diff options
| author | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2008-10-28 16:51:52 +0100 |
|---|---|---|
| committer | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2008-10-28 16:51:52 +0100 |
| commit | a67cd9193a6ac04d34c92c1a817fb0f5e44af30f (patch) | |
| tree | 888227edebb4844efb01cd70bcbfc459b09d2a56 | |
| parent | 4234ca950044c27a1b2fcc92f45d816ef217487f (diff) | |
| download | tuxcmd-0.6.54.tar.xz | |
Password callback support from all VFS modulesv0.6.54
Cleanup, remove unused dialogs
| -rw-r--r-- | .gitignore | 6 | ||||
| -rw-r--r-- | UConfig.pas | 4 | ||||
| -rw-r--r-- | UConnectionManager.pas | 6 | ||||
| -rw-r--r-- | UCore.pas | 503 | ||||
| -rw-r--r-- | UEngines.pas | 8 | ||||
| -rw-r--r-- | UGnome.pas | 36 | ||||
| -rw-r--r-- | ULogin.pas | 146 | ||||
| -rw-r--r-- | UMain.pas | 95 | ||||
| -rw-r--r-- | USearch.pas | 4 | ||||
| -rw-r--r-- | USetPassword.pas | 107 | ||||
| -rw-r--r-- | tuxcmd.dpr | 2 | ||||
| -rw-r--r-- | vfs/UVFSCore.pas | 112 | ||||
| -rw-r--r-- | vfs/uVFSprototypes.pas | 75 |
13 files changed, 453 insertions, 651 deletions
@@ -5,9 +5,12 @@ *.desk *.lpi *.kof -*.pas~ +*.*~ *.so +tuxcmd +fpcver.inc + Copy-rules.txt Copy.txt ToDo-NextGen.txt @@ -15,4 +18,3 @@ ToDo-Target-Next_Version.txt ToDo-VFS.txt ToDo-VFS2.txt Todo.txt -fpcver.inc diff --git a/UConfig.pas b/UConfig.pas index 9ef8917..343f281 100644 --- a/UConfig.pas +++ b/UConfig.pas @@ -25,8 +25,8 @@ uses Classes, ULocale; resourcestring ConstAppTitle = 'Tux Commander'; - ConstAboutVersion = '0.6.53-dev'; - ConstAboutBuildDate = '2008-10-12'; + ConstAboutVersion = '0.6.54-dev'; + ConstAboutBuildDate = '2008-10-28'; {$IFDEF FPC} {$INCLUDE fpcver.inc} diff --git a/UConnectionManager.pas b/UConnectionManager.pas index 90db1e7..86f3bd7 100644 --- a/UConnectionManager.pas +++ b/UConnectionManager.pas @@ -360,7 +360,7 @@ begin end; end; -function vfs_ask_password_callback(const AMessage: PChar; const default_user: PChar; const default_domain: PChar; flags: TVFSAskPasswordFlags; +function vfs_ask_password_callback(const AMessage: PChar; const default_user: PChar; const default_domain: PChar; const default_password: PChar; flags: TVFSAskPasswordFlags; username, password: PPChar; anonymous: PInteger; domain: PPChar; password_save: PVFSPasswordSave; user_data: Pointer): LongBool; cdecl; var ConnMgr: TFConnectionManager; @@ -387,7 +387,7 @@ begin if (password_save <> nil) { and ConfGnomeKeyringEnabled} then password_save^ := VFS_PASSWORD_SAVE_PERMANENTLY; end else begin // Show password dialog and continue in loop - Result := HandleVFSAskPasswordCallback(DialogParent, AMessage, default_user, default_domain, flags, username, password, anonymous, domain, password_save); + Result := HandleVFSAskPasswordCallback(DialogParent, AMessage, default_user, default_domain, default_password, flags, username, password, anonymous, domain, password_save); if ConnMgr is TFConnectionManager then begin ConnMgr.FSilenceError := Result = False; // Save password back to Connection Manager @@ -452,7 +452,7 @@ begin Application.ProcessMessages; FVFSAskPasswordTry := 0; - b := Engine.VFSOpenURI(UTF8ToStr(FActiveConnInfo.GetURI(False)), @vfs_ask_question_callback, @vfs_ask_password_callback, Self); + b := Engine.VFSOpenURI(UTF8ToStr(FActiveConnInfo.GetURI(False)), @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self); AFRemoteWait.Free; AFRemoteWait := nil; @@ -28,7 +28,42 @@ function MakeDirectory(ListView: TGTKListView; Engine: TPanelEngine; LeftPanel: procedure FindNextSelected(ListView: TGTKListView; DataList: TList; var Item1, Item2: string); procedure UnselectAll(ListView: TGTKListView; DataList: TList); -type TWorkerThread = class(TThread) + +type TVFSCallbackThread = class(TThread) + private + FThreadID: __pthread_t; + FCopyProgressFunc: TEngineProgressFunc; + procedure PrepareExecute; // Call this right after thread has been started + public + AEngine: TPanelEngine; + APlugin: TVFSPlugin; + + VFSCallbackEvent: TSimpleEvent; + VFSAskQuestion_Message: PChar; + VFSAskQuestion_Choices: PPChar; + VFSAskQuestion_Choice: PInteger; + VFSAskQuestion_Display: boolean; + + VFSAskPassword_Message: PChar; + VFSAskPassword_default_user: PChar; + VFSAskPassword_default_domain: PChar; + VFSAskPassword_default_password: PChar; + VFSAskPassword_flags: TVFSAskPasswordFlags; + VFSAskPassword_username: PPChar; + VFSAskPassword_password: PPChar; + VFSAskPassword_anonymous: PInteger; + VFSAskPassword_domain: PPChar; + VFSAskPassword_password_save: PVFSPasswordSave; + VFSAskPassword_Display: boolean; + VFSAskPassword_Result: LongBool; + + VFSCallbackCancelled: boolean; + + constructor Create(CreateSuspended: boolean); + destructor Destroy; override; + end; + + TWorkerThread = class(TVFSCallbackThread) private FCancelled: boolean; GUIMutex: TCriticalSection; @@ -119,15 +154,12 @@ type TWorkerThread = class(TThread) procedure CancelIt; end; - TOpenDirThread = class(TThread) + TOpenDirThread = class(TVFSCallbackThread) private - FThreadID: __pthread_t; function ChangeDir(Engine: TPanelEngine; Path: string; var SelItem: string; const AutoFallBack: boolean): integer; protected procedure Execute; override; public - AEngine: TPanelEngine; - xEngine: TVFSEngine; APath: string; ASelItem: string; AAutoFallBack: boolean; @@ -135,35 +167,12 @@ type TWorkerThread = class(TThread) ChDirResult, ListingResult, VFSOpenResult: integer; Finished, CancelIt: boolean; RunningTime: Int64; - APlugin: TVFSPlugin; AFullPath, AHighlightItem: string; - Password: string; - - VFSCallbackEvent: TSimpleEvent; - VFSAskQuestion_Message: PChar; - VFSAskQuestion_Choices: PPChar; - VFSAskQuestion_Choice: PInteger; - VFSAskQuestion_Display: boolean; - - VFSAskPassword_Message: PChar; - VFSAskPassword_default_user: PChar; - VFSAskPassword_default_domain: PChar; - VFSAskPassword_flags: TVFSAskPasswordFlags; - VFSAskPassword_username: PPChar; - VFSAskPassword_password: PPChar; - VFSAskPassword_anonymous: PInteger; - VFSAskPassword_domain: PPChar; - VFSAskPassword_password_save: PVFSPasswordSave; - VFSAskPassword_Display: boolean; - VFSAskPassword_Result: LongBool; - - VFSCallbackCancelled: boolean; constructor Create; destructor Destroy; override; end; - // Thread aware functions (also half-thread-safe) without any piece of GTK code procedure DeleteFilesWorker(SenderThread: TWorkerThread); procedure CopyFilesWorker(SenderThread: TWorkerThread); @@ -176,7 +185,6 @@ procedure DummyThreadWorker(SenderThread: TWorkerThread); // Classic functions - don't need progress window function CreateSymlink(const FileName, PossibleNewName: string; Engine: TPanelEngine) : boolean; function EditSymlink(const FileName: string; Engine: TPanelEngine) : boolean; -function HandleLogin(Parent: TComponent; Engine: TPanelEngine; UserName, Password: string): boolean; procedure GetDirSize(AListView: TGTKListView; Engine: TPanelEngine; DataList: TList; AllItems: boolean); @@ -233,9 +241,152 @@ var LeftLocalEngine, RightLocalEngine: TPanelEngine; implementation (********************************************************************************************************************************) uses SysUtils, DateUtils, StrUtils, UConfig, UDirDelete, UOverwrite, ULocale, - UNewDir, UFileAssoc, USymlink, UCoreClasses, ULogin, URemoteWait, UMain, UGnome; + UNewDir, UFileAssoc, USymlink, UCoreClasses, URemoteWait, UMain, UGnome; + + + + +(********************************************************************************************************************************) +constructor TVFSCallbackThread.Create(CreateSuspended: boolean); +begin + inherited Create(CreateSuspended); + APlugin := nil; + VFSCallbackEvent := TSimpleEvent.Create; + VFSAskQuestion_Display := False; + VFSAskPassword_Display := False; + VFSCallbackCancelled := False; +end; +destructor TVFSCallbackThread.Destroy; +begin + VFSCallbackEvent.Free; + inherited Destroy; +end; + +procedure TVFSCallbackThread.PrepareExecute; +begin + FThreadID := pthread_self; + VFSCallbackCancelled := False; +end; + +(********************************************************************************************************************************) +procedure vfs_ask_question_callback(const AMessage: PChar; const Choices: PPChar; choice: PInteger; cancel_choice: Integer; user_data: Pointer); cdecl; +var Thread: TVFSCallbackThread; +begin + Thread := user_data; + if (Thread = nil) { or (not (Thread is TVFSCallbackThread))} then begin + DebugMsg(['(ERROR): vfs_ask_question_callback: user_data is not TVFSCallbackThread, exiting.']); + Exit; + end; + + if pthread_self = Application.ThreadID then begin + DebugMsg(['!! (WARNING): vfs_ask_question_callback called from the main thread, expected spawn from a OpenDirThread']); + HandleVFSAskQuestionCallback(FMain.FWidget, AMessage, Choices, choice); + if (choice <> nil) then Thread.VFSCallbackCancelled := (choice^ < 0) or (choice^ = cancel_choice); + Exit; + end; + + if pthread_self = Thread.FThreadID then begin + DebugMsg(['******* vfs_ask_question_callback spawned, user_data = 0x', IntToHex(QWord(user_data), 16), ', ThreadID = 0x', IntToHex(pthread_self, 16)]); + Thread.VFSAskQuestion_Message := AMessage; + Thread.VFSAskQuestion_Choices := Choices; + Thread.VFSAskQuestion_Choice := choice; + Thread.VFSAskQuestion_Display := True; + Thread.VFSCallbackEvent.ResetEvent; + Thread.VFSCallbackEvent.WaitFor(INFINITE); + DebugMsg(['******* thread: resuming...']); + if (choice <> nil) then Thread.VFSCallbackCancelled := (choice^ < 0) or (choice^ = cancel_choice); + Exit; + end; + + DebugMsg(['!! (ERROR): vfs_ask_question_callback spawned neither from the main thread nor from active OpenDirThread, dropping the callback to prevent data corruption.']); + DebugMsg([' ThreadID = 0x', IntToHex(pthread_self, 16), ', OpenDirThread ID = 0x', IntToHex(Thread.FThreadID, 16), ', Application.ThreadID = 0x', IntToHex(Application.ThreadID, 16)]); +end; + +function vfs_ask_password_callback(const AMessage: PChar; const default_user: PChar; const default_domain: PChar; const default_password: PChar; flags: TVFSAskPasswordFlags; + username, password: PPChar; anonymous: PInteger; domain: PPChar; password_save: PVFSPasswordSave; + user_data: Pointer): LongBool; cdecl; +var Thread: TVFSCallbackThread; + def_pass: PChar; +begin + Result := False; + Thread := user_data; + if (Thread = nil) { or (not (Thread is TVFSCallbackThread))} then begin + DebugMsg(['(ERROR): vfs_ask_question_callback: user_data is not TVFSCallbackThread, exiting.']); + Exit; + end; + + def_pass := default_password; + + // Use stored password, if previously set + if ((flags and VFS_ASK_PASSWORD_ARCHIVE_MODE) = VFS_ASK_PASSWORD_ARCHIVE_MODE) and (password <> nil) and + (Thread.AEngine is TVFSEngine) and (Length((Thread.AEngine as TVFSEngine).Password) > 0) then + begin + if not (Thread.AEngine as TVFSEngine).PasswordUsed then begin + DebugMsg([' (II) vfs_ask_password_callback: reusing manually set password']); + password^ := g_strdup(PChar((Thread.AEngine as TVFSEngine).Password)); + (Thread.AEngine as TVFSEngine).PasswordUsed := True; + Result := True; + Thread.VFSCallbackCancelled := False; + Exit; + end else def_pass := PChar((Thread.AEngine as TVFSEngine).Password); + end; + + // Ask for password + if pthread_self = Application.ThreadID then begin + DebugMsg(['!! (WARNING): vfs_ask_password_callback called from the main thread, expected spawn from a OpenDirThread']); + Result := HandleVFSAskPasswordCallback(FMain.FWidget, AMessage, default_user, default_domain, def_pass, flags, username, password, anonymous, domain, password_save); + Thread.VFSCallbackCancelled := Result = False; + end else + if pthread_self = Thread.FThreadID then begin + DebugMsg(['******* vfs_ask_password_callback spawned, user_data = 0x', IntToHex(QWord(user_data), 16), ', ThreadID = 0x', IntToHex(pthread_self, 16), ', Application.ThreadID = 0x', IntToHex(Application.ThreadID, 16)]); + Thread.VFSAskPassword_Message := AMessage; + Thread.VFSAskPassword_default_user := default_user; + Thread.VFSAskPassword_default_domain := default_domain; + Thread.VFSAskPassword_default_password := def_pass; + Thread.VFSAskPassword_flags := flags; + Thread.VFSAskPassword_username := username; + Thread.VFSAskPassword_password := password; + Thread.VFSAskPassword_anonymous := anonymous; + Thread.VFSAskPassword_domain := domain; + Thread.VFSAskPassword_password_save := password_save; + Thread.VFSAskPassword_Display := True; + Thread.VFSAskPassword_Result := False; + Thread.VFSCallbackEvent.ResetEvent; + Thread.VFSCallbackEvent.WaitFor(INFINITE); + DebugMsg(['******* thread: resuming...']); + Result := Thread.VFSAskPassword_Result; + Thread.VFSCallbackCancelled := Result = False; + end else + begin + DebugMsg(['!! (ERROR): vfs_ask_password_callback spawned neither from the main thread nor from active OpenDirThread, dropping the callback to prevent data corruption.']); + DebugMsg([' ThreadID = 0x', IntToHex(pthread_self, 16), ', OpenDirThread ID = 0x', IntToHex(Thread.FThreadID, 16), ', Application.ThreadID = 0x', IntToHex(Application.ThreadID, 16)]); + end; + + // Save password back to the engine + if ((flags and VFS_ASK_PASSWORD_ARCHIVE_MODE) = VFS_ASK_PASSWORD_ARCHIVE_MODE) and + Result and (password <> nil) and (strlen(password^) > 0) and + (Thread.AEngine is TVFSEngine) then + begin + (Thread.AEngine as TVFSEngine).Password := string(password^); + (Thread.AEngine as TVFSEngine).PasswordUsed := True; + end; +end; + +function vfs_progress_callback(position, max: Int64; user_data: Pointer): LongBool; cdecl; +begin +// DebugMsg(['VFSCopyCallBackFunc called (iPos = ', iPos, ', iMax = ', iMax, ')']); + Result := True; + if not Assigned(user_data) then Exit; + + if Assigned(TVFSCallbackThread(user_data).FCopyProgressFunc) then + try + Result := TVFSCallbackThread(user_data).FCopyProgressFunc(user_data, position); + except + on E: Exception do DebugMsg(['*** Exception raised in vfs_progress_callback(position=', position, ', max=', max, ', user_data=', user_data, '): (', E.ClassName, '): ', E.Message]); + end; +end; (********************************************************************************************************************************) procedure ClearListData(List: TList); @@ -586,6 +737,10 @@ end; Exit; end; case ErrorType of + 0 : begin + CancelIt; + Exit; + end; 1 : s := LANGMemoryAllocationFailed; 2 : s := LANGCannotOpenSourceFile; 3 : s := LANGCannotOpenDestinationFile; @@ -598,8 +753,9 @@ end; else s2 := LANGMoveError; if ErrorType <> 1 then s3 := StrToUTF8(FileName) else s3 := ''; + case ShowDirDeleteDialog(3, s, s3, GetErrorString(ErrorNum), s2) of - 0 : begin // Cancel button + 0, 252 : begin // Cancel button, Escape Result := False; CancelIt; end; @@ -704,28 +860,48 @@ var DefResponse: integer; // Global variables for this function begin Result := False; try - with SenderThread do begin - if ((SrcEngine is TLocalTreeEngine) and (DestEngine is TLocalTreeEngine)) or - ((SrcEngine is TLocalTreeEngine) and (not (DestEngine is TLocalTreeEngine))) - then Result := DestEngine.CopyFileIn(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ProgressFunc, @CopyFilesWorker_ErrorFunc, Append) else -// DebugMsg(['2 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']); - if (not (SrcEngine is TLocalTreeEngine)) and (DestEngine is TLocalTreeEngine) - then Result := SrcEngine.CopyFileOut(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ProgressFunc, @CopyFilesWorker_ErrorFunc, Append) - // both files are on different engines, we will have to handle the copy process ourselves - else Result := ManualCopyFile(SourceFile, DestFile, Append); -// DebugMsg(['3 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']); - - // If size differs, then delete target file - if (not Append) and (not Result) then begin -// DebugMsg(['4 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']); - DataSrc := SrcEngine.GetFileInfoSL(SourceFile); - if DataSrc = nil then Exit; - DataDest := DestEngine.GetFileInfoSL(DestFile); - if DataDest = nil then Exit; - if DataSrc^.Size <> DataDest^.Size then DestEngine.Remove(DestFile); + with SenderThread do begin + AEngine := nil; + FCopyProgressFunc := CopyFilesWorker_ProgressFunc; + + // local -> local + if (SrcEngine is TLocalTreeEngine) and (DestEngine is TLocalTreeEngine) + then Result := DestEngine.CopyFileIn(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ProgressFunc, @CopyFilesWorker_ErrorFunc, Append) + else + + // from local engine to VFS engine + if (SrcEngine is TLocalTreeEngine) and (DestEngine is TVFSEngine) then + begin + AEngine := DestEngine; + Result := (DestEngine as TVFSEngine).CopyFileInEx(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ErrorFunc, Append, + @vfs_ask_question_callback, @vfs_ask_password_callback, @vfs_progress_callback, SenderThread); + end else + + // from VFS engine to local (most common use) + if (SrcEngine is TVFSEngine) and (DestEngine is TLocalTreeEngine) then + begin + AEngine := SrcEngine; + Result := (SrcEngine as TVFSEngine).CopyFileOutEx(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ErrorFunc, Append, + @vfs_ask_question_callback, @vfs_ask_password_callback, @vfs_progress_callback, SenderThread); + end + + // VFS to VFS (not supported yet) + else + begin + AEngine := SrcEngine; + Result := ManualCopyFile(SourceFile, DestFile, Append); + end; + AEngine := nil; + + // Copy OK? (check size, otherwise delete target file) + if (not Append) and (not Result) then begin + DataSrc := SrcEngine.GetFileInfoSL(SourceFile); + if DataSrc = nil then Exit; + DataDest := DestEngine.GetFileInfoSL(DestFile); + if DataDest = nil then Exit; + if DataSrc^.Size <> DataDest^.Size then DestEngine.Remove(DestFile); + end; end; - end; -// DebugMsg(['(II) CopyFilesWorker.LocalCopyFile: finished']); except on E: Exception do DebugMsg(['*** Exception raised in LocalCopyFile(SourceFile=', SourceFile, ', DestFile=', DestFile, ', Append=', Append, '): (', E.ClassName, '): ', E.Message]); end; @@ -2090,6 +2266,32 @@ begin Application.ProcessMessages; // DebugMsg(['After refresh']); + + // VFS callbacks + if SenderThread.VFSAskQuestion_Display then begin + SenderThread.VFSAskQuestion_Display := False; + DebugMsg(['ProcessProgressThread - Main thread: displaying question dialog']); + HandleVFSAskQuestionCallback(ProgressForm.FWidget, SenderThread.VFSAskQuestion_Message, SenderThread.VFSAskQuestion_Choices, SenderThread.VFSAskQuestion_Choice); + SenderThread.VFSCallbackEvent.SetEvent; + end; + if SenderThread.VFSAskPassword_Display then begin + SenderThread.VFSAskPassword_Display := False; + DebugMsg(['ProcessProgressThread - Main thread: displaying password prompt']); + SenderThread.VFSAskPassword_Result := HandleVFSAskPasswordCallback(ProgressForm.FWidget, + SenderThread.VFSAskPassword_Message, + SenderThread.VFSAskPassword_default_user, + SenderThread.VFSAskPassword_default_domain, + SenderThread.VFSAskPassword_default_password, + SenderThread.VFSAskPassword_flags, + SenderThread.VFSAskPassword_username, + SenderThread.VFSAskPassword_password, + SenderThread.VFSAskPassword_anonymous, + SenderThread.VFSAskPassword_domain, + SenderThread.VFSAskPassword_password_save); + SenderThread.VFSCallbackEvent.SetEvent; + end; + + try if SenderThread.FDialogShowDirDelete then begin AFDirDelete := nil; @@ -2182,6 +2384,7 @@ end; (********************************************************************************************************************************) procedure TWorkerThread.Execute; begin + PrepareExecute; if Assigned(WorkerProcedure) then WorkerProcedure(Self); end; @@ -2295,6 +2498,7 @@ begin if DirDeleteCaption = '' then FDirDeleteCaption := LANGRemoveDirectory else FDirDeleteCaption := DirDeleteCaption; FDialogShowDirDelete := True; + FCallbackLockEvent.ResetEvent; FCallbackLockEvent.WaitFor(INFINITE); Result := FDialogResultDirDelete; end; @@ -2311,6 +2515,7 @@ begin FOverwriteSourceFile := SourceFile; FOverwriteDestFile := DestFile; FDialogShowOverwrite := True; + FCallbackLockEvent.ResetEvent; FCallbackLockEvent.WaitFor(INFINITE); Result := FDialogResultOverwrite; end; @@ -2321,6 +2526,7 @@ begin FNewDirLabel := LabelCaption; FNewDirEdit := Edit; FDialogShowNewDir := True; + FCallbackLockEvent.ResetEvent; FCallbackLockEvent.WaitFor(INFINITE); Result := FDialogResultNewDir; end; @@ -2333,6 +2539,7 @@ begin FMsgBoxDefault := Default; FMsgBoxEscape := Escape; FDialogShowMsgBox := True; + FCallbackLockEvent.ResetEvent; FCallbackLockEvent.WaitFor(INFINITE); Result := FDialogResultMsgBox; end; @@ -2468,29 +2675,6 @@ end; (********************************************************************************************************************************) (********************************************************************************************************************************) -function HandleLogin(Parent: TComponent; Engine: TPanelEngine; UserName, Password: string): boolean; -var b: boolean; -begin - Result := False; - b := Engine.Login(UserName, Password) = cVFS_OK; - if not b then - repeat - try - FLogin := TFLogin.Create(Parent); - b := FLogin.Run = mbOK; - UserName := FLogin.UserEntry.Text; - Password := FLogin.PasswordEntry.Text; - finally - FLogin.Free; - end; - if not b then Exit; - if b then b := Engine.Login(UserName, Password) = cVFS_OK; - until b; - Result := True; -end; - -(********************************************************************************************************************************) -(********************************************************************************************************************************) procedure TGetDirSizeThread.Execute; begin Result := Engine.GetDirSize(Path); @@ -2606,147 +2790,14 @@ begin ListingResult := 0; VFSOpenResult := 0; RunningTime := 0; - APlugin := nil; - xEngine := nil; - Password := ''; - VFSCallbackEvent := TSimpleEvent.Create; - VFSAskQuestion_Display := False; - VFSAskPassword_Display := False; - VFSCallbackCancelled := False; end; destructor TOpenDirThread.Destroy; begin -{ - if (APlugin <> nil) and (xEngine <> nil) then - try - xEngine.Free; - except - on E: Exception do DebugMsg(['*** TOpenDirThread.Destroy -Exception: ', E.Message]); - end; -} - VFSCallbackEvent.Free; inherited Destroy; end; -procedure TOpenDirThread.Execute; -var tt: TDateTime; -begin - FThreadID := pthread_self; - VFSCallbackCancelled := False; - try -// Writeln('execute.'); - tt := Now; - try -// WriteLn('x1'); - if APlugin <> nil then begin - xEngine := TVFSEngine.Create(APlugin); - xEngine.ParentEngine := AEngine; - xEngine.ArchiveMode := True; - AEngine.LastHighlightItem := AHighlightItem; - xEngine.SavePath := AEngine.Path; - AEngine := xEngine; - if Length(Password) > 0 then (xEngine as TVFSEngine).Password := Password; - VFSOpenResult := (xEngine as TVFSEngine).VFSOpenEx(AFullPath); - end else VFSOpenResult := 0; -// WriteLn('x2'); - - if (VFSOpenResult = 0) and (not CancelIt) then begin -// WriteLn('x3'); - ChDirResult := ChangeDir(AEngine, APath, ASelItem, AAutoFallBack); -// WriteLn('x4'); - - if (ChDirResult = 0) and (not CancelIt) then begin -// WriteLn('x5'); - ListingResult := AEngine.GetListing(ADirList, ConfShowDotFiles); -// WriteLn('x6'); - end; -// WriteLn('x7'); - end; - except - on E: Exception do DebugMsg(['*** TOpenDirThread.Execute -Exception: ', E.Message]); - end; - RunningTime := MilliSecondsBetween(tt, Now); -// WriteLn('x8'); - finally - Finished := True; - end; -{ except - on E: Exception do DebugMsg(['*** Exception raised in TOpenDirThread.Execute (', E.ClassName, '): ', E.Message]); - end; } -end; - (********************************************************************************************************************************) -procedure vfs_ask_question_callback(const AMessage: PChar; const Choices: PPChar; choice: PInteger; cancel_choice: Integer; user_data: Pointer); cdecl; -var Thread: TOpenDirThread; -begin - Thread := user_data; - - if pthread_self = Application.ThreadID then begin - DebugMsg(['!! (WARNING): vfs_ask_question_callback called from the main thread, expected spawn from a OpenDirThread']); - HandleVFSAskQuestionCallback(FMain.FWidget, AMessage, Choices, choice); - if (choice <> nil) and (Thread <> nil) and (Thread is TOpenDirThread) then Thread.VFSCallbackCancelled := (choice^ < 0) or (choice^ = cancel_choice); - Exit; - end; - - if (Thread <> nil) and (Thread is TOpenDirThread) and (pthread_self = Thread.FThreadID) then begin - DebugMsg(['******* vfs_ask_question_callback spawned, user_data = 0x', IntToHex(QWord(user_data), 16), ', ThreadID = 0x', IntToHex(pthread_self, 16)]); - Thread.VFSAskQuestion_Message := AMessage; - Thread.VFSAskQuestion_Choices := Choices; - Thread.VFSAskQuestion_Choice := choice; - Thread.VFSAskQuestion_Display := True; - Thread.VFSCallbackEvent.WaitFor(INFINITE); - DebugMsg(['******* thread: resuming...']); - if (choice <> nil) then Thread.VFSCallbackCancelled := (choice^ < 0) or (choice^ = cancel_choice); - Exit; - end; - - DebugMsg(['!! (ERROR): vfs_ask_question_callback spawned neither from the main thread nor from active OpenDirThread, dropping the callback to prevent data corruption.']); - if (Thread <> nil) and (Thread is TOpenDirThread) - then DebugMsg([' ThreadID = 0x', IntToHex(pthread_self, 16), ', OpenDirThread ID = 0x', IntToHex(Thread.FThreadID, 16), ', Application.ThreadID = 0x', IntToHex(Application.ThreadID, 16)]); -end; - -function vfs_ask_password_callback(const AMessage: PChar; const default_user: PChar; const default_domain: PChar; flags: TVFSAskPasswordFlags; - username, password: PPChar; anonymous: PInteger; domain: PPChar; password_save: PVFSPasswordSave; - user_data: Pointer): LongBool; cdecl; -var Thread: TOpenDirThread; -begin - Thread := user_data; - - if pthread_self = Application.ThreadID then begin - DebugMsg(['!! (WARNING): vfs_ask_password_callback called from the main thread, expected spawn from a OpenDirThread']); - Result := HandleVFSAskPasswordCallback(FMain.FWidget, AMessage, default_user, default_domain, flags, username, password, anonymous, domain, password_save); - if (Thread <> nil) and (Thread is TOpenDirThread) then Thread.VFSCallbackCancelled := Result = False; - Exit; - end; - - if (Thread <> nil) and (Thread is TOpenDirThread) and (pthread_self = Thread.FThreadID) then begin - DebugMsg(['******* vfs_ask_password_callback spawned, user_data = 0x', IntToHex(QWord(user_data), 16), ', ThreadID = 0x', IntToHex(pthread_self, 16), ', Application.ThreadID = 0x', IntToHex(Application.ThreadID, 16)]); - Thread.VFSAskPassword_Message := AMessage; - Thread.VFSAskPassword_default_user := default_user; - Thread.VFSAskPassword_default_domain := default_domain; - Thread.VFSAskPassword_flags := flags; - Thread.VFSAskPassword_username := username; - Thread.VFSAskPassword_password := password; - Thread.VFSAskPassword_anonymous := anonymous; - Thread.VFSAskPassword_domain := domain; - Thread.VFSAskPassword_password_save := password_save; - Thread.VFSAskPassword_Display := True; - Thread.VFSAskPassword_Result := False; - Thread.VFSCallbackEvent.WaitFor(INFINITE); - DebugMsg(['******* thread: resuming...']); - Result := Thread.VFSAskPassword_Result; - Thread.VFSCallbackCancelled := Result = False; - Exit; - end; - - DebugMsg(['!! (ERROR): vfs_ask_password_callback spawned neither from the main thread nor from active OpenDirThread, dropping the callback to prevent data corruption.']); - if (Thread <> nil) and (Thread is TOpenDirThread) - then DebugMsg([' ThreadID = 0x', IntToHex(pthread_self, 16), ', OpenDirThread ID = 0x', IntToHex(Thread.FThreadID, 16), ', Application.ThreadID = 0x', IntToHex(Application.ThreadID, 16)]); - Result := False; -end; - - function TOpenDirThread.ChangeDir(Engine: TPanelEngine; Path: string; var SelItem: string; const AutoFallBack: boolean): integer; procedure GoUp(var NewPath: string); @@ -2778,13 +2829,13 @@ begin // AutoFallback loop if Engine is TVFSEngine - then Error := (Engine as TVFSEngine).ChangeDirEx(APath, @vfs_ask_question_callback, @vfs_ask_password_callback, Self) + then Error := (Engine as TVFSEngine).ChangeDirEx(APath, @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self) else Error := Engine.ChangeDir(APath); while AutoFallback and (Error <> 0) and (APath <> '/') do begin GoUp(APath); if Engine is TVFSEngine - then Error := (Engine as TVFSEngine).ChangeDirEx(APath, @vfs_ask_question_callback, @vfs_ask_password_callback, Self) + then Error := (Engine as TVFSEngine).ChangeDirEx(APath, @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self) else Error := Engine.ChangeDir(APath); end; // Going on... @@ -2803,6 +2854,38 @@ begin end; end; +procedure TOpenDirThread.Execute; +var tt: TDateTime; + xEngine: TVFSEngine; +begin + PrepareExecute; + try + tt := Now; + try + if APlugin <> nil then begin + xEngine := TVFSEngine.Create(APlugin); + xEngine.ParentEngine := AEngine; + xEngine.ArchiveMode := True; + AEngine.LastHighlightItem := AHighlightItem; + xEngine.SavePath := AEngine.Path; + // AEngine must be set here since VFSOpenEx callbacks will reference it + AEngine := xEngine; + VFSOpenResult := (AEngine as TVFSEngine).VFSOpenEx(AFullPath, @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self); + end else VFSOpenResult := 0; + + if (VFSOpenResult = 0) and (not CancelIt) then begin + ChDirResult := ChangeDir(AEngine, APath, ASelItem, AAutoFallBack); + if (ChDirResult = 0) and (not CancelIt) then + ListingResult := AEngine.GetListing(ADirList, ConfShowDotFiles); + end; + except + on E: Exception do DebugMsg(['*** Exception raised in TOpenDirThread.Execute (', E.ClassName, '): ', E.Message]); + end; + RunningTime := MilliSecondsBetween(tt, Now); + finally + Finished := True; + end; +end; (********************************************************************************************************************************) (********************************************************************************************************************************) diff --git a/UEngines.pas b/UEngines.pas index 8e8a0b8..903bec3 100644 --- a/UEngines.pas +++ b/UEngines.pas @@ -113,7 +113,6 @@ type function GetPath: string; virtual; abstract; procedure SetPath(Value: string); virtual; abstract; function GetPrefix: string; virtual; abstract; - function Login(Username, Password: string): integer; virtual; abstract; // Copy-related routines function GetBlockSize: guint32; virtual; abstract; @@ -166,7 +165,6 @@ type function GetPath: string; override; procedure SetPath(Value: string); override; function GetPrefix: string; override; - function Login(Username, Password: string): integer; override; function GetBlockSize: guint32; override; procedure SetBlockSize(Value: guint32); override; @@ -1075,12 +1073,6 @@ begin end; (********************************************************************************************************************************) -function TLocalTreeEngine.Login(Username, Password: string): integer; -begin - Result := 0; -end; - -(********************************************************************************************************************************) function TLocalTreeEngine.TwoSameFiles(const Path1, Path2: string): boolean; var st1, st2: Pstat64; begin @@ -157,6 +157,7 @@ function HandleVFSAskPasswordCallback(DialogParent: PGtkWidget; const AMessage: PChar; const default_user: PChar; const default_domain: PChar; + const default_password: PChar; flags: TVFSAskPasswordFlags; username: PPChar; password: PPChar; @@ -1234,7 +1235,7 @@ procedure HandleVFSAskQuestionCallback(DialogParent: PGtkWidget; var dialog: PGtkWidget; secondary: PChar; primary: PChar; - count, len: integer; + count, len, res: integer; begin len := 0; secondary := nil; @@ -1257,6 +1258,7 @@ begin if primary <> nil then g_free (primary); // gtk_window_set_title (PGtkWindow(dialog), 'VFS Question'); + gtk_window_set_title (PGtkWindow(dialog), ''); // First count the items in the list then add the buttons in reverse order while (TOpenPCharArray(choices)[len] <> nil) @@ -1265,7 +1267,8 @@ begin for count := len - 1 downto 0 do gtk_dialog_add_button (PGtkDialog(dialog), TOpenPCharArray(choices)[count], count); - choice^ := gtk_dialog_run(PGtkDialog(Dialog)); + res := gtk_dialog_run (PGtkDialog(Dialog)); + if choice <> nil then choice^ := res; gtk_widget_destroy (PGtkWidget(Dialog)); end; @@ -1289,7 +1292,7 @@ begin end; end; -function pw_dialog_input_is_valid (priv: PVFSAskPasswordCallbackPriv): boolean; +function pw_dialog_input_is_valid(priv: PVFSAskPasswordCallbackPriv): boolean; begin Result := entry_has_input(priv^.username_entry) and entry_has_input(priv^.domain_entry) and @@ -1313,7 +1316,7 @@ begin gtk_dialog_set_response_sensitive(GTK_DIALOG (priv^.dialog), GTK_RESPONSE_OK, is_valid); end; -procedure pw_dialog_cycle_focus (widget: PGtkWidget; priv: PVFSAskPasswordCallbackPriv); cdecl; +procedure pw_dialog_cycle_focus(widget: PGtkWidget; priv: PVFSAskPasswordCallbackPriv); cdecl; var next_widget: PGtkWidget; begin next_widget := nil; @@ -1327,6 +1330,12 @@ begin then gtk_window_activate_default(GTK_WINDOW(priv^.dialog)); end; +procedure unmask_checkbox_toggled(togglebutton: PGtkToggleButton; priv: PVFSAskPasswordCallbackPriv); cdecl; +var active: gboolean; +begin + active := gtk_toggle_button_get_active(togglebutton); + if priv^.password_entry <> nil then gtk_entry_set_visibility(priv^.password_entry, active); +end; // The following code has been stolen from gtkmountoperation.c // Copyright (C) Christian Kellner <gicmo@gnome.org> @@ -1334,6 +1343,7 @@ function HandleVFSAskPasswordCallback(DialogParent: PGtkWidget; const AMessage: PChar; const default_user: PChar; const default_domain: PChar; + const default_password: PChar; flags: TVFSAskPasswordFlags; username: PPChar; password: PPChar; @@ -1370,6 +1380,7 @@ var widget: PGtkWidget; remember_box: PGtkWidget; priv: TVFSAskPasswordCallbackPriv; s: PChar; + unmask_checkbox: PGtkWidget; begin FillChar(priv, sizeof(priv), 0); radio_forget := nil; @@ -1380,6 +1391,7 @@ begin priv.dialog := PGtkDialog(widget); window := PGtkWindow(widget); // gtk_window_set_title (window, 'VFS Question'); + gtk_window_set_title (window, ''); // Set the dialog up with HIG properties gtk_dialog_set_has_separator (priv.dialog, False); @@ -1391,9 +1403,13 @@ begin gtk_window_set_resizable (window, False); // gtk_window_set_icon_name (window, 'gtk-dialog-authentication'); + if (flags and VFS_ASK_PASSWORD_ARCHIVE_MODE) = VFS_ASK_PASSWORD_ARCHIVE_MODE + then s := GTK_STOCK_OK + else s := PChar(LANGConnMgr_ConnectButton); + gtk_dialog_add_buttons (priv.dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - PChar(LANGConnMgr_ConnectButton), GTK_RESPONSE_OK, + s, GTK_RESPONSE_OK, nil); gtk_dialog_set_default_response (priv.dialog, GTK_RESPONSE_OK); @@ -1463,10 +1479,19 @@ begin end; if (flags and VFS_ASK_PASSWORD_NEED_PASSWORD) = VFS_ASK_PASSWORD_NEED_PASSWORD then begin priv.password_entry := table_add_entry (table, rows, '_Password:', nil, @priv); + if (default_password <> nil) and (strlen(default_password) > 0) then + gtk_entry_set_text(priv.password_entry, default_password); // Inc(Rows); gtk_entry_set_visibility (GTK_ENTRY (priv.password_entry), FALSE); end; + if (flags and VFS_ASK_PASSWORD_ARCHIVE_MODE) = VFS_ASK_PASSWORD_ARCHIVE_MODE then begin + unmask_checkbox := gtk_check_button_new_with_mnemonic (PChar(LANGFSetPassword_ShowPasswordCheckButton)); + g_object_set(G_OBJECT(unmask_checkbox), 'can-focus', 0, nil); + gtk_box_pack_start (GTK_BOX (vbox), unmask_checkbox, FALSE, FALSE, 0); + g_signal_connect (unmask_checkbox, 'toggled', G_CALLBACK (@unmask_checkbox_toggled), @priv); + end; + if ((flags and VFS_ASK_PASSWORD_SAVING_SUPPORTED) = VFS_ASK_PASSWORD_SAVING_SUPPORTED) or ((flags and VFS_ASK_PASSWORD_SAVE_INTERNAL) = VFS_ASK_PASSWORD_SAVE_INTERNAL) then begin @@ -1515,6 +1540,7 @@ begin if gtk_toggle_button_get_active(PGtkToggleButton(radio_remember)) then password_save^ := VFS_PASSWORD_SAVE_PERMANENTLY; end; end; + gtk_widget_destroy (PGtkWidget(priv.dialog)); end; diff --git a/ULogin.pas b/ULogin.pas deleted file mode 100644 index 8dbf5bb..0000000 --- a/ULogin.pas +++ /dev/null @@ -1,146 +0,0 @@ -(* - Tux Commander - ULogin - Login dialog - Copyright (C) 2004 Tomas Bzatek <tbzatek@users.sourceforge.net>
- Check for updates on tuxcmd.sourceforge.net
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*) -unit ULogin; - -interface - -uses - glib2, gdk2, gtk2, pango, SysUtils, Types, Classes, Variants, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKConsts, GTKView, - GTKUtils, GTKDialogs, GTKPixbuf, GTKClasses, GTKMenus, - UCoreClasses; - -type - TFLogin = class(TGTKDialog) - TitleFrame: TGTKFrame; - TitleLabel: TGTKLabel; - TitleEventBox: TGTKEventBox; - TitleIcon: TGTKImage; - TitleHBox: TGTKHBox; - Table: TGTKTable; - Label3, Label4: TGTKLabel; - UserEntry, PasswordEntry: TGTKEntry; - ExperimentalWarningLabel: TGTKLabel; - ExperimentalWarningIcon: TGTKImage; - AnonymousCheckButton: TGTKCheckButton; - HBox4: TGTKHBox; - procedure FormCreate(Sender: TObject); override; - procedure FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); - procedure AnonymousCheckButtonToggled(Sender: TObject); - end; - -var - FLogin: TFLogin; - -implementation - -uses ULocale; - - -procedure TFLogin.FormCreate(Sender: TObject); -begin - SetDefaultSize(200, 150); - Caption := LANGConnLogin_Caption; - Buttons := [mbOK, mbCancel]; - DefaultButton := mbOK; - ShowSeparator := False; - TitleEventBox := TGTKEventBox.Create(Self); - TitleLabel := TGTKLabel.Create(Self); - TitleLabel.Caption := Format('<span size="x-large" weight="ultrabold">%s</span>', [LANGConnLogin_Login]); - TitleLabel.UseMarkup := True; - TitleLabel.XAlign := 0; - TitleLabel.XPadding := 0; - TitleLabel.YPadding := 3; - TitleEventBox.ControlState := csPrelight; - TitleFrame := TGTKFrame.CreateWithoutLabel(Self); - TitleFrame.ShadowType := stShadowOut; - TitleIcon := TGTKImage.Create(Self); - TitleIcon.SetFromStock('gtk-dialog-authentication', isLargeToolbar); - TitleHBox := TGTKHBox.Create(Self); - TitleHBox.Homogeneous := False; - TitleHBox.AddControlEx(TGTKEventBox.Create(Self), False, False, 5); - TitleHBox.AddControlEx(TitleIcon, False, False, 0); - TitleHBox.AddControlEx(TitleLabel, True, True, 10); - TitleEventBox.AddControl(TitleHBox); - TitleFrame.AddControl(TitleEventBox); - ClientArea.AddControlEx(TitleFrame, False, True, 0); - - HBox4 := TGTKHBox.Create(Self); - HBox4.Homogeneous := False; - ExperimentalWarningLabel := TGTKLabel.Create(Self); - ExperimentalWarningLabel.Caption := LANGConnLogin_ExperimentalWarningLabelCaption; - ExperimentalWarningLabel.UseMarkup := True; - ExperimentalWarningLabel.LineWrap := True; - ExperimentalWarningIcon := TGTKImage.Create(Self); - ExperimentalWarningIcon.SetFromStock('gtk-dialog-authentication', isDialog); - HBox4.AddControlEx(ExperimentalWarningIcon, False, False, 7); - HBox4.AddControlEx(ExperimentalWarningLabel, True, True, 7); - HBox4.AddControlEx(TGTKEventBox.Create(Self), False, False, 8); - - - Table := TGTKTable.Create(Self); - Table.BorderWidth := 20; - ClientArea.AddControlEx(Table, True, True, 0); - Table.AddControlEx(0, 0, 2, 1, HBox4, [taoShrink, taoFill], [taoShrink, taoExpand, taoFill], 5, 0); - Table.AddControlEx(0, 1, 2, 1, TGTKEventBox.Create(Self), [taoShrink, taoFill], [taoShrink], 5, 10); - Label3 := TGTKLabel.Create(Self); - Label3.XAlign := 1; - Label3.Caption := LANGConnLogin_Username; - UserEntry := TGTKEntry.Create(Self); - Label3.FocusControl := UserEntry; - Label3.UseUnderline := True; - Label4 := TGTKLabel.Create(Self); - Label4.XAlign := 1; - Label4.Caption := LANGConnLogin_Password; - PasswordEntry := TGTKEntry.Create(Self); - PasswordEntry.Visibility := False; - Label4.FocusControl := PasswordEntry; - Label4.UseUnderline := True; - AnonymousCheckButton := TGTKCheckButton.CreateWithLabel(Self, LANGConnLogin_AnonymousCheckButton); - AnonymousCheckButton.OnToggled := AnonymousCheckButtonToggled; - AnonymousCheckButton.Checked := False; - Table.AddControlEx(0, 2, 1, 1, Label3, [taoShrink, taoFill], [taoShrink, taoExpand, taoFill], 5, 2); - Table.AddControlEx(1, 2, 1, 1, UserEntry, [taoExpand, taoFill], [taoShrink], 5, 2); - Table.AddControlEx(0, 3, 1, 1, Label4, [taoShrink, taoFill], [taoShrink, taoExpand, taoFill], 5, 2); - Table.AddControlEx(1, 3, 1, 1, PasswordEntry, [taoExpand, taoFill], [taoShrink], 5, 2); - Table.AddControlEx(0, 4, 2, 1, AnonymousCheckButton, [taoExpand, taoFill], [taoShrink], 20, 2); - - UserEntry.SetFocus; - OnKeyDown := FormKeyDown; -end; - -procedure TFLogin.FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); -begin - case Key of - GDK_RETURN, GDK_KP_ENTER: ModalResult := mbOK; - GDK_ESCAPE: ModalResult := mbCancel; - end; -end; - -procedure TFLogin.AnonymousCheckButtonToggled(Sender: TObject); -begin - Label3.Enabled := not AnonymousCheckButton.Checked; - Label4.Enabled := not AnonymousCheckButton.Checked; - UserEntry.Enabled := not AnonymousCheckButton.Checked; - PasswordEntry.Enabled := not AnonymousCheckButton.Checked; -end; - - -end. -
@@ -236,7 +236,6 @@ type procedure NewTabInternal(LeftPanel: boolean; _Engine: TPanelEngine; _Path: string; NewTabPosition: integer); procedure CopyFilenamesToClipboard(FullPaths, LeftPanel: boolean); function HandleRunFromArchive(var APath: string; Engine: TPanelEngine; Command, FileTypeDesc: string; BypassDialog: boolean): boolean; - function HandleSetPassword(Engine: TPanelEngine): boolean; function HandleKey(Key: Word; Shift: TShiftState; LeftPanel: boolean): boolean; function IsEditing(AListView: TGTKListView): boolean; function PanelFindEditableWidget(AListView: TGTKListView): PGtkWidget; @@ -258,7 +257,7 @@ uses ULibc, UFileTypeSettings, UFileAssoc, UChmod, UChown, USymlink, UPreferences, UViewer, UToolTips, UMounterPrefs, UColumns, UTestPlugin, UConnectionManager, USearch, UProperties, - URemoteWait, URunFromVFS, USetPassword, uVFSprototypes; + URemoteWait, URunFromVFS, uVFSprototypes; @@ -1702,7 +1701,7 @@ var ListView: TGTKListView; Engine: TPanelEngine; s, ss: string; i, Sel: integer; - b, bb: boolean; + b: boolean; tt: TDateTime; DataList, DirList: TList; SelectedFiles: TStringList; @@ -1775,6 +1774,7 @@ var ListView: TGTKListView; OpenDirThread.VFSAskPassword_Message, OpenDirThread.VFSAskPassword_default_user, OpenDirThread.VFSAskPassword_default_domain, + OpenDirThread.VFSAskPassword_default_password, OpenDirThread.VFSAskPassword_flags, OpenDirThread.VFSAskPassword_username, OpenDirThread.VFSAskPassword_password, @@ -1834,29 +1834,14 @@ begin DebugMsg(['TFMain.ChangingDir: Creating thread...']); DoThread; - bb := OpenDirThread.VFSOpenResult = 0; - if OpenDirThread.VFSOpenResult <> 0 then begin - DebugMsg(['(II) TFMain.ChangingDir: OpenDirThread.VFSOpenResult <> 0']); - if OpenDirThread.VFSOpenResult = cVFS_BadPassword then begin - // Handle password - if not HandleSetPassword(OpenDirThread.xEngine) then Exit; - ss := OpenDirThread.xEngine.Password; - if Assigned(OpenDirThread.xEngine) then OpenDirThread.xEngine.Free; - DebugMsg(['TFMain.ChangingDir: Freeing thread...']); - OpenDirThread.Free; - OpenDirThread := TOpenDirThread.Create; - DebugMsg(['TFMain.ChangingDir: Creating thread...']); - OpenDirThread.Password := ss; - DoThread; - bb := OpenDirThread.VFSOpenResult = 0; - end; - end; if Plugin <> nil then begin HiliString1 := ''; HiliString2 := ''; end; - if not bb then begin - Application.MessageBox(LANGCouldntOpenURIArchive, [mbOK], mbError, mbOK, mbOK); + if OpenDirThread.VFSOpenResult <> 0 then begin + // Silence the error if password dialog has been cancelled + if not OpenDirThread.VFSCallbackCancelled then + Application.MessageBox(LANGCouldntOpenURIArchive, [mbOK], mbError, mbOK, mbOK); DebugMsg(['TFMain.ChangingDir: Freeing thread...']); OpenDirThread.Free; end else @@ -2649,12 +2634,6 @@ begin end; DebugMsg(['TFMain.DoCopyMove: NewPath = "', NewPath, '"']); - // Handle password in archives - if (CurrentEngine is TVFSEngine) and (CurrentEngine as TVFSEngine).GetPasswordRequired and (Length((CurrentEngine as TVFSEngine).Password) < 1) then - if not HandleSetPassword(CurrentEngine) then Exit; - if (OppositeEngine is TVFSEngine) and (OppositeEngine as TVFSEngine).GetPasswordRequired and (Length((OppositeEngine as TVFSEngine).Password) < 1) then - if not HandleSetPassword(OppositeEngine) then Exit; - NextItem1 := ''; NextItem2 := ''; FindNextSelected(ListView, DataList, NextItem1, NextItem2); DebugMsg(['TFMain.DoCopyMove: FindNextSelected, NextItem1 = "', NextItem1, '", NextItem2 = "', NextItem2, '"']); @@ -3969,11 +3948,7 @@ begin Break; end; - // Handle password - if (Engine is TVFSEngine) and TVFSEngine(Engine).GetPasswordRequired and (Length(TVFSEngine(Engine).Password) < 1) then - if not HandleSetPassword(Engine) then Exit; - - if AFile <> '' then + if AFile <> '' then try FChmod := TFChmod.Create(Self); Stat := Engine.GetFileInfoSL(IncludeTrailingPathDelimiter(Engine.Path) + AFile); @@ -4069,11 +4044,7 @@ begin Break; end; - // Handle password - if (Engine is TVFSEngine) and TVFSEngine(Engine).GetPasswordRequired and (Length(TVFSEngine(Engine).Password) < 1) then - if not HandleSetPassword(Engine) then Exit; - - if AFile <> '' then + if AFile <> '' then try FChown := TFChown.Create(Self); Stat := Engine.GetFileInfoSL(IncludeTrailingPathDelimiter(Engine.Path) + AFile); @@ -4148,10 +4119,6 @@ begin then s2 := IncludeTrailingPathDelimiter(EngineOpposite.Path) + PDataItem(AListView.Selected.Data)^.FName else s2 := ''; - // Handle password - if (Engine is TVFSEngine) and TVFSEngine(Engine).GetPasswordRequired and (Length(TVFSEngine(Engine).Password) < 1) then - if not HandleSetPassword(Engine) then Exit; - if CreateSymlink(s1, s2, Engine) then begin DoRefresh(LeftPanel, True, True); DoRefresh(not LeftPanel, True, True); @@ -4187,10 +4154,6 @@ begin Exit; end; - // Handle password - if (Engine is TVFSEngine) and TVFSEngine(Engine).GetPasswordRequired and (Length(TVFSEngine(Engine).Password) < 1) then - if not HandleSetPassword(Engine) then Exit; - if EditSymlink(IncludeTrailingPathDelimiter(Engine.Path) + PDataItem(AListView.Selected.Data)^.FName, Engine) then begin DoRefresh(LeftPanel, True, True); DoRefresh(not LeftPanel, True, True); @@ -5276,13 +5239,13 @@ begin FTestPlugin := TFTestPlugin.Create(Self); if (FTestPlugin.Run = mbOK) and (PluginList.Count > 0) then begin Engine := TVFSEngine.Create(PluginList[FTestPlugin.PluginOptionMenu.ItemIndex]); - if not Engine.VFSOpenURI(FTestPlugin.CommandEntry.Text, nil, nil, nil) then begin + if not Engine.VFSOpenURI(FTestPlugin.CommandEntry.Text, nil, nil, nil, nil) then begin Application.MessageBox(LANGCouldntOpenURI, [mbOK], mbError, mbOK, mbOK); Exit; end; b := True; - if not FTestPlugin.AnonymousCheckButton.Checked then - b := HandleLogin(FTestPlugin, Engine, FTestPlugin.UserEntry.Text, FTestPlugin.PasswordEntry.Text); +{ if not FTestPlugin.AnonymousCheckButton.Checked then + b := HandleLogin(FTestPlugin, Engine, FTestPlugin.UserEntry.Text, FTestPlugin.PasswordEntry.Text); } if b then begin if LeftLastFocused then LeftPanelEngine := Engine else RightPanelEngine := Engine; @@ -6250,10 +6213,6 @@ begin end else Res := mbYes; if Res in [mbYes, mbNo] then begin Result := False; - // Handle password - if (Engine is TVFSEngine) and TVFSEngine(Engine).GetPasswordRequired and (Length(TVFSEngine(Engine).Password) < 1) then - if not HandleSetPassword(Engine) then Exit; - if Res = mbYes then DebugMsg(['(II) HandleRunFromArchive: Selected extract and execute single item']) else DebugMsg(['(II) HandleRunFromArchive: Selected extract all and execute']); s := IncludeTrailingPathDelimiter(ConfTempPath) + 'tuxcmd-XXXXXX'; @@ -6335,30 +6294,30 @@ begin end; procedure TFMain.PasswordButtonClick(Sender: TObject); +var Engine: TPanelEngine; + Password: PChar; begin - if Sender = LeftPasswordButton then HandleSetPassword(LeftPanelEngine) else - if Sender = RightPasswordButton then HandleSetPassword(RightPanelEngine); -end; + if Sender = LeftPasswordButton then Engine := LeftPanelEngine else + if Sender = RightPasswordButton then Engine := RightPanelEngine + else Exit; -function TFMain.HandleSetPassword(Engine: TPanelEngine): boolean; -begin - Result := False; if not (Engine is TVFSEngine) then Exit; try - FSetPassword := TFSetPassword.Create(Self); - FSetPassword.Entry.Text := TVFSEngine(Engine).Password; - if Length(FSetPassword.Entry.Text) > 0 then FSetPassword.Entry.SelectAll; - Result := FSetPassword.Run = mbOK; - if Result then TVFSEngine(Engine).Password := FSetPassword.Entry.Text; - FSetPassword.Free; + Password := nil; + if HandleVFSAskPasswordCallback(FWidget, PChar('The archive is encrypted and requires password'), + nil, nil, PChar(TVFSEngine(Engine).Password), + VFS_ASK_PASSWORD_NEED_PASSWORD or VFS_ASK_PASSWORD_ARCHIVE_MODE, + nil, @Password, nil, nil, nil) then + if Password <> nil then begin + TVFSEngine(Engine).Password := string(Password); + TVFSEngine(Engine).PasswordUsed := False; + g_free(Password); + end; except on E: Exception do DebugMsg(['*** Exception raised in FMain.HandleSetPassword: (', E.ClassName, '): ', E.Message]); end; end; - - - end. diff --git a/USearch.pas b/USearch.pas index 1c319d9..763dd41 100644 --- a/USearch.pas +++ b/USearch.pas @@ -577,7 +577,7 @@ begin DebugMsg(['Found plugin ''', Plugin.VFSName, ''', trying to open the archive ''', archive, '''']); AEngine := TVFSEngine.Create(Plugin); (AEngine as TVFSEngine).ArchiveMode := True; - b := b and ((AEngine as TVFSEngine).VFSOpenEx(archive) = 0); + b := b and ((AEngine as TVFSEngine).VFSOpenEx(archive, nil, nil, nil, nil) = 0); end; end; end else begin @@ -953,7 +953,7 @@ begin xEngine.ArchiveMode := True; xEngine.SavePath := StartDir + FileName; FEngine := xEngine; - VFSOpenResult := (FEngine as TVFSEngine).VFSOpenEx(IncludeTrailingPathDelimiter(StartDir) + FileName); + VFSOpenResult := (FEngine as TVFSEngine).VFSOpenEx(IncludeTrailingPathDelimiter(StartDir) + FileName, nil, nil, nil, nil); if (VFSOpenResult = 0) and (not CancelIt) then Rekurze('/'); FEngine := FEngine.ParentEngine; if not (xEngine as TVFSEngine).VFSClose then DebugMsg(['Error closing the engine...']); diff --git a/USetPassword.pas b/USetPassword.pas deleted file mode 100644 index cdf7fee..0000000 --- a/USetPassword.pas +++ /dev/null @@ -1,107 +0,0 @@ -(* - Tux Commander - USetPassword - Password prompt dialog - Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net> - Check for updates on tuxcmd.sourceforge.net - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*) -unit USetPassword; - -interface - -uses - glib2, gtk2, pango, SysUtils, Types, Classes, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKConsts, GTKView, - GTKUtils, GTKDialogs, GTKPixbuf, GTKClasses; - -type - TFSetPassword = class(TGTKDialog) - Label1, Label2: TGTKLabel; - DialogIcon: TGTKImage; - Entry: TGTKEntry; - Table: TGTKTable; - ShowPasswordCheckButton: TGTKCheckButton; - procedure FormCreate(Sender: TObject); override; - procedure FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); - procedure ShowPasswordCheckButtonClick(Sender: TObject); - end; - -var - FSetPassword: TFSetPassword; - -implementation - -uses ULocale, UFileAssoc; - - -procedure TFSetPassword.FormCreate(Sender: TObject); -begin - SetDefaultSize(400, -1); - Buttons := [mbOK, mbCancel]; - Caption := LANGFSetPassword_Caption; - - Table := TGTKTable.Create(Self); - DialogIcon := TGTKImage.Create(Self); - if gtk_style_lookup_icon_set(gtk_widget_get_style(FWidget), 'gtk-dialog-authentication') <> nil - then DialogIcon.SetFromStock('gtk-dialog-authentication', isDialog) - else DialogIcon.CopyFromPixbuf(StockLock48); - - Label1 := TGTKLabel.Create(Self); - Label1.Caption := Format('<span size="x-large" weight="bold">%s</span>', [LANGFSetPassword_Label1_Caption]); - Label1.UseMarkup := True; - Label1.XAlign := 0; - Label2 := TGTKLabel.Create(Self); - Label2.Caption := LANGFSetPassword_Label2_Caption; - Label2.LineWrap := True; - Label2.XAlign := 0; - Label2.SetSizeRequest(270, -1); - Entry := TGTKEntry.Create(Self); - Entry.Visibility := False; - ShowPasswordCheckButton := TGTKCheckButton.CreateWithLabel(Self, LANGFSetPassword_ShowPasswordCheckButton); - ShowPasswordCheckButton.OnToggled := ShowPasswordCheckButtonClick; - - Table.AddControlEx(0, 0, 2, 1, Label1, [taoExpand, taoFill], [taoShrink], 20, 3); - Table.AddControlEx(0, 1, 1, 1, DialogIcon, [taoShrink], [taoShrink], 10, 5); - Table.AddControlEx(1, 1, 1, 1, Label2, [taoExpand, taoFill], [taoShrink], 5, 0); - Table.AddControlEx(0, 2, 1, 1, TGTKVBox.Create(Self), [taoShrink], [taoShrink, taoExpand, taoFill], 2, 6); - Table.AddControlEx(0, 3, 2, 1, Entry, [taoExpand, taoFill], [taoShrink], 5, 0); - Table.AddControlEx(0, 4, 2, 1, ShowPasswordCheckButton, [taoExpand, taoFill], [taoShrink], 15, 5); - Table.BorderWidth := 10; - ClientArea.AddControlEx(Table, True, True, 0); - OnKeyDown := FormKeyDown; - Entry.SetFocus; -end; - -procedure TFSetPassword.FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); -begin - case Key of - GDK_RETURN, GDK_KP_ENTER: ModalResult := mbOK; - GDK_ESCAPE: ModalResult := mbCancel; - GDK_M, GDK_Capital_M: if (Shift = [ssAlt]) then begin - ShowPasswordCheckButton.Checked := not ShowPasswordCheckButton.Checked; - Accept := False; - end; - end; -end; - -procedure TFSetPassword.ShowPasswordCheckButtonClick(Sender: TObject); -begin - Entry.Visibility := ShowPasswordCheckButton.Checked; -end; - - - - -end. - @@ -60,14 +60,12 @@ uses UVFSCore in 'vfs/UVFSCore.pas', uVFSprototypes in 'vfs/uVFSprototypes.pas', UToolTips in 'UToolTips.pas', - ULogin in 'ULogin.pas', UConnectionManager in 'UConnectionManager.pas', UConnectionProperties in 'UConnectionProperties.pas', USearch in 'USearch.pas', UGlibThreads in 'UGlibThreads.pas', URunFromVFS in 'URunFromVFS.pas', ULibc in 'ULibc.pas', - USetPassword in 'USetPassword.pas', UTranslation_EN in 'translations/UTranslation_EN.pas', UTranslation_CZ in 'translations/UTranslation_CZ.pas', UTranslation_RU in 'translations/UTranslation_RU.pas', diff --git a/vfs/UVFSCore.pas b/vfs/UVFSCore.pas index ee2a6ca..8bba788 100644 --- a/vfs/UVFSCore.pas +++ b/vfs/UVFSCore.pas @@ -41,7 +41,6 @@ type FVFSGetPrefix: TVFSGetPrefix; FVFSGetFileSystemSize: TVFSGetFileSystemSize; FVFSGetFileSystemFree: TVFSGetFileSystemFree; - FVFSLogin: TVFSLogin; FVFSFileExists: TVFSFileExists; FVFSFileInfo: TVFSFileInfo; FVFSMkDir: TVFSMkDir; @@ -65,7 +64,6 @@ type FVFSTwoSameFiles: TVFSTwoSameFiles; FVFSGetExts: TVFSGetExts; FVFSGetServices: TVFSGetServices; - FVFSSetPassword: TVFSSetPassword; FVFSGetPasswordRequired: TVFSGetPasswordRequired; FVFSSetCallbacks: TVFSSetCallbacks; public @@ -88,23 +86,21 @@ type FGlobs: Pointer; FSourcePlugin: TVFSPlugin; FBlockSize: Cardinal; - FProgressFunc: TEngineProgressFunc; - FSenderThread: Pointer; BreakProcessingKind: integer; - FPassword: string; - procedure SetFPassword(Value: string); public ArchiveMode: boolean; + Password: string; + PasswordUsed: boolean; constructor Create(SourcePlugin: TVFSPlugin); - function VFSOpenURI(URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; CallbackData: Pointer): boolean; - function VFSOpenEx(OpenFile: string): TVFSResult; + function VFSOpenURI(URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; + function VFSOpenEx(OpenFile: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): TVFSResult; function VFSClose: boolean; destructor Destroy; override; function GetListing(var List: TList; const AddDotFiles: boolean): integer; override; function GetListing(var List: TList; const AddDotFiles: boolean; APath: string): integer; override; function ChangeDir(const NewPath: string): integer; override; - function ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; CallbackData: Pointer): integer; + function ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): integer; function ExplicitChDir(const NewPath: string): integer; override; function GetFileSystemSize: Int64; override; function GetFileSystemSize(const APath: string): Int64; override; @@ -134,21 +130,22 @@ type function GetPath: string; override; procedure SetPath(Value: string); override; function GetPrefix: string; override; - function Login(Username, Password: string): integer; override; function GetBlockSize: Cardinal; override; procedure SetBlockSize(Value: Cardinal); override; function CopyFileIn(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; override; function CopyFileOut(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; override; + function CopyFileInEx(Sender: Pointer; SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean; + AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; + function CopyFileOutEx(Sender: Pointer; SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean; + AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; function IsOnSameFS(const Path1, Path2: string): boolean; override; function TwoSameFiles(const Path1, Path2: string): boolean; override; - function SetPassword(Password: string): integer; function GetPasswordRequired: boolean; published property Path: string read GetPath write SetPath; property BlockSize: Cardinal read GetBlockSize write SetBlockSize; - property Password: string read FPassword write SetFPassword; end; @@ -199,7 +196,6 @@ begin @FVFSGetPrefix := dlsym(ModuleHandle, 'VFSGetPrefix'); @FVFSGetFileSystemSize := dlsym(ModuleHandle, 'VFSGetFileSystemSize'); @FVFSGetFileSystemFree := dlsym(ModuleHandle, 'VFSGetFileSystemFree'); - @FVFSLogin := dlsym(ModuleHandle, 'VFSLogin'); @FVFSFileExists := dlsym(ModuleHandle, 'VFSFileExists'); @FVFSFileInfo := dlsym(ModuleHandle, 'VFSFileInfo'); @FVFSMkDir := dlsym(ModuleHandle, 'VFSMkDir'); @@ -223,7 +219,6 @@ begin @FVFSTwoSameFiles := dlsym(ModuleHandle, 'VFSTwoSameFiles'); @FVFSGetExts := dlsym(ModuleHandle, 'VFSGetExts'); @FVFSGetServices := dlsym(ModuleHandle, 'VFSGetServices'); - @FVFSSetPassword := dlsym(ModuleHandle, 'VFSSetPassword'); @FVFSGetPasswordRequired := dlsym(ModuleHandle, 'VFSGetPasswordRequired'); @FVFSSetCallbacks := dlsym(ModuleHandle, 'VFSSetCallbacks'); // Initialize the extensions list @@ -294,7 +289,8 @@ begin ArchiveMode := False; BreakProcessingKind := 0; FGlobs := nil; - FPassword := ''; + Password := ''; + PasswordUsed := False; if @FSourcePlugin.FVFSNew <> nil then FGlobs := FSourcePlugin.FVFSNew(@VFSLogFunc); end; @@ -308,23 +304,28 @@ begin end; end; -function TVFSEngine.VFSOpenURI(URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; CallbackData: Pointer): boolean; +function TVFSEngine.VFSOpenURI(URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; begin Result := False; if (FGlobs <> nil) and (@FSourcePlugin.FVFSOpen <> nil) then begin if @FSourcePlugin.FVFSSetCallbacks <> nil then - FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, CallbackData); + FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData); Result := FSourcePlugin.FVFSOpen(FGlobs, PChar(URI)) = cVFS_OK; if @FSourcePlugin.FVFSSetCallbacks <> nil then - FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil); + FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil); end; end; -function TVFSEngine.VFSOpenEx(OpenFile: string): TVFSResult; +function TVFSEngine.VFSOpenEx(OpenFile: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): TVFSResult; begin Result := cVFS_OK; - if (FGlobs <> nil) and (@FSourcePlugin.FVFSOpen <> nil) - then Result := FSourcePlugin.FVFSOpen(FGlobs, PChar(OpenFile)); + if (FGlobs <> nil) and (@FSourcePlugin.FVFSOpen <> nil) then begin + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData); + Result := FSourcePlugin.FVFSOpen(FGlobs, PChar(OpenFile)); + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil); + end; end; function TVFSEngine.VFSClose: boolean; @@ -510,30 +511,22 @@ begin DebugMsg(['^^VFS (II): ChangeDir end.']); end; -function TVFSEngine.ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; CallbackData: Pointer): integer; +function TVFSEngine.ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): integer; begin if (FGlobs <> nil) and (@FSourcePlugin.FVFSChangeDir <> nil) then begin if @FSourcePlugin.FVFSSetCallbacks <> nil then - FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, CallbackData); + FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData); Result := ChangeDir(NewPath); if @FSourcePlugin.FVFSSetCallbacks <> nil then - FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil); + FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil); end; end; - procedure TVFSEngine.SetPath(Value: string); begin ChangeDir(Value); end; -function TVFSEngine.Login(Username, Password: string): integer; -begin - if (FGlobs <> nil) and (@FSourcePlugin.FVFSLogin <> nil) - then Result := FSourcePlugin.FVFSLogin(FGlobs, PChar(Username), PChar(Password)) - else Result := cVFS_OK; -end; - function TVFSEngine.FileExists(const FileName: string; const Use_lstat: boolean = False): Boolean; begin if (FGlobs <> nil) and (@FSourcePlugin.FVFSFileExists <> nil) @@ -840,32 +833,31 @@ end; (********************************************************************************************************************************) - -function VFSCopyCallBackFunc(iPos, iMax:Int64; data: Pointer): LongBool; cdecl; +function TVFSEngine.CopyFileIn(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; begin -// DebugMsg(['VFSCopyCallBackFunc called (iPos = ', iPos, ', iMax = ', iMax, ')']); - Result := True; - if not Assigned(data) then Exit; - if Assigned(TVFSEngine(data).FProgressFunc) then - try - Result := TVFSEngine(data).FProgressFunc(TVFSEngine(data).FSenderThread, iPos); - except - on E: Exception do DebugMsg(['*** Exception raised in VFSCopyCallBackFunc(iPos=', iPos, ', iMax=', iMax, ', data=', data, '): (', E.ClassName, '): ', E.Message]); - end; + Result := CopyFileInEx(Sender, SourceFile, DestFile, ErrorFunc, Append, nil, nil, nil, nil); end; function TVFSEngine.CopyFileOut(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; +begin + Result := CopyFileInEx(Sender, SourceFile, DestFile, ErrorFunc, Append, nil, nil, nil, nil); +end; + +function TVFSEngine.CopyFileOutEx(Sender: Pointer; SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean; + AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; var Res: TVFSResult; begin Result := False; try if @FSourcePlugin.FVFSCopyOut <> nil then begin - FSenderThread := Sender; - FProgressFunc := ProgressFunc; // DebugMsg(['0 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']); // DebugMsg([' Pointer(FGlobs) = 0x', IntToHex(Int64(FGlobs), 16), ', Pointer(@NewVFSCopyCallBackFunc) = 0x', IntToHex(Int64(@NewVFSCopyCallBackFunc), 16), ', Pointer(Self) = 0x', IntToHex(Int64(Self), 16)]); try - Res := FSourcePlugin.FVFSCopyOut(FGlobs, PChar(SourceFile), PChar(DestFile), @VFSCopyCallBackFunc, Self, Append); + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData); + Res := FSourcePlugin.FVFSCopyOut(FGlobs, PChar(SourceFile), PChar(DestFile), Append); + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil); except on E: Exception do begin DebugMsg(['*** Exception raised in TVFSEngine.CopyFileOut(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]); @@ -879,7 +871,7 @@ begin cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, SourceFile); cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, DestFile); cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, SourceFile); - cVFS_Cancelled: Result := False; + cVFS_Cancelled: ErrorFunc(Sender, 0, 0, SourceFile); end; end else Result := False; except @@ -887,16 +879,19 @@ begin end; end; -function TVFSEngine.CopyFileIn(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; +function TVFSEngine.CopyFileInEx(Sender: Pointer; SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; + Append: boolean; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean; var Res: TVFSResult; begin Result := False; try if @FSourcePlugin.FVFSCopyIn <> nil then begin - FSenderThread := Sender; - FProgressFunc := ProgressFunc; try - Res := FSourcePlugin.FVFSCopyIn(FGlobs, PChar(SourceFile), PChar(DestFile), @VFSCopyCallBackFunc, Self, Append); + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData); + Res := FSourcePlugin.FVFSCopyIn(FGlobs, PChar(SourceFile), PChar(DestFile), Append); + if @FSourcePlugin.FVFSSetCallbacks <> nil then + FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil); except on E: Exception do begin DebugMsg(['*** Exception raised in TVFSEngine.CopyFileIn(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]); @@ -909,7 +904,7 @@ begin cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, SourceFile); cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, DestFile); cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, SourceFile); - cVFS_Cancelled: Result := False; + cVFS_Cancelled: ErrorFunc(Sender, 0, 0, SourceFile); end; end else Result := False; except @@ -920,25 +915,12 @@ end; (********************************************************************************************************************************) (********************************************************************************************************************************) -function TVFSEngine.SetPassword(Password: string): integer; -begin - if @FSourcePlugin.FVFSSetPassword <> nil then Result := FSourcePlugin.FVFSSetPassword(FGlobs, PChar(Password)) - else Result := 0; - FPassword := Password; -end; - function TVFSEngine.GetPasswordRequired: boolean; begin if @FSourcePlugin.FVFSGetPasswordRequired <> nil then Result := FSourcePlugin.FVFSGetPasswordRequired(FGlobs) else Result := False; end; -procedure TVFSEngine.SetFPassword(Value: string); -begin - SetPassword(Value); -end; - - (********************************************************************************************************************************) (********************************************************************************************************************************) function GetBinaryPath: string; diff --git a/vfs/uVFSprototypes.pas b/vfs/uVFSprototypes.pas index ba848e9..43190a4 100644 --- a/vfs/uVFSprototypes.pas +++ b/vfs/uVFSprototypes.pas @@ -69,7 +69,8 @@ const VFS_ASK_PASSWORD_NEED_DOMAIN = 1 shl 2; VFS_ASK_PASSWORD_SAVING_SUPPORTED = 1 shl 3; // Plugin reports if gnome-keyring is available VFS_ASK_PASSWORD_ANONYMOUS_SUPPORTED = 1 shl 4; - VFS_ASK_PASSWORD_SAVE_INTERNAL = 1 shl 15; // Save password into internal Connection Manager + VFS_ASK_PASSWORD_SAVE_INTERNAL = 1 shl 14; // Save password into internal Connection Manager + VFS_ASK_PASSWORD_ARCHIVE_MODE = 1 shl 15; // Callback from archive, change the UI a little bit type @@ -145,6 +146,38 @@ type end; type + // Return index of the choice selected or negative number when dialog has been cancelled + // cancel_choice: index which represents the cancellation choice. Set to -1 (e.g.) to disable this feature + PVFSAskQuestionCallback = ^TVFSAskQuestionCallback; + TVFSAskQuestionCallback = procedure (const AMessage: PChar; + const Choices: PPChar; + choice: PInteger; + cancel_choice: Integer; + user_data: Pointer); cdecl; + + PVFSAskPasswordCallback = ^TVFSAskPasswordCallback; + // Remember to allocate passed strings separately (use strdup() when setting reply) + // Modules are eligible for keeping passwords during one session; calling callback again means the last password was wrong and user should enter new one + // Returns True (1) if succeeded or False (0) if cancelled + TVFSAskPasswordCallback = function (const AMessage: PChar; + const default_user: PChar; + const default_domain: PChar; + const default_password: PChar; + flags: TVFSAskPasswordFlags; + username: PPChar; + password: PPChar; + anonymous: PInteger; + domain: PPChar; + password_save: PVFSPasswordSave; + user_data: Pointer): LongBool; cdecl; + + // Return False to break the operation + PVFSProgressCallback = ^TVFSProgressCallback; + TVFSProgressCallback = function (position: Int64; + max: Int64; + user_data: Pointer): LongBool; cdecl; + +type // Log function which could plugin call - the application must handle the messages (e.g. write them to the stdout) PVFSLogFunc = ^TVFSLogFunc; TVFSLogFunc = procedure(S: PChar); cdecl; @@ -177,8 +210,6 @@ type TVFSOpen = function (g:TVFSGlobs; const sName: PChar): TVFSResult; cdecl; // TODO: Opens the location (file or URI/URL) // In case of URI, do not supply password encoded in the string; plugin will automatically spawn the TVFSAskPasswordCallback callback - TVFSLogin = function (g:TVFSGlobs; const User, Pass: PChar): TVFSResult; cdecl; - // TODO: Performs login to the server TVFSClose = function (g:TVFSGlobs): TVFSResult; cdecl; // Closes the file or connection to the server TVFSMkDir = function (g:TVFSGlobs; const sDirName: PChar): TVFSResult; cdecl; @@ -214,19 +245,20 @@ type // TODO: Runs the command read from inside the archive (typically installing the rpm package) - TVFSCopyCallBackFunc = function (iPos, iMax: Int64; data: Pointer):LongBool; cdecl; - // Callback function used during the copy process; return False to break the copy process - - TVFSCopyOut = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; pCallBackProgress: TVFSCopyCallBackFunc; data: Pointer; Append: LongBool): TVFSResult; cdecl; + TVFSCopyOut = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; Append: LongBool): TVFSResult; cdecl; // Performs the copy process from inside of module to the file in the local system // (thus sSrcName is a path from inside of module and sDstName is path in the local filesystem where the file should be copied) // The data pointer is then used to call the callback function in // Note: if you need to transfer a file between two VFS modules, you need to do it manually - either first copy to local FS or use the Open, Read, Write functions of the module (NOTE: both VFS modules have to support these functions) - TVFSCopyIn = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; pCallBackProgress: TVFSCopyCallBackFunc; data: Pointer; Append: LongBool): TVFSResult; cdecl; + TVFSCopyIn = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; Append: LongBool): TVFSResult; cdecl; // Performs the copy process from the local filesystem into the module + // Prototype function for packing new files into archive + TVFSPack = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; CompressionLevel: integer; const Password: PChar): TVFSResult; cdecl; + + // This is the set of basic functions which can manipulate with the data // There is a TVFSFileDes object which identifies the processed file (filedescriptor) // All these functions needs a pointer to an int variable to store the error code @@ -253,7 +285,6 @@ type TVFSFileInfo = function (g:TVFSGlobs; AFileName: PChar; VFSItem: PVFSItem): TVFSResult; cdecl; // Gets a single info item without need to list a whole directory - TVFSSetPassword = function (g:TVFSGlobs; pass: PChar): TVFSResult; cdecl; TVFSGetPasswordRequired = function (g:TVFSGlobs): LongBool; cdecl; /// pridat neco jako set_loglevel ?? @@ -261,29 +292,11 @@ type //// pridat typ pluginu - jestli archive nebo protocol - prip. jeste pridat ktery protokoly je to schopno handlovat - // Return index of the choice selected or negative number when dialog has been cancelled - // cancel_choice: index which represents the cancellation choice. Set to -1 (e.g.) to disable this feature - PVFSAskQuestionCallback = ^TVFSAskQuestionCallback; - TVFSAskQuestionCallback = procedure (const AMessage: PChar; - const Choices: PPChar; - choice: PInteger; - cancel_choice: Integer; - user_data: Pointer); cdecl; - - PVFSAskPasswordCallback = ^TVFSAskPasswordCallback; - // Remember to allocate passed strings separately (use strdup() when setting reply) - TVFSAskPasswordCallback = function (const AMessage: PChar; - const default_user: PChar; - const default_domain: PChar; - flags: TVFSAskPasswordFlags; - username: PPChar; - password: PPChar; - anonymous: PInteger; - domain: PPChar; - password_save: PVFSPasswordSave; - user_data: Pointer): LongBool; cdecl; - TVFSSetCallbacks = procedure (g: TVFSGlobs; ask_question_callback: PVFSAskQuestionCallback; ask_password_callback: PVFSAskPasswordCallback; Data: Pointer); cdecl; + TVFSSetCallbacks = procedure (g: TVFSGlobs; ask_question_callback: PVFSAskQuestionCallback; + ask_password_callback: PVFSAskPasswordCallback; + progress_func: PVFSProgressCallback; + user_data: Pointer); cdecl; |
