private void addCredentialButton_Click(object sender, RoutedEventArgs e) { try { ListView listView = this.credentialListView; // create a new CredentialSettings CredentialSettings newItem = new CredentialSettings(); // set its default persistence to Process (i.e. not persistent) // The default value reverted because it was confusing. // newItem.Persistence = CredentialPersistence.Process; // prepare a validator CredentialSettings[] items = listView.Items.Cast <CredentialSettings>().ToArray(); Func <CredentialSettings, string> validator = (s) => { // check whether there is no credential which is for the same end point CredentialSettings conflicting = items.Where(item => s.HasSameEndPoint(item)).FirstOrDefault(); return((conflicting == null) ? null : string.Format(Properties.Resources.SettingsWindow_Message_ConflictingCredential, s.EndPoint)); }; // edit the CredentialSettings CredentialDialog dialog = new CredentialDialog(newItem, validator, endPointEditable: true); dialog.Owner = this; if (dialog.ShowDialog() ?? false) { // add the CredentialSettings AddListItem(listView, dialog.CredentialSettings); } } catch (Exception exception) { ShowErrorDialog(exception.Message); } return; }
/// <summary> /// </summary> /// <remarks> /// GetCredential() call may cause user interaction such as showing a Credential Dialog. /// So its call should be synchronized by locking this.getCredentialLocker /// not to show multiple user interactions at a time. /// </remarks> CredentialSettings IProxyRunner.GetCredential(string endPoint, string realm, bool needUpdate) { // argument checks if (endPoint == null) { throw new ArgumentNullException(nameof(endPoint)); } if (realm == null) { realm = string.Empty; } CredentialSettings credential = null; lock (this.getCredentialLocker) { // state checks IDictionary <string, CredentialSettings> dictionary; lock (this.credentialsLocker) { dictionary = this.dictionary; if (dictionary == null) { throw new ObjectDisposedException(nameof(RunningProxyState)); } if (needUpdate == false) { // try to find the credential for the end point if (dictionary.TryGetValue(endPoint, out credential) == false) { // try to find the credential for the "wildcard" if (dictionary.TryGetValue(string.Empty, out credential) == false) { needUpdate = true; } } } } // update the credential if necessary if (needUpdate) { credential = this.Owner.UpdateCredential(endPoint, realm, credential); if (credential != null) { SetCredential(credential); } } else { Debug.Assert(credential != null); } } // return the clone of the credential not to be changed return(CloneSettings(credential)); }
protected override CredentialSettings UpdateCredential(string endPoint, string realm, CredentialSettings oldCredential) { // argument checks Debug.Assert(endPoint != null); Debug.Assert(realm != null); // may be empty // oldCredential can be null // state checks Debug.Assert(this.app != null); // clone the CredentialSettings CredentialSettings credentialSettings; if (oldCredential != null) { credentialSettings = CredentialSettings.Clone(oldCredential); } else { credentialSettings = new CredentialSettings(); // set default Persistence value to Session (i.e. volatile) // The default value reverted because it was confusing. // credentialSettings.Persistence = CredentialPersistence.Session; } credentialSettings.EndPoint = endPoint; // ask user's credential Func <CredentialSettings> callback = () => { // get the MainWindow // Note that the MainWindow can be accessed only from the GUI thread // (that is, it must be gotten inside this callback) Window mainWindow = this.app.MainWindow; // prepare CredentialDialog CredentialDialog dialog = new CredentialDialog(credentialSettings); dialog.Title = realm; if (mainWindow != null) { dialog.Owner = mainWindow; } // show the credential dialog and get user input this.credentialDialog = dialog; try { return((dialog.ShowDialog() ?? false) ? dialog.CredentialSettings : null); } finally { this.credentialDialog = null; } }; return(this.app.Dispatcher.Invoke <CredentialSettings>(callback)); }
private void SetCredential(CredentialSettings credential) { // argument checks Debug.Assert(credential != null); lock (this.credentialsLocker) { // state checks IDictionary <string, CredentialSettings> dictionary = this.dictionary; Debug.Assert(dictionary != null); // register the credential to the credential list string endPoint = credential.EndPoint; bool changed = false; CredentialSettings oldCredential; if (dictionary.TryGetValue(endPoint, out oldCredential)) { // the credential for the endpoint exists changed = !credential.Equals(oldCredential); } else { // newly added changed = true; } if (changed) { // register the credential this.isCredentialsDirty = true; if (credential.Persistence == CredentialPersistence.Session) { // do not keep in the process state dictionary.Remove(endPoint); } else { dictionary[endPoint] = credential; } } } return; }
private void editCredentialButton_Click(object sender, RoutedEventArgs e) { try { ListView listView = this.credentialListView; // get the selected CredentialSettings CredentialSettings originalItem = listView.SelectedItem as CredentialSettings; if (originalItem == null) { // this item is not editable return; } // create a clone of the selected CredentialSettings CredentialSettings newItem = CredentialSettings.Clone(originalItem); // prepare a validator CredentialSettings[] items = listView.Items.Cast <CredentialSettings>().ToArray(); Func <CredentialSettings, string> validator = (s) => { // check there is no credential which is for the same end point CredentialSettings conflicting = items.Where(item => (item != originalItem && s.HasSameEndPoint(item))).FirstOrDefault(); return((conflicting == null) ? null : string.Format(Properties.Resources.SettingsWindow_Message_ConflictingCredential, s.EndPoint)); }; // edit the clone CredentialDialog dialog = new CredentialDialog(newItem, validator, endPointEditable: true); dialog.Owner = this; if (dialog.ShowDialog() ?? false) { ReplaceSelectedListItemWith(listView, dialog.CredentialSettings); } } catch (Exception exception) { ShowErrorDialog(exception.Message); } return; }
protected override CredentialSettings UpdateCredential(string endPoint, string realm, CredentialSettings oldCredential) { // argument checks Debug.Assert(endPoint != null); Debug.Assert(realm != null); // may be empty return(AskCredentialInfo(endPoint, realm, canSave: this.HasSettingsFile)); }
/// <remarks> /// Note that Dispose() may be called during running this method. /// That is, system shutdown or suspend may cause Dispose() call /// while it executes runner.GetCredential(), which may be opening a CredentialDialog. /// In this case, runner.GetCredential() will return in the next turn /// on the GUI thread cycle after Dispose() is called. /// </remarks> public BasicCredential GetServerBasicCredentials(string endPoint, string realm, bool firstRequest, BasicCredential oldBasicCredentials) { // argument checks if (endPoint == null) { throw new ArgumentNullException(nameof(endPoint)); } // realm can be null // oldBasicCredentials can be null BasicCredential basicCredential; IDictionary <string, BasicCredential> basicCredentialCache; IProxyRunner runner; // the value of the this.serverBasicCredentialCache field is synchronized by locking this lock (this) { // state checks basicCredentialCache = this.serverBasicCredentialCache; if (basicCredentialCache == null) { throw new ObjectDisposedException(this.ComponentName); } runner = this.Runner; } // the contents of the this.serverBasicCredentialCache are synchronized by locking this.credentialCacheLocker lock (this.credentialCacheLocker) { // get value from the cache basicCredentialCache.TryGetValue(endPoint, out basicCredential); // need a new credential? bool needGetCredential; if (basicCredential == null) { needGetCredential = !firstRequest; } else { // try the current credential if the current revision is newer than the caller's. needGetCredential = ((oldBasicCredentials != null) && (basicCredential.Revision <= oldBasicCredentials.Revision)); } // get the credential from the runner if (needGetCredential) { // figure out the next revision number int revision = 1; if (basicCredential != null) { revision = basicCredential.Revision; if (int.MaxValue <= revision) { throw new Exception("An internal counter was overflowed."); } ++revision; } // get the credential from the runner CredentialSettings credential = null; if (runner != null) { credential = runner.GetCredential(endPoint, realm, needUpdate: (basicCredential != null)); } if (credential == null) { // maybe user cancel entering a credential basicCredential = null; } else { basicCredential = new BasicCredential(revision, credential.EnableAssumptionMode, CreateBasicProxyAuthorizationBytes(credential.GetNetworkCredential())); } // update the cache if (basicCredential == null || credential.Persistence == CredentialPersistence.Session) { basicCredentialCache.Remove(endPoint); } else { basicCredentialCache[endPoint] = basicCredential; } } } // adjust for first time if (firstRequest && basicCredential != null && basicCredential.EnableAssumptionMode == false) { // In the first request, the basic credential is returned only if the AssumptionMode is enabled basicCredential = null; } return(basicCredential); }
protected virtual CredentialSettings UpdateCredential(string endPoint, string realm, CredentialSettings oldCredential) { return(null); // no credential by default }
public CredentialDialog(CredentialSettings credentialSettings, Func <CredentialSettings, string> validator = null, bool endPointEditable = false) { // argument checks if (credentialSettings == null) { throw new ArgumentNullException(nameof(credentialSettings)); } // validator can be null if (endPointEditable && credentialSettings.Persistence == CredentialPersistence.Session) { // session mode is useless when endPoint is editable throw new ArgumentException($"Its 'Persistence' property cannot be 'Session' if '{nameof(endPointEditable)}' is true.", nameof(credentialSettings)); } // initialize members this.CredentialSettings = credentialSettings; this.validator = validator; // initialize components InitializeComponent(); this.DataContext = credentialSettings; // EndPoint if (endPointEditable) { // show TextBox to edit EndPoint this.endPointLabel.Visibility = Visibility.Visible; this.endPointTextBox.Visibility = Visibility.Visible; this.endPointTextBox.IsEnabled = true; this.descriptionTextBlock.Visibility = Visibility.Hidden; this.sessionRadioButton.IsEnabled = false; // useless in this mode // this.endPointTextBox.Text is bound to credentialSettings.EndPoint } else { // show EndPoint which asks your credential string endPoint = credentialSettings.EndPoint; if (endPoint == null) { endPoint = "(unidentified proxy)"; } else if (endPoint.Length == 0) { endPoint = "(all proxies)"; } this.descriptionTextBlock.Text = string.Format(Properties.Resources.CredentialDialog_descriptionTextBlock_Text, endPoint); this.endPointLabel.Visibility = Visibility.Hidden; this.endPointTextBox.Visibility = Visibility.Hidden; this.endPointTextBox.IsEnabled = false; this.descriptionTextBlock.Visibility = Visibility.Visible; } // UserName // this.userNameTextBox.Text is bound to credentialSettings.UserName // Password this.passwordBox.Password = credentialSettings.Password; // Persistence // update persistence radio buttons RadioButton radioButton = null; switch (credentialSettings.Persistence) { case CredentialPersistence.Session: radioButton = this.sessionRadioButton; break; case CredentialPersistence.Persistent: radioButton = this.persistentRadioButton; break; default: // CredentialPersistence.Process is default radioButton = this.processRadioButton; break; } radioButton.IsChecked = true; // EnableAssumptionMode // this.enableAssumptionModeCheckBox.IsChecked is bound to credentialSettings.EnableAssumptionMode // set initial focus Control control; if (endPointEditable) { control = this.endPointTextBox; } else { if (string.IsNullOrEmpty(credentialSettings.UserName)) { control = this.userNameTextBox; } else { control = this.passwordBox; } } control.Focus(); return; }