diff options
18 files changed, 88 insertions, 73 deletions
diff --git a/src/DotNetOpenAuth/GlobalSuppressions.cs b/src/DotNetOpenAuth/GlobalSuppressions.cs index 12e3df0..6e9c87b 100644 --- a/src/DotNetOpenAuth/GlobalSuppressions.cs +++ b/src/DotNetOpenAuth/GlobalSuppressions.cs @@ -33,3 +33,10 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "usersetupurl", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "birthdate", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "rehydrated", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Messaging.Bindings")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.ChannelElements")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.SimpleRegistration")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Messages")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "We sign it when producing drops.")] diff --git a/src/DotNetOpenAuth/Messaging/Bindings/StandardExpirationBindingElement.cs b/src/DotNetOpenAuth/Messaging/Bindings/StandardExpirationBindingElement.cs index 2531f67..2722881 100644 --- a/src/DotNetOpenAuth/Messaging/Bindings/StandardExpirationBindingElement.cs +++ b/src/DotNetOpenAuth/Messaging/Bindings/StandardExpirationBindingElement.cs @@ -45,7 +45,7 @@ namespace DotNetOpenAuth.Messaging.Bindings { /// <see cref="IExpiringProtocolMessage"/> interface can be before /// being discarded as too old. /// </summary> - protected internal TimeSpan MaximumMessageAge { + protected internal static TimeSpan MaximumMessageAge { get { return Configuration.DotNetOpenAuthSection.Configuration.Messaging.MaximumMessageLifetime; } } @@ -87,7 +87,7 @@ namespace DotNetOpenAuth.Messaging.Bindings { if (expiringMessage != null) { // Yes the UtcCreationDate is supposed to always be in UTC already, // but just in case a given message failed to guarantee that, we do it here. - DateTime expirationDate = expiringMessage.UtcCreationDate.ToUniversalTime() + this.MaximumMessageAge; + DateTime expirationDate = expiringMessage.UtcCreationDate.ToUniversalTime() + MaximumMessageAge; if (expirationDate < DateTime.UtcNow) { throw new ExpiredMessageException(expirationDate, expiringMessage); } diff --git a/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs b/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs index 752550f..9d2593f 100644 --- a/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs +++ b/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs @@ -152,12 +152,14 @@ namespace DotNetOpenAuth.Messaging { /// Gets a collection of host name literals that should be allowed even if they don't /// pass standard security checks. /// </summary> + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Whitelist", Justification = "Spelling as intended.")] public ICollection<string> WhitelistHosts { get { return this.whitelistHosts; } } /// <summary> /// Gets a collection of host name regular expressions that indicate hosts that should /// be allowed even though they don't pass standard security checks. /// </summary> + [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Whitelist", Justification = "Spelling as intended.")] public ICollection<Regex> WhitelistHostsRegex { get { return this.whitelistHostsRegex; } } /// <summary> @@ -257,7 +259,7 @@ namespace DotNetOpenAuth.Messaging { // We have no copy of the post entity stream to repeat on our manually // cloned HttpWebRequest, so we have to bail. ErrorUtilities.VerifyProtocol(request.Method != "POST", MessagingStrings.UntrustedRedirectsOnPOSTNotSupported); - Uri redirectUri = new Uri(response.FinalUri, response.Headers[HttpResponseHeader.Location]); + Uri redirectUri = new Uri(response.FinalUri, new Uri(response.Headers[HttpResponseHeader.Location])); request = request.Clone(redirectUri); } else { return response; diff --git a/src/DotNetOpenAuth/OAuth/ConsumerBase.cs b/src/DotNetOpenAuth/OAuth/ConsumerBase.cs index ae2e1d1..210864d 100644 --- a/src/DotNetOpenAuth/OAuth/ConsumerBase.cs +++ b/src/DotNetOpenAuth/OAuth/ConsumerBase.cs @@ -93,6 +93,18 @@ namespace DotNetOpenAuth.OAuth { return this.Channel.WebRequestHandler.GetResponse(wr); } + #region IDisposable Members + + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + public void Dispose() { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + /// <summary> /// Prepares an OAuth message that begins an authorization request that will /// redirect the user to the Service Provider to provide that authorization. @@ -163,16 +175,6 @@ namespace DotNetOpenAuth.OAuth { return grantAccess; } - #region IDisposable Members - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() { - this.Dispose(true); - GC.SuppressFinalize(this); - } - /// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> @@ -182,7 +184,5 @@ namespace DotNetOpenAuth.OAuth { this.Channel.Dispose(); } } - - #endregion } } diff --git a/src/DotNetOpenAuth/OAuth/ServiceProvider.cs b/src/DotNetOpenAuth/OAuth/ServiceProvider.cs index 9a706fe..20788fc 100644 --- a/src/DotNetOpenAuth/OAuth/ServiceProvider.cs +++ b/src/DotNetOpenAuth/OAuth/ServiceProvider.cs @@ -380,19 +380,6 @@ namespace DotNetOpenAuth.OAuth { return accessMessage; } - /// <summary> - /// Hooks the channel in order to perform some operations on some outgoing messages. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="DotNetOpenAuth.Messaging.ChannelEventArgs"/> instance containing the event data.</param> - private void OAuthChannel_Sending(object sender, ChannelEventArgs e) { - // Hook to store the token and secret on its way down to the Consumer. - var grantRequestTokenResponse = e.Message as UnauthorizedTokenResponse; - if (grantRequestTokenResponse != null) { - this.TokenManager.StoreNewRequestToken(grantRequestTokenResponse.RequestMessage, grantRequestTokenResponse); - } - } - #region IDisposable Members /// <summary> @@ -414,5 +401,18 @@ namespace DotNetOpenAuth.OAuth { } #endregion + + /// <summary> + /// Hooks the channel in order to perform some operations on some outgoing messages. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="DotNetOpenAuth.Messaging.ChannelEventArgs"/> instance containing the event data.</param> + private void OAuthChannel_Sending(object sender, ChannelEventArgs e) { + // Hook to store the token and secret on its way down to the Consumer. + var grantRequestTokenResponse = e.Message as UnauthorizedTokenResponse; + if (grantRequestTokenResponse != null) { + this.TokenManager.StoreNewRequestToken(grantRequestTokenResponse.RequestMessage, grantRequestTokenResponse); + } + } } } diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs index 61786a1..3b2f740 100644 --- a/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs +++ b/src/DotNetOpenAuth/OpenId/ChannelElements/OpenIdChannel.cs @@ -118,11 +118,6 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { } /// <summary> - /// Gets the extension factory that can be used to register OpenID extensions. - /// </summary> - internal OpenIdExtensionFactory Extensions { get; private set; } - - /// <summary> /// Verifies the integrity and applicability of an incoming message. /// </summary> /// <param name="message">The message just received.</param> diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs index 62e61be..a1b98b8 100644 --- a/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs +++ b/src/DotNetOpenAuth/OpenId/ChannelElements/ReturnToNonceBindingElement.cs @@ -42,11 +42,6 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { private INonceStore nonceStore; /// <summary> - /// The standard expiration binding element used in the channel. - /// </summary> - private StandardExpirationBindingElement expirationElement; - - /// <summary> /// Backing field for the <see cref="Channel"/> property. /// </summary> private Channel channel; @@ -80,7 +75,6 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { } this.channel = value; - this.expirationElement = this.channel.BindingElements.OfType<StandardExpirationBindingElement>().Single(); } } @@ -96,8 +90,8 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { /// <summary> /// Gets the maximum message age from the standard expiration binding element. /// </summary> - private TimeSpan MaximumMessageAge { - get { return this.expirationElement.MaximumMessageAge; } + private static TimeSpan MaximumMessageAge { + get { return StandardExpirationBindingElement.MaximumMessageAge; } } #region IChannelBindingElement Methods @@ -150,7 +144,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements { ErrorUtilities.VerifyProtocol(nonceValue != null, OpenIdStrings.UnsolicitedAssertionsNotAllowedFrom1xOPs); CustomNonce nonce = CustomNonce.Deserialize(nonceValue); - DateTime expirationDate = nonce.CreationDateUtc + this.MaximumMessageAge; + DateTime expirationDate = nonce.CreationDateUtc + MaximumMessageAge; if (expirationDate < DateTime.UtcNow) { throw new ExpiredMessageException(expirationDate, message); } diff --git a/src/DotNetOpenAuth/OpenId/Identifier.cs b/src/DotNetOpenAuth/OpenId/Identifier.cs index 4800ef3..cc051d5 100644 --- a/src/DotNetOpenAuth/OpenId/Identifier.cs +++ b/src/DotNetOpenAuth/OpenId/Identifier.cs @@ -43,6 +43,7 @@ namespace DotNetOpenAuth.OpenId { /// </summary> /// <param name="identifier">The identifier.</param> /// <returns>The particular Identifier instance to represent the value given.</returns> + [SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads", Justification = "Not all identifiers are URIs.")] [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "Our named alternate is Parse.")] public static implicit operator Identifier(string identifier) { if (identifier == null) { @@ -56,6 +57,7 @@ namespace DotNetOpenAuth.OpenId { /// </summary> /// <param name="identifier">The identifier to convert.</param> /// <returns>The result of the conversion.</returns> + [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "We have a Parse function.")] public static implicit operator Identifier(Uri identifier) { if (identifier == null) { return null; @@ -68,6 +70,7 @@ namespace DotNetOpenAuth.OpenId { /// </summary> /// <param name="identifier">The identifier to convert to a string.</param> /// <returns>The result of the conversion.</returns> + [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "We have a Parse function.")] public static implicit operator string(Identifier identifier) { if (identifier == null) { return null; diff --git a/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs b/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs index b16bd7e..77071cf 100644 --- a/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs +++ b/src/DotNetOpenAuth/OpenId/Interop/OpenIdRelyingPartyShim.cs @@ -102,7 +102,6 @@ namespace DotNetOpenAuth.OpenId.Interop { /// <param name="form">The form data that may have been included in the case of a POST request.</param> /// <returns>The Provider's response to a previous authentication request, or null if no response is present.</returns> public AuthenticationResponseShim ProcessAuthentication(string url, string form) { - Uri uri = new Uri(url); OpenIdRelyingParty rp = new OpenIdRelyingParty(null); HttpRequestInfo requestInfo = new HttpRequestInfo { Url = new Uri(url) }; if (form != null) { diff --git a/src/DotNetOpenAuth/OpenId/Provider/IdentityEndpoint.cs b/src/DotNetOpenAuth/OpenId/Provider/IdentityEndpoint.cs index 07ed0ff..7ada51b 100644 --- a/src/DotNetOpenAuth/OpenId/Provider/IdentityEndpoint.cs +++ b/src/DotNetOpenAuth/OpenId/Provider/IdentityEndpoint.cs @@ -192,7 +192,7 @@ namespace DotNetOpenAuth.OpenId.Provider { if (!string.IsNullOrEmpty(this.ProviderEndpointUrl)) { writer.WriteBeginTag("link"); writer.WriteAttribute("rel", this.Protocol.HtmlDiscoveryProviderKey); - writer.WriteAttribute("href", new Uri(MessagingUtilities.GetRequestUrlFromContext(), this.Page.ResolveUrl(this.ProviderEndpointUrl)).AbsoluteUri); + writer.WriteAttribute("href", new Uri(MessagingUtilities.GetRequestUrlFromContext(), new Uri(this.Page.ResolveUrl(this.ProviderEndpointUrl))).AbsoluteUri); writer.Write(">"); writer.WriteEndTag("link"); writer.WriteLine(); @@ -200,7 +200,7 @@ namespace DotNetOpenAuth.OpenId.Provider { if (!string.IsNullOrEmpty(this.ProviderLocalIdentifier)) { writer.WriteBeginTag("link"); writer.WriteAttribute("rel", Protocol.HtmlDiscoveryLocalIdKey); - writer.WriteAttribute("href", new Uri(MessagingUtilities.GetRequestUrlFromContext(), this.Page.ResolveUrl(this.ProviderLocalIdentifier)).AbsoluteUri); + writer.WriteAttribute("href", new Uri(MessagingUtilities.GetRequestUrlFromContext(), new Uri(this.Page.ResolveUrl(this.ProviderLocalIdentifier))).AbsoluteUri); writer.Write(">"); writer.WriteEndTag("link"); writer.WriteLine(); diff --git a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs index 3e4e570..2bea543 100644 --- a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs +++ b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs @@ -249,7 +249,11 @@ namespace DotNetOpenAuth.OpenId.Provider { /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> private void Dispose(bool disposing) { if (disposing) { - this.Channel.Dispose(); + // Tear off the instance member as a local variable for thread safety. + IDisposable channel = this.Channel as IDisposable; + if (channel != null) { + channel.Dispose(); + } } } diff --git a/src/DotNetOpenAuth/OpenId/Provider/StandardProviderApplicationStore.cs b/src/DotNetOpenAuth/OpenId/Provider/StandardProviderApplicationStore.cs index 1867c43..a1afe11 100644 --- a/src/DotNetOpenAuth/OpenId/Provider/StandardProviderApplicationStore.cs +++ b/src/DotNetOpenAuth/OpenId/Provider/StandardProviderApplicationStore.cs @@ -55,12 +55,21 @@ namespace DotNetOpenAuth.OpenId.Provider { /// Gets the best association (the one with the longest remaining life) for a given key. /// </summary> /// <param name="distinguishingFactor">The Uri (for relying parties) or Smart/Dumb (for Providers).</param> - /// <param name="securitySettings">The security settings.</param> + /// <param name="securityRequirements">The security requirements that the returned association must meet.</param> /// <returns> /// The requested association, or null if no unexpired <see cref="Association"/>s exist for the given key. /// </returns> - public Association GetAssociation(AssociationRelyingPartyType distinguishingFactor, SecuritySettings securitySettings) { - return this.associationStore.GetAssociation(distinguishingFactor, securitySettings); + /// <remarks> + /// In the event that multiple associations exist for the given + /// <paramref name="distinguishingFactor"/>, it is important for the + /// implementation for this method to use the <paramref name="securityRequirements"/> + /// to pick the best (highest grade or longest living as the host's policy may dictate) + /// association that fits the security requirements. + /// Associations that are returned that do not meet the security requirements will be + /// ignored and a new association created. + /// </remarks> + public Association GetAssociation(AssociationRelyingPartyType distinguishingFactor, SecuritySettings securityRequirements) { + return this.associationStore.GetAssociation(distinguishingFactor, securityRequirements); } /// <summary> diff --git a/src/DotNetOpenAuth/OpenId/Realm.cs b/src/DotNetOpenAuth/OpenId/Realm.cs index 17df120..b3b86e0 100644 --- a/src/DotNetOpenAuth/OpenId/Realm.cs +++ b/src/DotNetOpenAuth/OpenId/Realm.cs @@ -57,6 +57,7 @@ namespace DotNetOpenAuth.OpenId { /// Initializes a new instance of the <see cref="Realm"/> class. /// </summary> /// <param name="realmUrl">The realm URL to use in the new instance.</param> + [SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads", Justification = "Not all realms are valid URLs (because of wildcards).")] public Realm(string realmUrl) { ErrorUtilities.VerifyArgumentNotNull(realmUrl, "realmUrl"); this.DomainWildcard = Regex.IsMatch(realmUrl, WildcardDetectionPattern); @@ -193,6 +194,8 @@ namespace DotNetOpenAuth.OpenId { /// </summary> /// <param name="uri">The URI that the new Realm instance will represent.</param> /// <returns>The result of the conversion.</returns> + [SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads", Justification = "Not all realms are valid URLs (because of wildcards).")] + [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Not all Realms are valid URLs.")] public static implicit operator Realm(string uri) { return uri != null ? new Realm(uri) : null; } @@ -203,7 +206,7 @@ namespace DotNetOpenAuth.OpenId { /// <param name="uri">The URI to convert to a realm.</param> /// <returns>The result of the conversion.</returns> public static implicit operator Realm(Uri uri) { - return uri != null ? new Realm(uri.AbsoluteUri) : null; + return uri != null ? new Realm(uri) : null; } /// <summary> diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs index f76a5a4..8385ce6 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs @@ -37,11 +37,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { private readonly ServiceEndpoint endpoint; /// <summary> - /// The protocol version used at the Provider. - /// </summary> - private readonly Protocol protocol; - - /// <summary> /// How an association may or should be created or used in the formulation of the /// authentication request. /// </summary> @@ -72,7 +67,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { ErrorUtilities.VerifyArgumentNotNull(relyingParty, "relyingParty"); this.endpoint = endpoint; - this.protocol = endpoint.Protocol; this.RelyingParty = relyingParty; this.Realm = realm; this.ReturnToUrl = returnToUrl; diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs index 3a884f2..89d058b 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdMobileTextBox.cs @@ -273,6 +273,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// <summary> /// Gets or sets the OpenID <see cref="Realm"/> of the relying party web site. /// </summary> + [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "DotNetOpenAuth.OpenId.Realm", Justification = "Using Realm.ctor for validation.")] [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.Uri", Justification = "Using Uri.ctor for validation.")] [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "DotNetOpenAuth.OpenId", Justification = "Using ctor for validation.")] [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Bindable property must be simple type")] @@ -316,7 +317,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { set { if (Page != null && !DesignMode) { // Validate new value by trying to construct a Uri based on it. - new Uri(MessagingUtilities.GetRequestUrlFromContext(), Page.ResolveUrl(value)); // throws an exception on failure. + new Uri(MessagingUtilities.GetRequestUrlFromContext(), new Uri(Page.ResolveUrl(value))); // throws an exception on failure. } else { // We can't fully test it, but it should start with either ~/ or a protocol. if (Regex.IsMatch(value, @"^https?://")) { @@ -571,7 +572,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { if (string.IsNullOrEmpty(this.ReturnToUrl)) { this.Request = consumer.CreateRequest(userSuppliedIdentifier, typedRealm); } else { - Uri returnTo = new Uri(MessagingUtilities.GetRequestUrlFromContext(), this.ReturnToUrl); + Uri returnTo = new Uri(MessagingUtilities.GetRequestUrlFromContext(), new Uri(this.ReturnToUrl)); this.Request = consumer.CreateRequest(userSuppliedIdentifier, typedRealm, returnTo); } this.Request.Mode = this.ImmediateMode ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup; diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs index 7b3d62f..0b32dfc 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs @@ -330,6 +330,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } } + #region IDisposable Members + + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + public void Dispose() { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + /// <summary> /// Determines whether some parameter name belongs to OpenID or this library /// as a protocol or internal parameter name. @@ -479,26 +491,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { return this.CreateRequests(userSuppliedIdentifier, new Realm(realmUrl.Uri)); } - #region IDisposable Members - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() { - this.Dispose(true); - GC.SuppressFinalize(this); - } - /// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> private void Dispose(bool disposing) { if (disposing) { - this.Channel.Dispose(); + // Tear off the instance member as a local variable for thread safety. + IDisposable disposableChannel = this.channel as IDisposable; + if (disposableChannel != null) { + disposableChannel.Dispose(); + } } } - - #endregion } } diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs index a632599..6623fea 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdTextBox.cs @@ -891,7 +891,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { if (string.IsNullOrEmpty(this.ReturnToUrl)) { this.Request = consumer.CreateRequest(userSuppliedIdentifier, typedRealm); } else { - Uri returnTo = new Uri(MessagingUtilities.GetRequestUrlFromContext(), this.ReturnToUrl); + Uri returnTo = new Uri(MessagingUtilities.GetRequestUrlFromContext(), new Uri(this.ReturnToUrl)); this.Request = consumer.CreateRequest(userSuppliedIdentifier, typedRealm, returnTo); } this.Request.Mode = this.ImmediateMode ? AuthenticationRequestMode.Immediate : AuthenticationRequestMode.Setup; diff --git a/src/DotNetOpenAuth/XrdsPublisher.cs b/src/DotNetOpenAuth/XrdsPublisher.cs index f0971a3..26c3aa1 100644 --- a/src/DotNetOpenAuth/XrdsPublisher.cs +++ b/src/DotNetOpenAuth/XrdsPublisher.cs @@ -188,7 +188,7 @@ namespace DotNetOpenAuth { /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param> protected override void Render(HtmlTextWriter writer) { if (this.Enabled && this.Visible && !string.IsNullOrEmpty(this.XrdsUrl)) { - Uri xrdsAddress = new Uri(MessagingUtilities.GetRequestUrlFromContext(), Page.Response.ApplyAppPathModifier(this.XrdsUrl)); + Uri xrdsAddress = new Uri(MessagingUtilities.GetRequestUrlFromContext(), new Uri(Page.Response.ApplyAppPathModifier(this.XrdsUrl))); if ((this.XrdsAdvertisement & XrdsUrlLocations.HttpHeader) != 0) { Page.Response.AddHeader(Yadis.Yadis.HeaderName, xrdsAddress.AbsoluteUri); } |