diff --git a/AddIns/ICSharpCode.SharpDevelop.addin b/AddIns/ICSharpCode.SharpDevelop.addin
index 26821c8991..6aaa89443e 100644
--- a/AddIns/ICSharpCode.SharpDevelop.addin
+++ b/AddIns/ICSharpCode.SharpDevelop.addin
@@ -1243,6 +1243,10 @@
+
+
+
+
+
+
+
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/AddWebReferenceDialog.cs b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/AddWebReferenceDialog.cs
index 1756415f37..91b7b0bc5e 100644
--- a/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/AddWebReferenceDialog.cs
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/AddWebReferenceDialog.cs
@@ -22,7 +22,8 @@ namespace ICSharpCode.SharpDevelop.Gui
{
public class AddWebReferenceDialog : System.Windows.Forms.Form
{
- DiscoveryClientProtocol discoveryClientProtocol;
+ WebServiceDiscoveryClientProtocol discoveryClientProtocol;
+ CredentialCache credentialCache = new CredentialCache();
int initialFormWidth;
int initialUrlComboBoxWidth;
string namespacePrefix = String.Empty;
@@ -32,6 +33,7 @@ namespace ICSharpCode.SharpDevelop.Gui
delegate DiscoveryDocument DiscoverAnyAsync(string url);
delegate void DiscoveredWebServicesHandler(DiscoveryClientProtocol protocol);
+ delegate void AuthenticationHandler(Uri uri, string authenticationType);
public AddWebReferenceDialog(IProject project)
{
@@ -431,7 +433,6 @@ namespace ICSharpCode.SharpDevelop.Gui
Cursor = Cursors.WaitCursor;
stopButton.Enabled = true;
webServicesView.Clear();
- StartDiscovery(e.Url);
}
void WebBrowserNavigated(object sender, WebBrowserNavigatedEventArgs e)
@@ -439,6 +440,7 @@ namespace ICSharpCode.SharpDevelop.Gui
Cursor = Cursors.Default;
stopButton.Enabled = false;
urlComboBox.Text = webBrowser.Url.ToString();
+ StartDiscovery(e.Url);
}
void WebBrowserCanGoForwardChanged(object sender, EventArgs e)
@@ -524,6 +526,11 @@ namespace ICSharpCode.SharpDevelop.Gui
/// Starts the search for web services at the specified url.
///
void StartDiscovery(Uri uri)
+ {
+ StartDiscovery(uri, new DiscoveryNetworkCredential(CredentialCache.DefaultNetworkCredentials, DiscoveryNetworkCredential.DefaultAuthenticationType));
+ }
+
+ void StartDiscovery(Uri uri, DiscoveryNetworkCredential credential)
{
// Abort previous discovery.
StopDiscovery();
@@ -532,8 +539,8 @@ namespace ICSharpCode.SharpDevelop.Gui
discoveryUri = uri;
DiscoverAnyAsync asyncDelegate = new DiscoverAnyAsync(discoveryClientProtocol.DiscoverAny);
AsyncCallback callback = new AsyncCallback(DiscoveryCompleted);
- discoveryClientProtocol.Credentials = CredentialCache.DefaultCredentials;
- IAsyncResult result = asyncDelegate.BeginInvoke(uri.AbsoluteUri, callback, discoveryClientProtocol);
+ discoveryClientProtocol.Credentials = credential;
+ IAsyncResult result = asyncDelegate.BeginInvoke(uri.AbsoluteUri, callback, new AsyncDiscoveryState(discoveryClientProtocol, uri, credential));
}
///
@@ -542,7 +549,8 @@ namespace ICSharpCode.SharpDevelop.Gui
///
void DiscoveryCompleted(IAsyncResult result)
{
- DiscoveryClientProtocol protocol = (DiscoveryClientProtocol)result.AsyncState;
+ AsyncDiscoveryState state = (AsyncDiscoveryState)result.AsyncState;
+ WebServiceDiscoveryClientProtocol protocol = state.Protocol;
// Check that we are still waiting for this particular callback.
bool wanted = false;
@@ -555,10 +563,19 @@ namespace ICSharpCode.SharpDevelop.Gui
try {
DiscoverAnyAsync asyncDelegate = (DiscoverAnyAsync)((AsyncResult)result).AsyncDelegate;
DiscoveryDocument doc = asyncDelegate.EndInvoke(result);
+ if (!state.Credential.IsDefaultAuthenticationType) {
+ AddCredential(state.Uri, state.Credential);
+ }
Invoke(handler, new object[] {protocol});
} catch (Exception ex) {
- LoggingService.Error("DiscoveryCompleted", ex);
- Invoke(handler, new object[] {null});
+ if (protocol.IsAuthenticationRequired) {
+ HttpAuthenticationHeader authHeader = protocol.GetAuthenticationHeader();
+ AuthenticationHandler authHandler = new AuthenticationHandler(AuthenticateUser);
+ Invoke(authHandler, new object[] {state.Uri, authHeader.AuthenticationType});
+ } else {
+ LoggingService.Error("DiscoveryCompleted", ex);
+ Invoke(handler, new object[] {null});
+ }
}
}
}
@@ -575,7 +592,7 @@ namespace ICSharpCode.SharpDevelop.Gui
} catch (NotImplementedException) {};
discoveryClientProtocol.Dispose();
}
- discoveryClientProtocol = new DiscoveryClientProtocol();
+ discoveryClientProtocol = new WebServiceDiscoveryClientProtocol();
}
}
@@ -649,7 +666,10 @@ namespace ICSharpCode.SharpDevelop.Gui
MessageService.ShowError(StringParser.Parse("${res:ICSharpCode.SharpDevelop.Gui.Dialogs.AddWebReferenceDialog.InvalidNamespaceError}"));
return;
}
-
+
+ webReference.Name = referenceNameTextBox.Text;
+ webReference.ProxyNamespace = namespaceTextBox.Text;
+
DialogResult = DialogResult.OK;
Close();
} catch (Exception ex) {
@@ -695,5 +715,28 @@ namespace ICSharpCode.SharpDevelop.Gui
webServicesTabPage.Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Gui.Dialogs.AddWebReferenceDialog.WebServicesTabPageTitle}");
webServicesTabPage.ToolTipText = webServicesTabPage.Text;
}
+
+ void AuthenticateUser(Uri uri, string authenticationType)
+ {
+ DiscoveryNetworkCredential credential = (DiscoveryNetworkCredential)credentialCache.GetCredential(uri, authenticationType);
+ if (credential != null) {
+ StartDiscovery(uri, credential);
+ } else {
+ using (UserCredentialsDialog credentialsForm = new UserCredentialsDialog(uri.ToString(), authenticationType)) {
+ if (DialogResult.OK == credentialsForm.ShowDialog()) {
+ StartDiscovery(uri, credentialsForm.Credential);
+ }
+ }
+ }
+ }
+
+ void AddCredential(Uri uri, DiscoveryNetworkCredential credential)
+ {
+ NetworkCredential matchedCredential = credentialCache.GetCredential(uri, credential.AuthenticationType);
+ if (matchedCredential != null) {
+ credentialCache.Remove(uri, credential.AuthenticationType);
+ }
+ credentialCache.Add(uri, credential.AuthenticationType, credential);
+ }
}
}
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/AsyncDiscoveryState.cs b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/AsyncDiscoveryState.cs
new file mode 100644
index 0000000000..3b07f5d935
--- /dev/null
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/AsyncDiscoveryState.cs
@@ -0,0 +1,46 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+
+namespace ICSharpCode.SharpDevelop.Gui
+{
+ ///
+ /// Holds information needed when an async web discovery call has completed.
+ ///
+ public class AsyncDiscoveryState
+ {
+ WebServiceDiscoveryClientProtocol protocol;
+ Uri uri;
+ DiscoveryNetworkCredential credential;
+
+ public WebServiceDiscoveryClientProtocol Protocol {
+ get {
+ return protocol;
+ }
+ }
+
+ public Uri Uri {
+ get {
+ return uri;
+ }
+ }
+
+ public DiscoveryNetworkCredential Credential {
+ get {
+ return credential;
+ }
+ }
+
+ public AsyncDiscoveryState(WebServiceDiscoveryClientProtocol protocol, Uri uri, DiscoveryNetworkCredential credential)
+ {
+ this.protocol = protocol;
+ this.uri = uri;
+ this.credential = credential;
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/DiscoveryNetworkCredential.cs b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/DiscoveryNetworkCredential.cs
new file mode 100644
index 0000000000..7a27da6949
--- /dev/null
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/DiscoveryNetworkCredential.cs
@@ -0,0 +1,43 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Net;
+
+namespace ICSharpCode.SharpDevelop.Gui
+{
+ ///
+ /// Adds an authentication type to the standard NetworkCredential class.
+ ///
+ public class DiscoveryNetworkCredential : NetworkCredential
+ {
+ public const string DefaultAuthenticationType = "Default";
+
+ string authenticationType = String.Empty;
+
+ public DiscoveryNetworkCredential(string userName, string password, string domain, string authenticationType) : base(userName, password, domain)
+ {
+ this.authenticationType = authenticationType;
+ }
+
+ public DiscoveryNetworkCredential(NetworkCredential credential, string authenticationType) : this(credential.UserName, credential.Password, credential.Domain, authenticationType)
+ {
+ }
+
+ public string AuthenticationType {
+ get {
+ return authenticationType;
+ }
+ }
+
+ public bool IsDefaultAuthenticationType {
+ get {
+ return String.Compare(authenticationType, DefaultAuthenticationType, true) == 0;
+ }
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/HttpAuthenticationHeader.cs b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/HttpAuthenticationHeader.cs
new file mode 100644
index 0000000000..408661a030
--- /dev/null
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/HttpAuthenticationHeader.cs
@@ -0,0 +1,72 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Net;
+using System.Text;
+
+namespace ICSharpCode.SharpDevelop.Gui
+{
+ ///
+ /// Represents the WWW-Authenticate HTTP response header.
+ ///
+ public class HttpAuthenticationHeader
+ {
+ string[] authenticationSchemes;
+
+ public HttpAuthenticationHeader(WebHeaderCollection headers)
+ {
+ authenticationSchemes = headers.GetValues("WWW-Authenticate");
+ }
+
+ public override string ToString()
+ {
+ if (HasAuthenticationSchemes) {
+ StringBuilder schemes = new StringBuilder();
+ foreach (string scheme in authenticationSchemes) {
+ schemes.Append("WWW-Authenticate: ");
+ schemes.Append(scheme);
+ schemes.Append("\r\n");
+ }
+ return schemes.ToString();
+ }
+ return String.Empty;
+ }
+
+ ///
+ /// Gets a comma separated list of authentication types.
+ ///
+ public string AuthenticationType {
+ get {
+ if (HasAuthenticationSchemes) {
+ int schemesAdded = 0;
+ StringBuilder authenticationType = new StringBuilder();
+ for (int i = 0; i < authenticationSchemes.Length; ++i) {
+ string scheme = authenticationSchemes[i];
+ int index = scheme.IndexOf(' ');
+ if (index > 0) {
+ scheme = scheme.Substring(0, index);
+ }
+ if (schemesAdded > 0) {
+ authenticationType.Append(",");
+ }
+ authenticationType.Append(scheme);
+ schemesAdded++;
+ }
+ return authenticationType.ToString();
+ }
+ return String.Empty;
+ }
+ }
+
+ bool HasAuthenticationSchemes {
+ get {
+ return authenticationSchemes != null && authenticationSchemes.Length > 0;
+ }
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/UserCredentialsDialog.cs b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/UserCredentialsDialog.cs
new file mode 100644
index 0000000000..e7ed20e155
--- /dev/null
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/UserCredentialsDialog.cs
@@ -0,0 +1,219 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using ICSharpCode.Core;
+using System;
+using System.Drawing;
+using System.Net;
+using System.Windows.Forms;
+
+namespace ICSharpCode.SharpDevelop.Gui
+{
+ public class UserCredentialsDialog : System.Windows.Forms.Form
+ {
+ string authenticationType = String.Empty;
+
+ public UserCredentialsDialog(string url, string authenticationType)
+ {
+ InitializeComponent();
+ this.url.Text = url;
+ this.authenticationType = authenticationType;
+ AddStringResources();
+ }
+
+ public DiscoveryNetworkCredential Credential {
+ get {
+ return new DiscoveryNetworkCredential(userTextBox.Text, passwordTextBox.Text, domainTextBox.Text, authenticationType);
+ }
+ }
+
+ #region Windows Forms Designer generated code
+ ///
+ /// This method is required for Windows Forms designer support.
+ /// Do not change the method contents inside the source code editor. The Forms designer might
+ /// not be able to load this method if it was changed manually.
+ ///
+ private void InitializeComponent()
+ {
+ this.urlLabel = new System.Windows.Forms.Label();
+ this.userNameLabel = new System.Windows.Forms.Label();
+ this.passwordLabel = new System.Windows.Forms.Label();
+ this.domainLabel = new System.Windows.Forms.Label();
+ this.userTextBox = new System.Windows.Forms.TextBox();
+ this.passwordTextBox = new System.Windows.Forms.TextBox();
+ this.domainTextBox = new System.Windows.Forms.TextBox();
+ this.url = new System.Windows.Forms.Label();
+ this.okButton = new System.Windows.Forms.Button();
+ this.cancelButton = new System.Windows.Forms.Button();
+ this.infoLabel = new System.Windows.Forms.Label();
+ this.SuspendLayout();
+ //
+ // urlLabel
+ //
+ this.urlLabel.Location = new System.Drawing.Point(10, 59);
+ this.urlLabel.Name = "urlLabel";
+ this.urlLabel.Size = new System.Drawing.Size(91, 23);
+ this.urlLabel.TabIndex = 0;
+ this.urlLabel.Text = "Url:";
+ this.urlLabel.UseCompatibleTextRendering = true;
+ //
+ // userNameLabel
+ //
+ this.userNameLabel.Location = new System.Drawing.Point(10, 88);
+ this.userNameLabel.Name = "userNameLabel";
+ this.userNameLabel.Size = new System.Drawing.Size(91, 23);
+ this.userNameLabel.TabIndex = 1;
+ this.userNameLabel.Text = "&User name:";
+ this.userNameLabel.UseCompatibleTextRendering = true;
+ //
+ // passwordLabel
+ //
+ this.passwordLabel.Location = new System.Drawing.Point(10, 115);
+ this.passwordLabel.Name = "passwordLabel";
+ this.passwordLabel.Size = new System.Drawing.Size(91, 23);
+ this.passwordLabel.TabIndex = 3;
+ this.passwordLabel.Text = "&Password:";
+ this.passwordLabel.UseCompatibleTextRendering = true;
+ //
+ // domainLabel
+ //
+ this.domainLabel.Location = new System.Drawing.Point(10, 142);
+ this.domainLabel.Name = "domainLabel";
+ this.domainLabel.Size = new System.Drawing.Size(91, 23);
+ this.domainLabel.TabIndex = 5;
+ this.domainLabel.Text = "&Domain:";
+ this.domainLabel.UseCompatibleTextRendering = true;
+ //
+ // userTextBox
+ //
+ this.userTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.userTextBox.Location = new System.Drawing.Point(93, 85);
+ this.userTextBox.Name = "userTextBox";
+ this.userTextBox.Size = new System.Drawing.Size(187, 21);
+ this.userTextBox.TabIndex = 2;
+ //
+ // passwordTextBox
+ //
+ this.passwordTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.passwordTextBox.Location = new System.Drawing.Point(93, 112);
+ this.passwordTextBox.Name = "passwordTextBox";
+ this.passwordTextBox.PasswordChar = '*';
+ this.passwordTextBox.Size = new System.Drawing.Size(187, 21);
+ this.passwordTextBox.TabIndex = 4;
+ //
+ // domainTextBox
+ //
+ this.domainTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.domainTextBox.Location = new System.Drawing.Point(93, 139);
+ this.domainTextBox.Name = "domainTextBox";
+ this.domainTextBox.Size = new System.Drawing.Size(187, 21);
+ this.domainTextBox.TabIndex = 6;
+ //
+ // url
+ //
+ this.url.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.url.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+ this.url.Location = new System.Drawing.Point(93, 57);
+ this.url.Name = "url";
+ this.url.Size = new System.Drawing.Size(187, 21);
+ this.url.TabIndex = 9;
+ this.url.UseCompatibleTextRendering = true;
+ //
+ // okButton
+ //
+ this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
+ this.okButton.Location = new System.Drawing.Point(146, 166);
+ this.okButton.Name = "okButton";
+ this.okButton.Size = new System.Drawing.Size(64, 26);
+ this.okButton.TabIndex = 7;
+ this.okButton.Text = "OK";
+ this.okButton.UseCompatibleTextRendering = true;
+ this.okButton.UseVisualStyleBackColor = true;
+ //
+ // cancelButton
+ //
+ this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.cancelButton.Location = new System.Drawing.Point(216, 166);
+ this.cancelButton.Name = "cancelButton";
+ this.cancelButton.Size = new System.Drawing.Size(64, 26);
+ this.cancelButton.TabIndex = 8;
+ this.cancelButton.Text = "Cancel";
+ this.cancelButton.UseCompatibleTextRendering = true;
+ this.cancelButton.UseVisualStyleBackColor = true;
+ //
+ // infoLabel
+ //
+ this.infoLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.infoLabel.Location = new System.Drawing.Point(12, 9);
+ this.infoLabel.Name = "infoLabel";
+ this.infoLabel.Size = new System.Drawing.Size(267, 48);
+ this.infoLabel.TabIndex = 10;
+ this.infoLabel.Text = "Please supply the credentials to access the specified url.";
+ this.infoLabel.UseCompatibleTextRendering = true;
+ //
+ // UserCredentialsDialog
+ //
+ this.AcceptButton = this.okButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this.cancelButton;
+ this.ClientSize = new System.Drawing.Size(292, 202);
+ this.Controls.Add(this.infoLabel);
+ this.Controls.Add(this.cancelButton);
+ this.Controls.Add(this.okButton);
+ this.Controls.Add(this.url);
+ this.Controls.Add(this.domainTextBox);
+ this.Controls.Add(this.passwordTextBox);
+ this.Controls.Add(this.userTextBox);
+ this.Controls.Add(this.domainLabel);
+ this.Controls.Add(this.passwordLabel);
+ this.Controls.Add(this.userNameLabel);
+ this.Controls.Add(this.urlLabel);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.MinimumSize = new System.Drawing.Size(300, 236);
+ this.Name = "UserCredentialsDialog";
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Discovery Credential";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+ }
+ private System.Windows.Forms.Label infoLabel;
+ private System.Windows.Forms.TextBox passwordTextBox;
+ private System.Windows.Forms.Label userNameLabel;
+ private System.Windows.Forms.Button cancelButton;
+ private System.Windows.Forms.Button okButton;
+ private System.Windows.Forms.Label url;
+ private System.Windows.Forms.TextBox domainTextBox;
+ private System.Windows.Forms.TextBox userTextBox;
+ private System.Windows.Forms.Label domainLabel;
+ private System.Windows.Forms.Label passwordLabel;
+ private System.Windows.Forms.Label urlLabel;
+ #endregion
+
+ void AddStringResources()
+ {
+ Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Gui.Dialogs.UserCredentialsDialog.DialogTitle}");
+ infoLabel.Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Gui.Dialogs.UserCredentialsDialog.InformationLabel}");
+ urlLabel.Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Gui.Dialogs.UserCredentialsDialog.UrlLabel}");
+ userNameLabel.Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Gui.Dialogs.UserCredentialsDialog.UserNameLabel}");
+ passwordLabel.Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Gui.Dialogs.UserCredentialsDialog.PasswordLabel}");
+ domainLabel.Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Gui.Dialogs.UserCredentialsDialog.DomainLabel}");
+ cancelButton.Text = StringParser.Parse("${res:Global.CancelButtonText}");
+ okButton.Text = StringParser.Parse("${res:Global.OKButtonText}");
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/WebReference.cs b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/WebReference.cs
index 6ada4fc3ca..188b3cc25f 100644
--- a/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/WebReference.cs
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/WebReference.cs
@@ -172,6 +172,15 @@ namespace ICSharpCode.SharpDevelop.Gui
}
}
+ public string ProxyNamespace {
+ get {
+ return proxyNamespace;
+ }
+ set {
+ proxyNamespace = value;
+ }
+ }
+
public List Items {
get {
if (items == null) {
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/WebServiceDiscoveryClientProtocol.cs b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/WebServiceDiscoveryClientProtocol.cs
new file mode 100644
index 0000000000..4f671c56b8
--- /dev/null
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/WebServiceDiscoveryClientProtocol.cs
@@ -0,0 +1,50 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+using System.Net;
+using System.Web.Services.Discovery;
+
+namespace ICSharpCode.SharpDevelop.Gui
+{
+ ///
+ /// Custom DiscoveryClientProtocol that determines whether user authentication
+ /// is required.
+ ///
+ public class WebServiceDiscoveryClientProtocol : DiscoveryClientProtocol
+ {
+ HttpWebResponse lastResponseReceived;
+
+ public WebServiceDiscoveryClientProtocol()
+ {
+ }
+
+ public HttpAuthenticationHeader GetAuthenticationHeader()
+ {
+ if (lastResponseReceived != null) {
+ return new HttpAuthenticationHeader(lastResponseReceived.Headers);
+ }
+ return null;
+ }
+
+ public bool IsAuthenticationRequired {
+ get {
+ if (lastResponseReceived != null) {
+ return lastResponseReceived.StatusCode == HttpStatusCode.Unauthorized;
+ }
+ return false;
+ }
+ }
+
+ protected override WebResponse GetWebResponse(WebRequest request)
+ {
+ lastResponseReceived = null;
+ lastResponseReceived = base.GetWebResponse(request) as HttpWebResponse;
+ return lastResponseReceived;
+ }
+ }
+}
diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs
index f408fb4400..b263268e1a 100644
--- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs
+++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs
@@ -53,37 +53,64 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
WebReferenceUrl url = (WebReferenceUrl)node.ProjectItem;
try {
// Discover web services at url.
- DiscoveryClientProtocol protocol = new DiscoveryClientProtocol();
- protocol.DiscoverAny(url.UpdateFromURL);
- protocol.ResolveOneLevel();
-
- // Save web services.
- WebReference webReference = new WebReference(url.Project, url.UpdateFromURL, node.Text, url.Project.RootNamespace, protocol);
- webReference.Save();
-
- // Update project.
- WebReferenceChanges changes = webReference.GetChanges(url.Project);
- if (changes.Changed) {
- foreach (ProjectItem itemRemoved in changes.ItemsRemoved) {
- ProjectService.RemoveProjectItem(url.Project, itemRemoved);
- FileService.RemoveFile(itemRemoved.FileName, false);
- }
- foreach (ProjectItem newItem in changes.NewItems) {
- ProjectService.AddProjectItem(url.Project, newItem);
- FileNode fileNode = new FileNode(newItem.FileName, FileNodeStatus.InProject);
- fileNode.AddTo(node);
+ DiscoveryClientProtocol protocol = DiscoverWebServices(url.UpdateFromURL);
+ if (protocol != null) {
+ // Save web services.
+ WebReference webReference = new WebReference(url.Project, url.UpdateFromURL, node.Text, url.Project.RootNamespace, protocol);
+ webReference.Save();
+
+ // Update project.
+ WebReferenceChanges changes = webReference.GetChanges(url.Project);
+ if (changes.Changed) {
+ foreach (ProjectItem itemRemoved in changes.ItemsRemoved) {
+ ProjectService.RemoveProjectItem(url.Project, itemRemoved);
+ FileService.RemoveFile(itemRemoved.FileName, false);
+ }
+ foreach (ProjectItem newItem in changes.NewItems) {
+ ProjectService.AddProjectItem(url.Project, newItem);
+ FileNode fileNode = new FileNode(newItem.FileName, FileNodeStatus.InProject);
+ fileNode.AddTo(node);
+ }
+ ProjectBrowserPad.Instance.ProjectBrowserControl.TreeView.Sort();
+ url.Project.Save();
}
- ProjectBrowserPad.Instance.ProjectBrowserControl.TreeView.Sort();
- url.Project.Save();
+
+ // Update code completion.
+ ParserService.ParseFile(webReference.WebProxyFileName);
}
-
- // Update code completion.
- ParserService.ParseFile(webReference.WebProxyFileName);
} catch (WebException ex) {
MessageService.ShowError(ex, String.Format(StringParser.Parse("${res:ICSharpCode.SharpDevelop.Commands.ProjectBrowser.RefreshWebReference.ReadServiceDescriptionError}"), url.UpdateFromURL));
}
}
}
+
+ DiscoveryClientProtocol DiscoverWebServices(string url)
+ {
+ WebServiceDiscoveryClientProtocol protocol = new WebServiceDiscoveryClientProtocol();
+ NetworkCredential credential = CredentialCache.DefaultNetworkCredentials;
+ bool retry = true;
+ while (retry) {
+ try {
+ protocol.Credentials = credential;
+ protocol.DiscoverAny(url);
+ protocol.ResolveOneLevel();
+ return protocol;
+ } catch (WebException ex) {
+ if (protocol.IsAuthenticationRequired) {
+ using (UserCredentialsDialog dialog = new UserCredentialsDialog(url, protocol.GetAuthenticationHeader().AuthenticationType)) {
+ if (dialog.ShowDialog() == DialogResult.OK) {
+ credential = dialog.Credential;
+ } else {
+ retry = false;
+ }
+ }
+ } else {
+ throw ex;
+ }
+ }
+ }
+ return null;
+ }
}
public class AddWebReferenceToProject : AbstractMenuCommand
diff --git a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj
index 9246bb2d6e..647e94568d 100644
--- a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj
+++ b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj
@@ -66,6 +66,7 @@
+
diff --git a/src/Main/Base/Test/WebReferences/HttpAuthenticationHeaderTests.cs b/src/Main/Base/Test/WebReferences/HttpAuthenticationHeaderTests.cs
new file mode 100644
index 0000000000..dccea3762f
--- /dev/null
+++ b/src/Main/Base/Test/WebReferences/HttpAuthenticationHeaderTests.cs
@@ -0,0 +1,81 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using ICSharpCode.SharpDevelop.Gui;
+using NUnit.Framework;
+using System;
+using System.Net;
+
+namespace ICSharpCode.SharpDevelop.Tests.WebReferences
+{
+ [TestFixture]
+ public class HttpAuthenticationHeaderTests
+ {
+ [Test]
+ public void IsBasicAuthentication()
+ {
+ WebHeaderCollection headers = new WebHeaderCollection();
+ headers.Add(HttpResponseHeader.WwwAuthenticate, "Basic realm='localhost'");
+ HttpAuthenticationHeader authenticationHeader = new HttpAuthenticationHeader(headers);
+
+ Assert.AreEqual("Basic", authenticationHeader.AuthenticationType);
+ }
+
+ [Test]
+ public void NoHeadersAdded()
+ {
+ WebHeaderCollection headers = new WebHeaderCollection();
+ HttpAuthenticationHeader authenticationHeader = new HttpAuthenticationHeader(headers);
+
+ Assert.AreEqual(String.Empty, authenticationHeader.AuthenticationType);
+ }
+
+ [Test]
+ public void NonStandardAuthenticationHeaderAdded()
+ {
+ WebHeaderCollection headers = new WebHeaderCollection();
+ headers.Add(HttpResponseHeader.WwwAuthenticate, "Foo");
+ HttpAuthenticationHeader authenticationHeader = new HttpAuthenticationHeader(headers);
+
+ Assert.AreEqual("Foo", authenticationHeader.AuthenticationType);
+ }
+
+ [Test]
+ public void IsWindowsAuthentication()
+ {
+ WebHeaderCollection headers = new WebHeaderCollection();
+ headers.Add(HttpResponseHeader.WwwAuthenticate, "Negotiate");
+ headers.Add(HttpResponseHeader.WwwAuthenticate, "NTLM");
+ HttpAuthenticationHeader authenticationHeader = new HttpAuthenticationHeader(headers);
+
+ Assert.AreEqual("Negotiate,NTLM", authenticationHeader.AuthenticationType);
+ }
+
+ [Test]
+ public void ManyAuthenticationSchemesAdded()
+ {
+ WebHeaderCollection headers = new WebHeaderCollection();
+ headers.Add(HttpResponseHeader.WwwAuthenticate, "Negotiate");
+ headers.Add(HttpResponseHeader.WwwAuthenticate, "NTLM");
+ headers.Add(HttpResponseHeader.WwwAuthenticate, "Basic realm='test'");
+ HttpAuthenticationHeader authenticationHeader = new HttpAuthenticationHeader(headers);
+
+ Assert.AreEqual("Negotiate,NTLM,Basic", authenticationHeader.AuthenticationType);
+ }
+
+ [Test]
+ public void DigestAuthenticationSchemeAdded()
+ {
+ WebHeaderCollection headers = new WebHeaderCollection();
+ headers.Add(HttpResponseHeader.WwwAuthenticate, "Digest realm='test'");
+ headers.Add(HttpResponseHeader.WwwAuthenticate, "NTLM");
+ HttpAuthenticationHeader authenticationHeader = new HttpAuthenticationHeader(headers);
+
+ Assert.AreEqual("Digest,NTLM", authenticationHeader.AuthenticationType);
+ }
+ }
+}
diff --git a/src/Main/StartUp/Project/Resources/StringResources.resources b/src/Main/StartUp/Project/Resources/StringResources.resources
index 7ebfa3cad0..ec800d804b 100644
Binary files a/src/Main/StartUp/Project/Resources/StringResources.resources and b/src/Main/StartUp/Project/Resources/StringResources.resources differ