diff options
| -rw-r--r-- | UConfig.pas | 1 | ||||
| -rw-r--r-- | UConnectionManager.pas | 190 | ||||
| -rw-r--r-- | UConnectionProperties.pas | 28 | ||||
| -rw-r--r-- | UCore.pas | 13 | ||||
| -rw-r--r-- | UCoreUtils.pas | 7 | ||||
| -rw-r--r-- | UGnome.pas | 50 | ||||
| -rw-r--r-- | UMain.pas | 100 | ||||
| -rw-r--r-- | libgtk_kylix/GTKForms.pas | 22 | ||||
| -rw-r--r-- | vfs/UVFSCore.pas | 2 | ||||
| -rw-r--r-- | vfs/uVFSprototypes.pas | 15 |
10 files changed, 273 insertions, 155 deletions
diff --git a/UConfig.pas b/UConfig.pas index 6da4faa..9ef8917 100644 --- a/UConfig.pas +++ b/UConfig.pas @@ -935,7 +935,6 @@ begin Password := IniFile.ReadString(Sections[i], 'Password', ''); TargetDir := IniFile.ReadString(Sections[i], 'TargetDir', ''); PluginID := IniFile.ReadString(Sections[i], 'PluginID', ''); - URI := ConstructURI(False, ServiceType, Server, Username, Password, TargetDir); end; ConnectionMgrList.Add(Item); end; diff --git a/UConnectionManager.pas b/UConnectionManager.pas index 0fbb4d1..dc97e20 100644 --- a/UConnectionManager.pas +++ b/UConnectionManager.pas @@ -24,7 +24,7 @@ interface uses glib2, gdk2, gtk2, pango, SysUtils, Types, Classes, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKConsts, GTKView, GTKUtils, GTKDialogs, GTKPixbuf, GTKClasses, - UCoreClasses; + UCore, UCoreClasses, UVFSCore, UEngines, URemoteWait; type TFConnectionManager = class(TGTKDialog) @@ -38,6 +38,8 @@ type ListViewTable: TGTKTable; AddConnectionButton, EditButton, RemoveButton: TGTKImageButton; ButtonBox: TGTKVButtonBox; + ActionButtonBox: TGTKHButtonBox; + ConnectButton, CloseButton: TGTKButton; procedure FormCreate(Sender: TObject); override; procedure ListViewSelectionChanged(Sender: TObject); procedure FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); @@ -46,8 +48,18 @@ type procedure RemoveButtonClick(Sender: TObject); procedure ListViewDblClick(Sender: TObject; Button: TGDKMouseButton; Shift: TShiftState; X, Y: Integer; var Accept: boolean); procedure ListViewKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); + procedure CloseButtonClick(Sender: TObject); + procedure ConnectButtonClick(Sender: TObject); private + FSilenceError: boolean; + AFRemoteWait: TFRemoteWait; + FActiveConnInfo: TConnMgrItem; + FVFSAskPasswordTry: integer; procedure FillList; + procedure DoConnect; + public + SourcePanelEngine: TPanelEngine; + ConnectedEngine: TVFSEngine; end; var @@ -55,19 +67,32 @@ var implementation -uses ULocale, UCoreUtils, UConfig, UCore, UConnectionProperties, UVFSCore; - -const Connect_Button_ID = integer(mbOK); +uses ULocale, UCoreUtils, UConfig, UConnectionProperties, UGnome, uVFSprototypes; procedure TFConnectionManager.FormCreate(Sender: TObject); var Column: TGTKTreeViewColumn; begin + ConnectedEngine := nil; SetDefaultSize(550, 450); Caption := LANGConnMgr_Caption; - AddButton(LANGConnMgr_ConnectButton, Connect_Button_ID); - Buttons := [mbClose]; + Buttons := []; ShowSeparator := False; + + ConnectButton := TGTKButton.Create(Self); + ConnectButton.Caption := LANGConnMgr_ConnectButton; +// ConnectButton.Default := True; + CloseButton := TGTKButton.CreateFromStock(Self, GTK_STOCK_CLOSE); +// Default := ConnectButton; + ActionButtonBox := TGTKHButtonBox.Create(Self); + ActionButtonBox.Layout := blEnd; + ActionButtonBox.Spacing := 10; + ActionButtonBox.BorderWidth := 0; + ActionButtonBox.AddControlEnd(CloseButton); + ActionButtonBox.AddControlEnd(ConnectButton); + + ActionArea.AddControlEx(ActionButtonBox, False, False, 0); + TitleEventBox := TGTKEventBox.Create(Self); TitleLabel := TGTKLabel.Create(Self); TitleLabel.Caption := Format('<span size="x-large" weight="ultrabold">%s</span>', [LANGConnMgr_OpenConnection]); @@ -158,6 +183,8 @@ begin AddConnectionButton.OnClick := AddConnectionButtonClick; EditButton.OnClick := EditButtonClick; RemoveButton.OnClick := RemoveButtonClick; + CloseButton.OnClick := CloseButtonClick; + ConnectButton.OnClick := ConnectButtonClick; OnKeyDown := FormKeyDown; end; @@ -166,21 +193,21 @@ begin try EditButton.Enabled := Assigned(ListView.Selected); RemoveButton.Enabled := Assigned(ListView.Selected); - SetResponseSensitive(Connect_Button_ID, Assigned(ListView.Selected)); + ConnectButton.Enabled := Assigned(ListView.Selected); except end; end; procedure TFConnectionManager.FormKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); begin case Key of - GDK_RETURN, GDK_KP_ENTER: if Assigned(ListView.Selected) then ModalResult := mbOK; + GDK_RETURN, GDK_KP_ENTER: if Assigned(ListView.Selected) then DoConnect; GDK_ESCAPE: ModalResult := mbCancel; end; end; procedure TFConnectionManager.ListViewDblClick(Sender: TObject; Button: TGDKMouseButton; Shift: TShiftState; X, Y: Integer; var Accept: boolean); begin - if Assigned(ListView.Selected) then ModalResult := mbOK; + if Assigned(ListView.Selected) then DoConnect; end; procedure TFConnectionManager.ListViewKeyDown(Sender: TObject; Key: Word; Shift: TShiftState; var Accept: boolean); @@ -202,8 +229,7 @@ begin ConnMgrItem := TConnMgrItem.Create; with FConnectionProperties do begin ConnMgrItem.ConnectionName := NameEntry.Text; - ConnMgrItem.URI := MakeURI(False); - ConnMgrItem.ServiceType := Copy(ConnMgrItem.URI, 1, Pos('://', ConnMgrItem.URI) - 1); + ConnMgrItem.ServiceType := GetService; ConnMgrItem.Server := ServerEntry.Text; ConnMgrItem.Username := UserNameEntry.Text; ConnMgrItem.Password := PasswordEntry.Text; @@ -234,7 +260,7 @@ begin if ConnMgrItem = nil then Exit; FConnectionProperties := TFConnectionProperties.Create(Self); FConnectionProperties.NameEntry.Text := ConnMgrItem.ConnectionName; - FConnectionProperties.URIEntry.Text := ConnMgrItem.URI; + FConnectionProperties.URIEntry.Text := ConstructURI(True, False, ConnMgrItem.ServiceType, ConnMgrItem.Server, ConnMgrItem.Username, ConnMgrItem.Password, ConnMgrItem.TargetDir); FConnectionProperties.ServiceTypeOptionMenuChanged(Sender); // Find the plugin by PluginID for i := 0 to PluginList.Count - 1 do @@ -246,8 +272,7 @@ begin if FConnectionProperties.Run = mbOK then begin with FConnectionProperties do begin ConnMgrItem.ConnectionName := NameEntry.Text; - ConnMgrItem.URI := MakeURI(False); - ConnMgrItem.ServiceType := Copy(ConnMgrItem.URI, 1, Pos('://', ConnMgrItem.URI) - 1); + ConnMgrItem.ServiceType := GetService; ConnMgrItem.Server := ServerEntry.Text; ConnMgrItem.Username := UserNameEntry.Text; ConnMgrItem.Password := PasswordEntry.Text; @@ -299,14 +324,147 @@ begin Item := ListView.Items.Add; Item.SetValue(0, ConnMgrItem); Item.SetValue(1, ConnMgrItem.ConnectionName); - Item.SetValue(2, ConstructURI(True, ConnMgrItem.ServiceType, ConnMgrItem.Server, ConnMgrItem.Username, - ConnMgrItem.Password, ConnMgrItem.TargetDir)); + Item.SetValue(2, ConstructURI(True, True, ConnMgrItem.ServiceType, ConnMgrItem.Server, ConnMgrItem.Username, + ConnMgrItem.Password, ConnMgrItem.TargetDir)); end; if (ConfConnMgrActiveItem < 0) or (ConfConnMgrActiveItem > ConnectionMgrList.Count) then ConfConnMgrActiveItem := 0; end; +(********************************************************************************************************************************) +procedure TFConnectionManager.CloseButtonClick(Sender: TObject); +begin + ModalResult := mbCancel; +end; + +procedure TFConnectionManager.ConnectButtonClick(Sender: TObject); +begin + DoConnect; +end; + +procedure vfs_ask_question_callback(const AMessage: PChar; const Choices: PPChar; choice: PInteger; user_data: Pointer); cdecl; +var ConnMgr: TFConnectionManager; + DialogParent: PGtkWidget; +begin + ConnMgr := user_data; + DialogParent := nil; +// DebugMsg(['******* vfs_ask_question_callback spawned, user_data = 0x', IntToHex(QWord(user_data), 16), ', ThreadID = 0x', IntToHex(pthread_self, 16)]); + if ConnMgr is TFConnectionManager then begin + if ConnMgr.AFRemoteWait <> nil then DialogParent := ConnMgr.AFRemoteWait.FWidget + else DialogParent := ConnMgr.FWidget; + end; + HandleVFSAskQuestionCallback(DialogParent, AMessage, Choices, choice); + if ConnMgr is TFConnectionManager then begin + if choice <> nil then ConnMgr.FSilenceError := choice^ < 0; + end; +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 ConnMgr: TFConnectionManager; + DialogParent: PGtkWidget; +begin + ConnMgr := user_data; + DialogParent := nil; +// DebugMsg(['******* vfs_ask_password_callback spawned, user_data = 0x', IntToHex(QWord(user_data), 16), ', ThreadID = 0x', IntToHex(pthread_self, 16)]); + if ConnMgr is TFConnectionManager then begin + Inc(ConnMgr.FVFSAskPasswordTry); + if ConnMgr.AFRemoteWait <> nil then DialogParent := ConnMgr.AFRemoteWait.FWidget + else DialogParent := ConnMgr.FWidget; + flags := flags or VFS_ASK_PASSWORD_SAVE_INTERNAL; + end; + + // First pass, supply stored password if we have one + if (ConnMgr is TFConnectionManager) and (ConnMgr.FVFSAskPasswordTry = 1) and (password <> nil) and + ((flags and VFS_ASK_PASSWORD_NEED_PASSWORD) = VFS_ASK_PASSWORD_NEED_PASSWORD) and ((flags and VFS_ASK_PASSWORD_NEED_USERNAME) = 0) and + (ConnMgr.FActiveConnInfo <> nil) and (Length(ConnMgr.FActiveConnInfo.Password) > 0) then + begin + DebugMsg(['(II) vfs_ask_password_callback: Supplying stored password from Connection Manager']); + Result := True; + password^ := g_strdup(PChar(ConnMgr.FActiveConnInfo.Password)); + 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); + if ConnMgr is TFConnectionManager then begin + ConnMgr.FSilenceError := Result = False; + // Save password back to Connection Manager + if Result and (password_save <> nil) and (password_save^ = VFS_PASSWORD_SAVE_PERMANENTLY) and + (ConnMgr.FActiveConnInfo <> nil) and (password <> nil) and (strlen(password^) > 0) then + begin + DebugMsg(['(II) vfs_ask_password_callback: Saving password to Connection Manager']); + ConnMgr.FActiveConnInfo.Password := password^; + end; + end; + end; +end; + +procedure TFConnectionManager.DoConnect; +var Engine: TVFSEngine; + i, j: integer; + VFSPlugin: TVFSPlugin; + b: boolean; +begin + FSilenceError := False; + + FActiveConnInfo := nil; + if ListView.Selected <> nil then FActiveConnInfo := ListView.Selected.AsPointer(0); + if FActiveConnInfo = nil then Exit; + + if PluginList.Count = 0 then begin + Application.MessageBox(PGtkWindow(FWidget), LANGThereIsNoModuleAvailable, [mbOK], mbError, mbOK, mbOK); + Exit; + end; + + // Find VFS module to use for this connection + VFSPlugin := nil; + if Length(FActiveConnInfo.PluginID) > 0 then + for i := 0 to PluginList.Count - 1 do + if TVFSPlugin(PluginList[i]).VFSName = FActiveConnInfo.PluginID then begin + VFSPlugin := PluginList[i]; + Break; + end; + if VFSPlugin = nil then begin + for i := 0 to PluginList.Count - 1 do begin + if Length(TVFSPlugin(PluginList[i]).Services) > 0 then + for j := 0 to Length(TVFSPlugin(PluginList[i]).Services) - 1 do + if WideCompareText(TVFSPlugin(PluginList[i]).Services[j], FActiveConnInfo.ServiceType) = 0 then begin + VFSPlugin := PluginList[i]; + Break; + end; + if VFSPlugin <> nil then Break; + end; + if VFSPlugin = nil then VFSPlugin := PluginList[0]; // Fallback in hope some other plugin can handle it + end; + + if (SourcePanelEngine is TVFSEngine) and (Application.MessageBox(PGtkWindow(FWidget), LANGCloseOpenConnection, [mbYes, mbNo], mbWarning, mbYes, mbNo) <> mbYes) then Exit; + + // Construct the VFS Engine and try to open the connection + Engine := TVFSEngine.Create(VFSPlugin); + Engine.ParentEngine := SourcePanelEngine; + Engine.SavePath := SourcePanelEngine.Path; + + AFRemoteWait := TFRemoteWait.Create(Application); + AFRemoteWait.ParentForm := FConnectionManager; + AFRemoteWait.ShowModal; + Application.ProcessMessages; + + FVFSAskPasswordTry := 0; + b := Engine.VFSOpenURI(UTF8ToStr(FActiveConnInfo.GetURI(False)), @vfs_ask_question_callback, @vfs_ask_password_callback, Self); + + AFRemoteWait.Free; + AFRemoteWait := nil; + if not b then begin + if not FSilenceError then Application.MessageBox(PGtkWindow(FWidget), LANGCouldntOpenURI, [mbOK], mbError, mbOK, mbOK); + Exit; + end; + + ConnectedEngine := Engine; + ModalResult := mbOK; +end; + end. diff --git a/UConnectionProperties.pas b/UConnectionProperties.pas index 27d5bbe..99dbf9a 100644 --- a/UConnectionProperties.pas +++ b/UConnectionProperties.pas @@ -44,6 +44,7 @@ type function ValidSettings: boolean; public function MakeURI(Hidden: boolean): string; + function GetService: string; end; var @@ -297,25 +298,8 @@ begin end; function TFConnectionProperties.MakeURI(Hidden: boolean): string; -var Prefix: string; begin - Prefix := ServiceTypeTable[ServiceTypeTable_Count, 1]; - if ServiceTypeOptionMenu.ItemIndex < ServiceTypeTable_Count - 1 - then Prefix := ServiceTypeTable[ServiceTypeOptionMenu.ItemIndex + 1, 1] else - if Pos('://', URIEntry.Text) > 1 then Prefix := Copy(URIEntry.Text, 1, Pos('://', URIEntry.Text) - 1); - Result := Prefix + '://'; - if Length(UserNameEntry.Text) > 0 then begin - Result := Result + UserNameEntry.Text; - if Length(PasswordEntry.Text) > 0 then - if Hidden then Result := Result + ':' + StringOfChar('*', Length(PasswordEntry.Text)) - else Result := Result + ':' + PasswordEntry.Text; - Result := Result + '@'; - end; - Result := Result + ServerEntry.Text; - if Length(TargetDirEntry.Text) > 0 then begin - if TargetDirEntry.Text[1] <> '/' then Result := Result + '/'; - Result := Result + TargetDirEntry.Text; - end; + Result := ConstructURI(True, Hidden, GetService, ServerEntry.Text, UserNameEntry.Text, PasswordEntry.Text, TargetDirEntry.Text); end; procedure TFConnectionProperties.ServiceTypeOptionMenuChanged(Sender: TObject); @@ -328,6 +312,14 @@ begin NameEntryChanged(Sender); end; +function TFConnectionProperties.GetService: string; +begin + Result := ServiceTypeTable[ServiceTypeTable_Count, 1]; + if ServiceTypeOptionMenu.ItemIndex < ServiceTypeTable_Count - 1 + then Result := ServiceTypeTable[ServiceTypeOptionMenu.ItemIndex + 1, 1] else + if Pos('://', URIEntry.Text) > 1 then Result := Copy(URIEntry.Text, 1, Pos('://', URIEntry.Text) - 1); +end; + end. @@ -193,9 +193,9 @@ type TMounterItem = class TConnMgrItem = class public ConnectionName: string; - URI: string; // generated at runtime ServiceType, Server, Username, Password, TargetDir: string; PluginID: string; // leave blank for default + function GetURI(IncludePassword: boolean): string; end; procedure FillDefaultFstabMounterItems; @@ -2678,7 +2678,7 @@ var Thread: TOpenDirThread; begin if pthread_self = Application.ThreadID then begin DebugMsg(['!! (WARNING): vfs_ask_question_callback called from the main thread, expected spawn from a OpenDirThread']); - HandleVFSAskQuestionCallback(nil, AMessage, Choices, choice); + HandleVFSAskQuestionCallback(FMain.FWidget, AMessage, Choices, choice); Exit; end; @@ -2706,7 +2706,7 @@ var Thread: TOpenDirThread; begin 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(nil, AMessage, default_user, default_domain, flags, username, password, anonymous, domain, password_save); + Result := HandleVFSAskPasswordCallback(FMain.FWidget, AMessage, default_user, default_domain, flags, username, password, anonymous, domain, password_save); Exit; end; @@ -2850,6 +2850,13 @@ begin end; +(********************************************************************************************************************************) +(********************************************************************************************************************************) +function TConnMgrItem.GetURI(IncludePassword: boolean): string; +begin + Result := ConstructURI(IncludePassword, False, ServiceType, Server, Username, Password, TargetDir); +end; + (********************************************************************************************************************************) (********************************************************************************************************************************) diff --git a/UCoreUtils.pas b/UCoreUtils.pas index 87232d7..bcaa927 100644 --- a/UCoreUtils.pas +++ b/UCoreUtils.pas @@ -115,7 +115,7 @@ procedure GetFirstLastPanelColumn(var FirstColumn, LastColumn: integer); procedure SetupColors; -function ConstructURI(HidePasswd: boolean; Protocol, Server, Username, Password, Dir: string): string; +function ConstructURI(IncludePasswd, HidePasswd: boolean; Protocol, Server, Username, Password, Dir: string): string; function URIHidePassword(const SrcURI: string): string; function StrTotimetDef(const S: string; const Default: time_t): time_t; @@ -1038,14 +1038,15 @@ begin end; (********************************************************************************************************************************) -function ConstructURI(HidePasswd: boolean; Protocol, Server, Username, Password, Dir: string): string; +function ConstructURI(IncludePasswd, HidePasswd: boolean; Protocol, Server, Username, Password, Dir: string): string; begin Result := Protocol + '://'; if Length(Username) > 0 then begin Result := Result + Username; - if Length(Password) > 0 then + if (Length(Password) > 0) and IncludePasswd then begin if HidePasswd then Result := Result + ':' + StringOfChar('*', Length(Password)) else Result := Result + ':' + Password; + end; Result := Result + '@'; end; Result := Result + Server; @@ -1256,7 +1256,7 @@ begin GTK_BUTTONS_NONE, '%s', AMessage); if primary <> nil then g_free (primary); - gtk_window_set_title (PGtkWindow(dialog), 'VFS Question'); +// gtk_window_set_title (PGtkWindow(dialog), 'VFS Question'); // First count the items in the list then add the buttons in reverse order while (TOpenPCharArray(choices)[len] <> nil) @@ -1369,6 +1369,7 @@ var widget: PGtkWidget; group: PGSList; remember_box: PGtkWidget; priv: TVFSAskPasswordCallbackPriv; + s: PChar; begin FillChar(priv, sizeof(priv), 0); radio_forget := nil; @@ -1378,7 +1379,7 @@ begin widget := gtk_dialog_new (); priv.dialog := PGtkDialog(widget); window := PGtkWindow(widget); - gtk_window_set_title (window, 'VFS Question'); +// gtk_window_set_title (window, 'VFS Question'); // Set the dialog up with HIG properties gtk_dialog_set_has_separator (priv.dialog, False); @@ -1392,7 +1393,7 @@ begin gtk_dialog_add_buttons (priv.dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - 'Co_nnect', GTK_RESPONSE_OK, + PChar(LANGConnMgr_ConnectButton), GTK_RESPONSE_OK, nil); gtk_dialog_set_default_response (priv.dialog, GTK_RESPONSE_OK); @@ -1419,7 +1420,7 @@ begin vbox := gtk_vbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0); - can_anonymous := (Integer(flags) and Integer(VFS_ASK_PASSWORD_ANONYMOUS_SUPPORTED)) = Integer(VFS_ASK_PASSWORD_ANONYMOUS_SUPPORTED); + can_anonymous := (flags and VFS_ASK_PASSWORD_ANONYMOUS_SUPPORTED) = VFS_ASK_PASSWORD_ANONYMOUS_SUPPORTED; if can_anonymous then begin anon_box := gtk_vbox_new (FALSE, 6); @@ -1436,9 +1437,9 @@ begin end; rows := 0; - if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_PASSWORD)) = Integer(VFS_ASK_PASSWORD_NEED_PASSWORD) then Inc(rows); - if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_USERNAME)) = Integer(VFS_ASK_PASSWORD_NEED_USERNAME) then Inc(rows); - if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_DOMAIN)) = Integer(VFS_ASK_PASSWORD_NEED_DOMAIN) then Inc(rows); + if (flags and VFS_ASK_PASSWORD_NEED_PASSWORD) = VFS_ASK_PASSWORD_NEED_PASSWORD then Inc(rows); + if (flags and VFS_ASK_PASSWORD_NEED_USERNAME) = VFS_ASK_PASSWORD_NEED_USERNAME then Inc(rows); + if (flags and VFS_ASK_PASSWORD_NEED_DOMAIN) = VFS_ASK_PASSWORD_NEED_DOMAIN then Inc(rows); // The table that holds the entries priv.entry_container := gtk_alignment_new (0.0, 0.0, 1.0, 1.0); @@ -1452,34 +1453,47 @@ begin gtk_container_add (GTK_CONTAINER (priv.entry_container), table); Rows := 0; - if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_USERNAME)) = Integer(VFS_ASK_PASSWORD_NEED_USERNAME) then begin + if (flags and VFS_ASK_PASSWORD_NEED_USERNAME) = VFS_ASK_PASSWORD_NEED_USERNAME then begin priv.username_entry := table_add_entry (table, rows, '_Username:', default_user, @priv); Inc(Rows); end; - if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_DOMAIN)) = Integer(VFS_ASK_PASSWORD_NEED_DOMAIN) then begin + if (flags and VFS_ASK_PASSWORD_NEED_DOMAIN) = VFS_ASK_PASSWORD_NEED_DOMAIN then begin priv.domain_entry := table_add_entry (table, rows, '_Domain:', default_domain, @priv); Inc(Rows); end; - if (Integer(flags) and Integer(VFS_ASK_PASSWORD_NEED_PASSWORD)) = Integer(VFS_ASK_PASSWORD_NEED_PASSWORD) then begin + 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); // Inc(Rows); gtk_entry_set_visibility (GTK_ENTRY (priv.password_entry), FALSE); end; - if (Integer(flags) and Integer(VFS_ASK_PASSWORD_SAVING_SUPPORTED)) = Integer(VFS_ASK_PASSWORD_SAVING_SUPPORTED) then begin + 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 remember_box := gtk_vbox_new (FALSE, 6); gtk_box_pack_start (GTK_BOX (vbox), remember_box, FALSE, FALSE, 0); - radio_forget := gtk_radio_button_new_with_mnemonic (nil, 'Forget password _immediately'); + if (flags and VFS_ASK_PASSWORD_SAVING_SUPPORTED) = 0 then s := 'Do not save password' + else s := 'Forget password _immediately'; + radio_forget := gtk_radio_button_new_with_mnemonic (nil, s); gtk_box_pack_start (GTK_BOX (remember_box), radio_forget, FALSE, FALSE, 0); group := gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_forget)); - radio_session := gtk_radio_button_new_with_mnemonic (group, 'Remember password until you _logout'); - gtk_box_pack_start (GTK_BOX (remember_box), radio_session, FALSE, FALSE, 0); + // gnome-keyring only + if (flags and VFS_ASK_PASSWORD_SAVING_SUPPORTED) = VFS_ASK_PASSWORD_SAVING_SUPPORTED then begin + radio_session := gtk_radio_button_new_with_mnemonic (group, 'Remember password until you _logout'); + gtk_box_pack_start (GTK_BOX (remember_box), radio_session, FALSE, FALSE, 0); + group := gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_session)); + end; - group := gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_session)); - radio_remember := gtk_radio_button_new_with_mnemonic (group, 'Remember _forever'); + if (flags and VFS_ASK_PASSWORD_SAVING_SUPPORTED) = 0 then s := '_Save password in Connection Manager' + else s := 'Remember _forever'; + radio_remember := gtk_radio_button_new_with_mnemonic (group, s); gtk_box_pack_start (GTK_BOX (remember_box), radio_remember, FALSE, FALSE, 0); + + // Select to save password when internal saving is supported + if (flags and VFS_ASK_PASSWORD_SAVE_INTERNAL) = VFS_ASK_PASSWORD_SAVE_INTERNAL + then gtk_toggle_button_set_active(PGtkToggleButton(radio_remember), True); end; // The anonymous option will be active by default, ensure the toggled signal is emitted for it. @@ -1495,9 +1509,9 @@ begin if (priv.domain_entry <> nil) and (domain <> nil) then domain^ := g_strdup(gtk_entry_get_text(priv.domain_entry)); if (priv.password_entry <> nil) and (password <> nil) then password^ := g_strdup(gtk_entry_get_text(priv.password_entry)); if (priv.choice_anon <> nil) and (anonymous <> nil) then anonymous^ := Ord(gtk_toggle_button_get_active(PGtkToggleButton(priv.choice_anon))); - if (password_save <> nil) and (radio_forget <> nil) and (radio_session <> nil) and (radio_remember <> nil) then begin + if (password_save <> nil) and (radio_forget <> nil) and (radio_remember <> nil) then begin if gtk_toggle_button_get_active(PGtkToggleButton(radio_forget)) then password_save^ := VFS_PASSWORD_SAVE_NEVER else - if gtk_toggle_button_get_active(PGtkToggleButton(radio_session)) then password_save^ := VFS_PASSWORD_SAVE_FOR_SESSION else + if (radio_session <> nil) and gtk_toggle_button_get_active(PGtkToggleButton(radio_session)) then password_save^ := VFS_PASSWORD_SAVE_FOR_SESSION else if gtk_toggle_button_get_active(PGtkToggleButton(radio_remember)) then password_save^ := VFS_PASSWORD_SAVE_PERMANENTLY; end; end; @@ -1726,6 +1726,7 @@ var ListView: TGTKListView; end; procedure DoThread; + var DialogParent: PGtkWidget; begin try OpenDirThread.AEngine := Engine; @@ -1757,13 +1758,17 @@ var ListView: TGTKListView; if OpenDirThread.VFSAskQuestion_Display then begin OpenDirThread.VFSAskQuestion_Display := False; DebugMsg(['Main thread: displaying question dialog']); - HandleVFSAskQuestionCallback(FRemoteWait.FWidget, OpenDirThread.VFSAskQuestion_Message, OpenDirThread.VFSAskQuestion_Choices, OpenDirThread.VFSAskQuestion_Choice); + if FRemoteWait.Visible then DialogParent := FRemoteWait.FWidget + else DialogParent := FWidget; + HandleVFSAskQuestionCallback(DialogParent, OpenDirThread.VFSAskQuestion_Message, OpenDirThread.VFSAskQuestion_Choices, OpenDirThread.VFSAskQuestion_Choice); OpenDirThread.VFSCallbackEvent.SetEvent; end; if OpenDirThread.VFSAskPassword_Display then begin OpenDirThread.VFSAskPassword_Display := False; DebugMsg(['Main thread: displaying password prompt']); - OpenDirThread.VFSAskPassword_Result := HandleVFSAskPasswordCallback(FRemoteWait.FWidget, + if FRemoteWait.Visible then DialogParent := FRemoteWait.FWidget + else DialogParent := FWidget; + OpenDirThread.VFSAskPassword_Result := HandleVFSAskPasswordCallback(DialogParent, OpenDirThread.VFSAskPassword_Message, OpenDirThread.VFSAskPassword_default_user, OpenDirThread.VFSAskPassword_default_domain, @@ -5958,94 +5963,23 @@ end; (********************************************************************************************************************************) (********************************************************************************************************************************) -procedure vfs_ask_question_callback(const AMessage: PChar; const Choices: PPChar; choice: PInteger; user_data: Pointer); cdecl; -begin -// DebugMsg(['******* vfs_ask_question_callback spawned, user_data = 0x', IntToHex(QWord(user_data), 16), ', ThreadID = 0x', IntToHex(pthread_self, 16)]); - HandleVFSAskQuestionCallback(user_data, AMessage, Choices, choice); -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; -begin -// DebugMsg(['******* vfs_ask_password_callback spawned, user_data = 0x', IntToHex(QWord(user_data), 16), ', ThreadID = 0x', IntToHex(pthread_self, 16)]); - Result := HandleVFSAskPasswordCallback(user_data, AMessage, default_user, default_domain, flags, username, password, anonymous, domain, password_save); -// DebugMsg(['after vfs_ask_password_callback: password = ', password^]); -end; - procedure TFMain.miOpenConnectionClick(Sender: TObject); -var Engine: TVFSEngine; - SourceEngine: TPanelEngine; - i, j: integer; - VFSPlugin: TVFSPlugin; - ConnInfo: TConnMgrItem; - b: boolean; +var b: boolean; begin try InternalLock; - ConnInfo := nil; - + FConnectionManager := TFConnectionManager.Create(Self); + if LeftLastFocused then FConnectionManager.SourcePanelEngine := LeftPanelEngine + else FConnectionManager.SourcePanelEngine := RightPanelEngine; b := FConnectionManager.Run = mbOK; - if FConnectionManager.ListView.Selected <> nil then begin - ConnInfo := FConnectionManager.ListView.Selected.AsPointer(0); - ConfConnMgrActiveItem := FConnectionManager.ListView.Selected.Index; - end; - WriteConnections; // Save the list to the file + if FConnectionManager.ListView.Selected <> nil then ConfConnMgrActiveItem := FConnectionManager.ListView.Selected.Index; + WriteConnections; // Save connection manager data - if b then begin - if PluginList.Count = 0 then begin - Application.MessageBox(LANGThereIsNoModuleAvailable, [mbOK], mbError, mbOK, mbOK); - Exit; - end; - if ConnInfo = nil then Exit; - - // Find the VFS module to use for this connection - VFSPlugin := nil; - if Length(ConnInfo.PluginID) > 0 then - for i := 0 to PluginList.Count - 1 do - if TVFSPlugin(PluginList[i]).VFSName = ConnInfo.PluginID then begin - VFSPlugin := PluginList[i]; - Break; - end; - if VFSPlugin = nil then begin - for i := 0 to PluginList.Count - 1 do begin - if Length(TVFSPlugin(PluginList[i]).Services) > 0 then - for j := 0 to Length(TVFSPlugin(PluginList[i]).Services) - 1 do - if WideCompareText(TVFSPlugin(PluginList[i]).Services[j], ConnInfo.ServiceType) = 0 then begin - VFSPlugin := PluginList[i]; - Break; - end; - if VFSPlugin <> nil then Break; - end; - if VFSPlugin = nil then VFSPlugin := PluginList[0]; // Fallback in hope something else could handle it - end; - - if (LeftLastFocused and (LeftPanelEngine is TVFSEngine)) or ((not LeftLastFocused) and (RightPanelEngine is TVFSEngine)) then - begin - if Application.MessageBox(LANGCloseOpenConnection, [mbYes, mbNo], mbWarning, mbYes, mbNo) <> mbYes then Exit; - CloseVFS(LeftLastFocused, True); - end; - - // Construct the VFS Engine and try to open the connection - if LeftLastFocused then SourceEngine := LeftPanelEngine - else SourceEngine := RightPanelEngine; - Engine := TVFSEngine.Create(VFSPlugin); - Engine.ParentEngine := SourceEngine; - Engine.SavePath := SourceEngine.Path; - - FRemoteWait := TFRemoteWait.Create(Application); - FRemoteWait.ParentForm := FConnectionManager; - FRemoteWait.ShowModal; - Application.ProcessMessages; - b := Engine.VFSOpenURI(UTF8ToStr(ConnInfo.URI), @vfs_ask_question_callback, @vfs_ask_password_callback, FRemoteWait.FWidget); - FRemoteWait.Free; - if not b then begin - Application.MessageBox(LANGCouldntOpenURI, [mbOK], mbError, mbOK, mbOK); - Exit; - end; - if LeftLastFocused then LeftPanelEngine := Engine - else RightPanelEngine := Engine; + if b and (FConnectionManager.ConnectedEngine <> nil) then begin + if FConnectionManager.SourcePanelEngine is TVFSEngine then CloseVFS(LeftLastFocused, True); + if LeftLastFocused then LeftPanelEngine := FConnectionManager.ConnectedEngine + else RightPanelEngine := FConnectionManager.ConnectedEngine; DoRefresh(LeftLastFocused, False, False); end; finally diff --git a/libgtk_kylix/GTKForms.pas b/libgtk_kylix/GTKForms.pas index 0f85652..7b23879 100644 --- a/libgtk_kylix/GTKForms.pas +++ b/libgtk_kylix/GTKForms.pas @@ -1,6 +1,6 @@ (* GTK-Kylix Library: GTKForms - Basic windows (TGTKForm, TGTKDialog), TGTKApplication, TGDKScreen - Version 0.6.27 (last updated 2008-10-11) + Version 0.6.28 (last updated 2008-10-12) Copyright (C) 2007 Tomas Bzatek <tbzatek@users.sourceforge.net> This library is free software; you can redistribute it and/or @@ -194,7 +194,9 @@ type // Some basic types procedure HookSynchronizeWakeup; procedure Initialize; function MessageBox(const Text: string; Buttons: TMessageButtons = [mbOK]; Style: TMessageStyle = mbInfo; - Default: TMessageButton = mbNone; Escape: TMessageButton = mbNone): TMessageButton; + Default: TMessageButton = mbNone; Escape: TMessageButton = mbNone): TMessageButton; overload; + function MessageBox(ParentWindow: PGtkWindow; const Text: string; Buttons: TMessageButtons = [mbOK]; Style: TMessageStyle = mbInfo; + Default: TMessageButton = mbNone; Escape: TMessageButton = mbNone): TMessageButton; overload; procedure ProcessMessages; procedure Run; procedure ShowException(E: Exception); @@ -716,9 +718,18 @@ end; function TGTKApplication.MessageBox(const Text: string; Buttons: TMessageButtons; Style: TMessageStyle; Default, Escape: TMessageButton): TMessageButton; +var DialogParent: PGtkWindow; +begin + if Screen.FormCount > 0 + then DialogParent := PGtkWindow(Screen.Forms[0].FWidget) + else DialogParent := nil; + Result := MessageBox(DialogParent, Text, Buttons, Style, Default, Escape); +end; + +function TGTKApplication.MessageBox(ParentWindow: PGtkWindow; const Text: string; Buttons: TMessageButtons = [mbOK]; Style: TMessageStyle = mbInfo; + Default: TMessageButton = mbNone; Escape: TMessageButton = mbNone): TMessageButton; overload; const TMessageStyleID : array[0..3] of TGtkMessageType = (GTK_MESSAGE_ERROR, GTK_MESSAGE_INFO, GTK_MESSAGE_QUESTION, GTK_MESSAGE_WARNING); var Dialog: PGtkWidget; - DialogParent: PGtkWindow; i: integer; begin if Application.Terminated then @@ -726,10 +737,7 @@ begin Result := Escape; Exit; end; - if Screen.FormCount > 0 - then DialogParent := PGtkWindow(Screen.Forms[0].FWidget) - else DialogParent := nil; - Dialog := gtk_message_dialog_new(DialogParent, GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT, TMessageStyleID[Integer(Style)], + Dialog := gtk_message_dialog_new(ParentWindow, GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT, TMessageStyleID[Integer(Style)], GTK_BUTTONS_NONE, StringToPgchar(Text)); for i := 1 to NumMessageButtons do if TMessageButton(i - 1) in Buttons diff --git a/vfs/UVFSCore.pas b/vfs/UVFSCore.pas index e884a09..ee2a6ca 100644 --- a/vfs/UVFSCore.pas +++ b/vfs/UVFSCore.pas @@ -486,7 +486,7 @@ end; function TVFSEngine.GetPrefix: string; begin if (FGlobs <> nil) and (@FSourcePlugin.FVFSGetPrefix <> nil) - then Result := URIHidePassword(FSourcePlugin.FVFSGetPrefix(FGlobs)) + then Result := FSourcePlugin.FVFSGetPrefix(FGlobs) else Result := 'VFS'; end; diff --git a/vfs/uVFSprototypes.pas b/vfs/uVFSprototypes.pas index 18830aa..7cff78b 100644 --- a/vfs/uVFSprototypes.pas +++ b/vfs/uVFSprototypes.pas @@ -64,6 +64,12 @@ const cVFS_OpenWrite = 1; cVFS_OpenAppend = 2; + VFS_ASK_PASSWORD_NEED_PASSWORD = 1 shl 0; + VFS_ASK_PASSWORD_NEED_USERNAME = 1 shl 1; + 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 type @@ -76,13 +82,10 @@ type // File descriptor for Open, Read, Write, Close, Seek operations TVFSFileDes = Pointer; - TVFSAskPasswordFlags = (VFS_ASK_PASSWORD_NEED_PASSWORD = 1 shl 0, - VFS_ASK_PASSWORD_NEED_USERNAME = 1 shl 1, - VFS_ASK_PASSWORD_NEED_DOMAIN = 1 shl 2, - VFS_ASK_PASSWORD_SAVING_SUPPORTED = 1 shl 3, - VFS_ASK_PASSWORD_ANONYMOUS_SUPPORTED = 1 shl 4); + TVFSAskPasswordFlags = Longint; PVFSPasswordSave = ^TVFSPasswordSave; + // Let plugin save the password, usually to gnome-keyring TVFSPasswordSave = (VFS_PASSWORD_SAVE_NEVER, VFS_PASSWORD_SAVE_FOR_SESSION, VFS_PASSWORD_SAVE_PERMANENTLY); @@ -173,6 +176,7 @@ 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; @@ -265,6 +269,7 @@ type 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; |
