mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
UPD: Start to implement a new elevation mechanism
This commit is contained in:
parent
50b1a86d01
commit
62fd46e72a
4 changed files with 50 additions and 224 deletions
|
|
@ -34,7 +34,7 @@ type
|
|||
procedure DeleteSubDirectory(const aFile: TFile);
|
||||
|
||||
protected
|
||||
function ProcessFile(aFile: TFile): Boolean;
|
||||
procedure ProcessFile(aFile: TFile);
|
||||
procedure ProcessList(aFiles: TFiles);
|
||||
function ShowError(sMessage: String): TFileSourceOperationUIResponse;
|
||||
procedure LogMessage(sMessage: String; logOptions: TLogOptions; logMsgType: TLogMsgType);
|
||||
|
|
@ -59,7 +59,7 @@ type
|
|||
implementation
|
||||
|
||||
uses
|
||||
DCOSUtils, DCStrUtils, uLng, uFileSystemUtil, uTrash, uAdministrator, uOSUtils
|
||||
DCOSUtils, DCStrUtils, uLng, uFileSystemUtil, uTrash
|
||||
{$IF DEFINED(MSWINDOWS)}
|
||||
, Windows, uFileUnlock, fFileUnlock
|
||||
{$ENDIF}
|
||||
|
|
@ -159,10 +159,8 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
function TFileSystemDeleteOperation.ProcessFile(aFile: TFile): Boolean;
|
||||
procedure TFileSystemDeleteOperation.ProcessFile(aFile: TFile);
|
||||
const
|
||||
ResponsesTrash: array[0..4] of TFileSourceOperationUIResponse
|
||||
= (fsourYes, fsourAll, fsourSkip, fsourSkipAll, fsourAbort);
|
||||
ResponsesError: array[0..3] of TFileSourceOperationUIResponse
|
||||
= (fsourRetry, fsourSkip, fsourSkipAll, fsourAbort);
|
||||
var
|
||||
|
|
@ -178,7 +176,6 @@ var
|
|||
ProcessInfo: TProcessInfoArray;
|
||||
{$ENDIF}
|
||||
begin
|
||||
Result := True;
|
||||
FileName := aFile.FullPath;
|
||||
|
||||
if FileIsReadOnly(aFile.Attributes) then
|
||||
|
|
@ -235,15 +232,8 @@ begin
|
|||
case FDeleteDirectly of
|
||||
fsoogNone:
|
||||
begin
|
||||
if AdministratorPrivileges then
|
||||
PossibleResponses:= ResponsesTrash
|
||||
else begin
|
||||
SetLength(PossibleResponses, Length(ResponsesTrash) + 1);
|
||||
Move(ResponsesTrash[0], PossibleResponses[0], SizeOf(ResponsesTrash));
|
||||
PossibleResponses[High(PossibleResponses)]:= fsourRetryAdmin;
|
||||
end;
|
||||
case AskQuestion(Format(rsMsgDelToTrashForce, [WrapTextSimple(FileName)]), '',
|
||||
PossibleResponses,
|
||||
[fsourYes, fsourAll, fsourSkip, fsourSkipAll, fsourAbort],
|
||||
fsourYes, fsourAbort) of
|
||||
fsourYes:
|
||||
RemoveDirectly:= fsoogYes;
|
||||
|
|
@ -261,8 +251,6 @@ begin
|
|||
end;
|
||||
fsourAbort:
|
||||
RaiseAbortOperation;
|
||||
fsourRetryAdmin:
|
||||
Exit(False);
|
||||
end;
|
||||
end;
|
||||
fsoogYes:
|
||||
|
|
@ -344,16 +332,8 @@ begin
|
|||
sQuestion+= LineEnding + mbSysErrorMessage(LastError);
|
||||
end;
|
||||
|
||||
if AdministratorPrivileges then
|
||||
begin
|
||||
SetLength(PossibleResponses, Length(ResponsesError));
|
||||
Move(ResponsesError[0], PossibleResponses[0], SizeOf(ResponsesError));
|
||||
end
|
||||
else begin
|
||||
SetLength(PossibleResponses, Length(ResponsesError) + 1);
|
||||
Move(ResponsesError[0], PossibleResponses[0], SizeOf(ResponsesError));
|
||||
PossibleResponses[High(PossibleResponses)]:= fsourRetryAdmin;
|
||||
end;
|
||||
SetLength(PossibleResponses, Length(ResponsesError));
|
||||
Move(ResponsesError[0], PossibleResponses[0], SizeOf(ResponsesError));
|
||||
{$IF DEFINED(MSWINDOWS)}
|
||||
if (Length(ProcessInfo) > 0) or (LastError = ERROR_ACCESS_DENIED) or (LastError = ERROR_SHARING_VIOLATION) then
|
||||
begin
|
||||
|
|
@ -370,8 +350,6 @@ begin
|
|||
FSkipErrors := True;
|
||||
fsourAbort:
|
||||
RaiseAbortOperation;
|
||||
fsourRetryAdmin:
|
||||
Exit(False);
|
||||
{$IF DEFINED(MSWINDOWS)}
|
||||
fsourUnlock:
|
||||
begin
|
||||
|
|
@ -398,11 +376,7 @@ begin
|
|||
FStatistics.CurrentFile := aFile.FullPath;
|
||||
UpdateStatistics(FStatistics);
|
||||
|
||||
if not ProcessFile(aFile) then
|
||||
begin
|
||||
Delete(Self, aFiles, CurrentFileIndex);
|
||||
Exit;
|
||||
end;
|
||||
ProcessFile(aFile);
|
||||
|
||||
with FStatistics do
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ function ExecCmdFork(sCmd: String): Boolean;
|
|||
function ExecCmdFork(sCmd: String; sParams: String; sStartPath: String = ''; bShowCommandLinePriorToExecute: Boolean = False;
|
||||
bTerm: Boolean = False; bKeepTerminalOpen: tTerminalEndindMode = termStayOpen): Boolean;
|
||||
|
||||
function ExecCmdAdmin(sCmd: String; sParams: String; sStartPath: String = ''): Boolean;
|
||||
function ExecCmdAdmin(const Exe: String; Args: array of String; sStartPath: String = ''): Boolean;
|
||||
{en
|
||||
Opens a file or URL in the user's preferred application
|
||||
@param(URL File name or URL)
|
||||
|
|
@ -408,23 +408,55 @@ begin
|
|||
end;
|
||||
{$ENDIF}
|
||||
|
||||
function ExecCmdAdmin(sCmd: String; sParams: String; sStartPath: String): Boolean;
|
||||
function ExecCmdAdmin(const Exe: String; Args: array of String; sStartPath: String): Boolean;
|
||||
{$IF DEFINED(MSWINDOWS)}
|
||||
var
|
||||
Index: Integer;
|
||||
AParams: String;
|
||||
begin
|
||||
sStartPath:= RemoveQuotation(sStartPath);
|
||||
AParams := EmptyStr;
|
||||
for Index := Low(Args) to High(Args) do
|
||||
AParams += QuoteDouble(Args[Index]) + ' ';
|
||||
|
||||
if sStartPath = '' then
|
||||
if sStartPath = EmptyStr then
|
||||
sStartPath:= mbGetCurrentDir;
|
||||
|
||||
sCmd:= NormalizePathDelimiters(sCmd);
|
||||
|
||||
Result:= ShellExecuteW(0, 'runas', PWideChar(UTF8Decode(sCmd)),
|
||||
PWideChar(UTF8Decode(sParams)),
|
||||
Result:= ShellExecuteW(0, 'runas', PWideChar(UTF8Decode(Exe)),
|
||||
PWideChar(UTF8Decode(AParams)),
|
||||
PWideChar(UTF8Decode(sStartPath)), SW_SHOW) > 32;
|
||||
end;
|
||||
{$ELSE}
|
||||
{$ELSEIF DEFINED(DARWIN)}
|
||||
var
|
||||
Index: Integer;
|
||||
ACommand: String;
|
||||
AParams: TStringArray;
|
||||
begin
|
||||
Result:= False;
|
||||
ACommand:= EscapeNoQuotes(Exe);
|
||||
for Index := Low(Args) to High(Args) do
|
||||
ACommand += ' ' + EscapeNoQuotes(Args[Index]);
|
||||
|
||||
SetLength(AParams, 7);
|
||||
AParams[0]:= '-e';
|
||||
AParams[1]:= 'on run argv';
|
||||
AParams[2]:= '-e';
|
||||
AParams[3]:= 'do shell script (item 1 of argv) with administrator privileges';
|
||||
AParams[4]:= '-e';
|
||||
AParams[5]:='end run';
|
||||
AParams[6]:= ACommand;
|
||||
|
||||
Result:= ExecuteCommand('/usr/bin/osascript', AParams, sStartPath);
|
||||
end;
|
||||
{$ELSE}
|
||||
var
|
||||
Index: Integer;
|
||||
AParams: TStringArray;
|
||||
begin
|
||||
SetLength(AParams, Length(Args) + 1);
|
||||
for Index := Low(Args) to High(Args) do
|
||||
AParams[Index + 1]:= Args[Index];
|
||||
AParams[0] := Exe;
|
||||
|
||||
Result:= ExecuteCommand('/usr/bin/pkexec', AParams, sStartPath);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,171 +0,0 @@
|
|||
{
|
||||
Double commander
|
||||
-------------------------------------------------------------------------
|
||||
Executes file operations with administrator privileges
|
||||
|
||||
Copyright (C) 2016-2019 Alexander Koblov (alexx2000@mail.ru)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
}
|
||||
|
||||
unit uAdministrator;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Forms, Dialogs, uFileSystemFileSource, uFile,
|
||||
uFileSystemDeleteOperation;
|
||||
|
||||
type
|
||||
EAccessDenied = class(Exception);
|
||||
|
||||
procedure ExecuteOperation(const FileList: String);
|
||||
|
||||
procedure Delete(Helper: TFileSystemDeleteOperation; Files: TFiles; Index: Integer);
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
uFileSource, uFileSourceOperationMessageBoxesUI, dmCommonData, uOSUtils,
|
||||
uGlobs, uGlobsPaths, uOperationsManager, uFileSourceOperation, DCXmlConfig,
|
||||
uFileSourceOperationOptions, uSpecialDir, DCOSUtils,
|
||||
uDCUtils;
|
||||
|
||||
type
|
||||
|
||||
{ TDummy }
|
||||
|
||||
TDummy = class
|
||||
procedure Finish(Operation: TFileSourceOperation; State: TFileSourceOperationState);
|
||||
end;
|
||||
|
||||
var
|
||||
Dummy: TDummy;
|
||||
FFileSourceOperationMessageBoxesUI: TFileSourceOperationMessageBoxesUI;
|
||||
|
||||
procedure Initialize;
|
||||
begin
|
||||
LoadPaths;
|
||||
LoadWindowsSpecialDir;
|
||||
InitGlobs;
|
||||
Dummy:= TDummy.Create;
|
||||
Application.CreateForm(TdmComData, dmComData); // common data
|
||||
FFileSourceOperationMessageBoxesUI := TFileSourceOperationMessageBoxesUI.Create;
|
||||
end;
|
||||
|
||||
procedure Delete(Xml: TXmlConfig);
|
||||
var
|
||||
Files: TFiles;
|
||||
ANode: TXmlNode;
|
||||
FileSource: IFileSource;
|
||||
Operation: TFileSystemDeleteOperation;
|
||||
begin
|
||||
ANode:= Xml.FindNode(Xml.RootNode, 'FileList');
|
||||
|
||||
if Assigned(ANode) then
|
||||
begin
|
||||
Files:= TFiles.Create(Xml.GetAttr(aNode, 'Path', EmptyStr));
|
||||
ANode:= ANode.FirstChild;
|
||||
while Assigned(ANode) do
|
||||
begin
|
||||
if ANode.CompareName('Item') = 0 then
|
||||
begin
|
||||
Files.Add(TFileSystemFileSource.CreateFileFromFile(Xml.GetAttr(aNode, 'Name', EmptyStr)));
|
||||
end;
|
||||
ANode:= ANode.NextSibling;
|
||||
end;
|
||||
|
||||
FileSource:= TFileSystemFileSource.GetFileSource;
|
||||
Operation:= FileSource.CreateDeleteOperation(Files) as TFileSystemDeleteOperation;
|
||||
|
||||
Operation.SkipErrors:= False;
|
||||
Operation.Recycle:= Xml.GetValue(Xml.RootNode, 'Recycle', False);
|
||||
Operation.SymLinkOption:= TFileSourceOperationOptionSymLink(Xml.GetValue(Xml.RootNode, 'SymLinkOption', Integer(fsooslNone)));
|
||||
Operation.DeleteReadOnly:= TFileSourceOperationOptionGeneral(Xml.GetValue(Xml.RootNode, 'DeleteReadOnly', Integer(fsoogNone)));
|
||||
|
||||
Operation.AddUserInterface(FFileSourceOperationMessageBoxesUI);
|
||||
Operation.AddStateChangedListener([fsosStopped], @Dummy.Finish);
|
||||
OperationsManager.AddOperation(Operation, True);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure Delete(Helper: TFileSystemDeleteOperation; Files: TFiles; Index: Integer);
|
||||
var
|
||||
I: Integer;
|
||||
Xml: TXmlConfig;
|
||||
ANode: TXmlNode;
|
||||
SubNode: TXmlNode;
|
||||
FileName: String;
|
||||
begin
|
||||
FileName:= GetTempFileName;
|
||||
Xml:= TXmlConfig.Create(FileName);
|
||||
Xml.SetValue(Xml.RootNode, 'Operation', 0);
|
||||
Xml.SetValue(Xml.RootNode, 'Recycle', Helper.Recycle);
|
||||
Xml.SetValue(Xml.RootNode, 'DeleteReadOnly', Integer(Helper.DeleteReadOnly));
|
||||
Xml.SetValue(Xml.RootNode, 'SymLinkOption', Integer(Helper.SymLinkOption));
|
||||
|
||||
ANode := Xml.AddNode(Xml.RootNode, 'FileList');
|
||||
Xml.SetAttr(ANode, 'Path', Files.Path);
|
||||
for I:= 0 to Index do
|
||||
begin
|
||||
SubNode := Xml.AddNode(ANode, 'Item');
|
||||
Xml.SetAttr(SubNode, 'Name', Files[I].FullPath);
|
||||
end;
|
||||
Xml.Save;
|
||||
Xml.Free;
|
||||
|
||||
ExecCmdAdmin(ParamStrU(0), '--config-dir=' + QuoteStr(gpCfgDir) +
|
||||
' ' +
|
||||
'--operation=' + QuoteStr(FileName));
|
||||
end;
|
||||
|
||||
procedure ExecuteOperation(const FileList: String);
|
||||
var
|
||||
Xml: TXmlConfig;
|
||||
begin
|
||||
try
|
||||
Initialize;
|
||||
|
||||
Xml:= TXmlConfig.Create(FileList, True);
|
||||
try
|
||||
case Xml.GetValue(Xml.RootNode, 'Operation', -1) of
|
||||
0: Delete(Xml);
|
||||
end;
|
||||
finally
|
||||
Xml.Free;
|
||||
mbDeleteFile(FileList);
|
||||
end;
|
||||
|
||||
Application.Run;
|
||||
|
||||
Halt(0);
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
ShowMessage(E.Message);
|
||||
Halt(1);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TDummy }
|
||||
|
||||
procedure TDummy.Finish(Operation: TFileSourceOperation; State: TFileSourceOperationState);
|
||||
begin
|
||||
Application.Terminate;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -26,7 +26,7 @@ implementation
|
|||
|
||||
uses
|
||||
Forms, Dialogs, SysUtils, uOSUtils, uDCUtils, uGlobsPaths, getopts, uDebug,
|
||||
uLng, uClipboard, uAdministrator, DCStrUtils;
|
||||
uLng, uClipboard, DCStrUtils;
|
||||
|
||||
function DecodePath(const Path: String): String;
|
||||
begin
|
||||
|
|
@ -42,7 +42,7 @@ procedure ProcessCommandLineParams;
|
|||
var
|
||||
Option: AnsiChar = #0;
|
||||
OptionIndex: LongInt = 0;
|
||||
Options: array[1..6] of TOption;
|
||||
Options: array[1..5] of TOption;
|
||||
OptionUnknown: String;
|
||||
begin
|
||||
FillChar(Options, SizeOf(Options), #0);
|
||||
|
|
@ -68,11 +68,6 @@ begin
|
|||
begin
|
||||
Name:= 'no-splash';
|
||||
end;
|
||||
with Options[6] do
|
||||
begin
|
||||
Name:= 'operation';
|
||||
Has_arg:= 1;
|
||||
end;
|
||||
FillChar(CommandLineParams, SizeOf(TCommandLineParams), #0);
|
||||
repeat
|
||||
try
|
||||
|
|
@ -108,10 +103,6 @@ begin
|
|||
begin
|
||||
CommandLineParams.NoSplash:= True;
|
||||
end;
|
||||
6:
|
||||
begin
|
||||
ExecuteOperation(ParamStrU(TrimQuotes(OptArg)));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
'L', 'l': CommandLineParams.LeftPath:= DecodePath(ParamStrU(OptArg));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue