diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2008-12-01 07:37:00 -0800 |
---|---|---|
committer | Andrew <andrewarnott@gmail.com> | 2008-12-01 07:37:00 -0800 |
commit | 9c85108a3a0b242c4ed5ae33da52df16c95c0ce3 (patch) | |
tree | 7aea92ec71dab0d1932f277cd77e4a2823b0c211 /src | |
parent | 98f10d7920e2d957f6aff937b9dd253f84145668 (diff) | |
download | DotNetOpenAuth-9c85108a3a0b242c4ed5ae33da52df16c95c0ce3.zip DotNetOpenAuth-9c85108a3a0b242c4ed5ae33da52df16c95c0ce3.tar.gz DotNetOpenAuth-9c85108a3a0b242c4ed5ae33da52df16c95c0ce3.tar.bz2 |
Lots of stylecop work.
Diffstat (limited to 'src')
20 files changed, 441 insertions, 63 deletions
diff --git a/src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs b/src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs index 94d6f81..6c853af 100644 --- a/src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs +++ b/src/DotNetOpenAuth.Test/Mocks/MockHttpRequest.cs @@ -133,7 +133,7 @@ namespace DotNetOpenAuth.Test.Mocks { directedIdentityAssignedIdentifier, directedIdentityAssignedIdentifier, providerEndpoint.ProviderEndpoint, - new string[] { providerEndpoint.Protocol.ClaimedIdentifierServiceTypeURI }, + providerEndpoint.ProviderDescription, 10, 10); this.RegisterMockXrdsResponse(identityEndpoint); diff --git a/src/DotNetOpenAuth.Test/OpenId/TestSupport.cs b/src/DotNetOpenAuth.Test/OpenId/TestSupport.cs index 665c041..c80fa97 100644 --- a/src/DotNetOpenAuth.Test/OpenId/TestSupport.cs +++ b/src/DotNetOpenAuth.Test/OpenId/TestSupport.cs @@ -144,11 +144,11 @@ namespace DotNetOpenAuth.Test.OpenId { } internal static ServiceEndpoint GetServiceEndpoint(Scenarios scenario, ProtocolVersion providerVersion, int servicePriority, bool useSsl) { + var providerEndpoint = new ProviderEndpointDescription(GetFullUrl("/" + ProviderPage, null, useSsl), new string[] { Protocol.Lookup(providerVersion).ClaimedIdentifierServiceTypeURI }); return ServiceEndpoint.CreateForClaimedIdentifier( GetIdentityUrl(scenario, providerVersion, useSsl), GetDelegateUrl(scenario, useSsl), - GetFullUrl("/" + ProviderPage, null, useSsl), - new string[] { Protocol.Lookup(providerVersion).ClaimedIdentifierServiceTypeURI }, + providerEndpoint, servicePriority, 10); } diff --git a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs index f4433f0..91dd5f4 100644 --- a/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/UriIdentifierTests.cs @@ -375,8 +375,8 @@ namespace DotNetOpenAuth.Test.OpenId { Assert.AreSame(protocol, se.Protocol); Assert.AreEqual(claimedId, se.ClaimedIdentifier); Assert.AreEqual(expectedLocalId, se.ProviderLocalIdentifier); - Assert.AreEqual(expectSreg ? 2 : 1, se.ProviderSupportedServiceTypeUris.Length); - Assert.IsTrue(Array.IndexOf(se.ProviderSupportedServiceTypeUris, protocol.ClaimedIdentifierServiceTypeURI) >= 0); + Assert.AreEqual(expectSreg ? 2 : 1, se.ProviderSupportedServiceTypeUris.Count); + Assert.IsTrue(se.ProviderSupportedServiceTypeUris.Contains(protocol.ClaimedIdentifierServiceTypeURI)); // TODO: re-enable this line once extensions support is added back in. ////Assert.AreEqual(expectSreg, se.IsExtensionSupported(new ClaimsRequest())); diff --git a/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs b/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs index b6b2e55..d84b8b1 100644 --- a/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs +++ b/src/DotNetOpenAuth.Test/OpenId/XriIdentifierTests.cs @@ -463,7 +463,7 @@ uEyb50RJ7DWmXctSC0b3eymZ2lSXxAWNOsNy if (expectedClaimedIdentifier != null) { Assert.IsNotNull(se); Assert.AreEqual(expectedClaimedIdentifier, se.ClaimedIdentifier.ToString(), "i-name {0} discovery resulted in unexpected CanonicalId", iname); - Assert.IsTrue(se.ProviderSupportedServiceTypeUris.Length > 0); + Assert.IsTrue(se.ProviderSupportedServiceTypeUris.Count > 0); } else { Assert.IsNull(se); } diff --git a/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs b/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs index 5678cc4..24a989c 100644 --- a/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs +++ b/src/DotNetOpenAuth/Messaging/UntrustedWebRequestHandler.cs @@ -275,6 +275,13 @@ namespace DotNetOpenAuth.Messaging { #endregion + /// <summary> + /// Determines whether a given host is whitelisted. + /// </summary> + /// <param name="host">The host name to test.</param> + /// <returns> + /// <c>true</c> if the host is whitelisted; otherwise, <c>false</c>. + /// </returns> private bool IsHostWhitelisted(string host) { return this.IsHostInList(host, this.WhitelistHosts, this.WhitelistHostsRegex); } @@ -330,7 +337,7 @@ namespace DotNetOpenAuth.Messaging { /// Determines whether a URI is allowed based on scheme and host name. /// No requireSSL check is done here /// </summary> - /// <param name="uri">The URI.</param> + /// <param name="uri">The URI to test for whether it should be allowed.</param> /// <returns> /// <c>true</c> if [is URI allowable] [the specified URI]; otherwise, <c>false</c>. /// </returns> @@ -389,6 +396,13 @@ namespace DotNetOpenAuth.Messaging { return true; } + /// <summary> + /// Determines whether an IP address is the IPv6 equivalent of "localhost/127.0.0.1". + /// </summary> + /// <param name="ip">The ip address to check.</param> + /// <returns> + /// <c>true</c> if this is a loopback IP address; <c>false</c> otherwise. + /// </returns> private bool IsIPv6Loopback(IPAddress ip) { ErrorUtilities.VerifyArgumentNotNull(ip, "ip"); byte[] addressBytes = ip.GetAddressBytes(); @@ -403,7 +417,11 @@ namespace DotNetOpenAuth.Messaging { return true; } - private HttpWebRequest PrepareRequest(HttpWebRequest request) { + /// <summary> + /// Prepares the request by setting timeout and redirect policies. + /// </summary> + /// <param name="request">The request to prepare.</param> + private void PrepareRequest(HttpWebRequest request) { // Set/override a few properties of the request to apply our policies for untrusted requests. request.ReadWriteTimeout = (int)this.ReadWriteTimeout.TotalMilliseconds; request.Timeout = (int)this.Timeout.TotalMilliseconds; @@ -413,8 +431,6 @@ namespace DotNetOpenAuth.Messaging { // it may include a pass through an unprotected HTTP request. // We have to follow redirects manually. request.AllowAutoRedirect = false; - - return request; } } } diff --git a/src/DotNetOpenAuth/OpenId/Protocol.cs b/src/DotNetOpenAuth/OpenId/Protocol.cs index 77041cb..5f2807b 100644 --- a/src/DotNetOpenAuth/OpenId/Protocol.cs +++ b/src/DotNetOpenAuth/OpenId/Protocol.cs @@ -168,7 +168,7 @@ namespace DotNetOpenAuth.OpenId { /// Attemps to detect the highest OpenID protocol version supported given a set /// of XRDS Service Type URIs included for some service. /// </summary> - internal static Protocol Detect(string[] serviceTypeURIs) { + internal static Protocol Detect(IEnumerable<string> serviceTypeURIs) { if (serviceTypeURIs == null) throw new ArgumentNullException("serviceTypeURIs"); return FindBestVersion(p => p.OPIdentifierServiceTypeURI, serviceTypeURIs) ?? FindBestVersion(p => p.ClaimedIdentifierServiceTypeURI, serviceTypeURIs) ?? diff --git a/src/DotNetOpenAuth/OpenId/ProviderDescription.cs b/src/DotNetOpenAuth/OpenId/ProviderDescription.cs index 0995d93..6a72e06 100644 --- a/src/DotNetOpenAuth/OpenId/ProviderDescription.cs +++ b/src/DotNetOpenAuth/OpenId/ProviderDescription.cs @@ -31,6 +31,11 @@ namespace DotNetOpenAuth.OpenId { this.ProtocolVersion = openIdVersion; } + /// <summary> + /// Initializes a new instance of the <see cref="ProviderEndpointDescription"/> class. + /// </summary> + /// <param name="providerEndpoint">The URI the provider listens on for OpenID requests.</param> + /// <param name="serviceTypeURIs">The set of services offered by this endpoint.</param> internal ProviderEndpointDescription(Uri providerEndpoint, IEnumerable<string> serviceTypeURIs) { ErrorUtilities.VerifyArgumentNotNull(providerEndpoint, "providerEndpoint"); ErrorUtilities.VerifyArgumentNotNull(serviceTypeURIs, "serviceTypeURIs"); diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs index 386e9c9..98a0d3c 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/ServiceEndpoint.cs @@ -6,9 +6,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { using System; - using System.Collections.Generic; + using System.Collections.ObjectModel; using System.Diagnostics; - using System.Globalization; using System.IO; using System.Text; using DotNetOpenAuth.Messaging; @@ -18,20 +17,35 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// </summary> [DebuggerDisplay("ClaimedIdentifier: {ClaimedIdentifier}, ProviderEndpoint: {ProviderEndpoint}, OpenId: {Protocol.Version}")] internal class ServiceEndpoint : IXrdsProviderEndpoint { + /// <summary> + /// The i-name identifier the user actually typed in + /// or the url identifier with the scheme stripped off. + /// </summary> private string friendlyIdentifierForDisplay; + + /// <summary> + /// The OpenID protocol version used at the identity Provider. + /// </summary> private Protocol protocol; + + /// <summary> + /// The @priority given in the XRDS document for this specific OP endpoint. + /// </summary> private int? uriPriority; + + /// <summary> + /// The @priority given in the XRDS document for this service + /// (which may consist of several endpoints). + /// </summary> private int? servicePriority; - private ServiceEndpoint(Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Uri providerEndpoint, Identifier providerLocalIdentifier, string[] providerSupportedServiceTypeUris, int? servicePriority, int? uriPriority) { + private ServiceEndpoint(ProviderEndpointDescription providerEndpoint, Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, int? servicePriority, int? uriPriority) { ErrorUtilities.VerifyArgumentNotNull(claimedIdentifier, "claimedIdentifier"); ErrorUtilities.VerifyArgumentNotNull(providerEndpoint, "providerEndpoint"); - ErrorUtilities.VerifyArgumentNotNull(providerSupportedServiceTypeUris, "providerSupportedServiceTypeUris"); + this.ProviderDescription = providerEndpoint; this.ClaimedIdentifier = claimedIdentifier; this.UserSuppliedIdentifier = userSuppliedIdentifier; - this.ProviderEndpoint = providerEndpoint; this.ProviderLocalIdentifier = providerLocalIdentifier ?? claimedIdentifier; - this.ProviderSupportedServiceTypeUris = providerSupportedServiceTypeUris; this.servicePriority = servicePriority; this.uriPriority = uriPriority; } @@ -42,7 +56,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { private ServiceEndpoint(Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Uri providerEndpoint, Identifier providerLocalIdentifier, Protocol protocol) { this.ClaimedIdentifier = claimedIdentifier; this.UserSuppliedIdentifier = userSuppliedIdentifier; - this.ProviderEndpoint = providerEndpoint; + this.ProviderDescription = new ProviderEndpointDescription(providerEndpoint, protocol.Version); this.ProviderLocalIdentifier = providerLocalIdentifier ?? claimedIdentifier; this.protocol = protocol; } @@ -56,7 +70,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// Obtained by performing discovery on the User-Supplied Identifier. /// This value MUST be an absolute HTTP or HTTPS URL. /// </remarks> - public Uri ProviderEndpoint { get; private set; } + public Uri ProviderEndpoint { + get { return this.ProviderDescription.Endpoint; } + } /* /// <summary> @@ -124,7 +140,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// Gets the list of services available at this OP Endpoint for the /// claimed Identifier. May be null. /// </summary> - public string[] ProviderSupportedServiceTypeUris { get; private set; } + public ReadOnlyCollection<string> ProviderSupportedServiceTypeUris { + get { return this.ProviderDescription.Capabilities; } + } /// <summary> /// Gets the OpenID protocol used by the Provider. @@ -160,6 +178,17 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { #endregion + Version IProviderEndpoint.Version { get { return Protocol.Version; } } + + /// <summary> + /// Gets a value indicating whether the <see cref="ProviderEndpoint"/> is using an encrypted channel. + /// </summary> + internal bool IsSecure { + get { return string.Equals(this.ProviderEndpoint.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase); } + } + + internal ProviderEndpointDescription ProviderDescription { get; set; } + public static bool operator ==(ServiceEndpoint se1, ServiceEndpoint se2) { return se1.EqualsNullSafe(se2); } @@ -176,7 +205,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { if (this.ProviderSupportedServiceTypeUris == null) { throw new InvalidOperationException("Cannot lookup extension support on a rehydrated ServiceEndpoint."); } - return Array.IndexOf(this.ProviderSupportedServiceTypeUris, extensionUri) >= 0; + return this.ProviderSupportedServiceTypeUris.Contains(extensionUri); } ////public bool IsExtensionSupported(IExtension extension) { @@ -212,15 +241,6 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { //// return IsExtensionSupported(extension); ////} - Version IProviderEndpoint.Version { get { return Protocol.Version; } } - - /// <summary> - /// Gets a value indicating whether the <see cref="ProviderEndpoint"/> is using an encrypted channel. - /// </summary> - internal bool IsSecure { - get { return string.Equals(this.ProviderEndpoint.Scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase); } - } - public override bool Equals(object obj) { ServiceEndpoint other = obj as ServiceEndpoint; if (other == null) { @@ -289,25 +309,26 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { return new ServiceEndpoint(claimedIdentifier, userSuppliedIdentifier, providerEndpoint, providerLocalIdentifier, protocol); } - internal static ServiceEndpoint CreateForProviderIdentifier(Identifier providerIdentifier, Uri providerEndpoint, string[] providerSupportedServiceTypeUris, int? servicePriority, int? uriPriority) { - Protocol protocol = Protocol.Detect(providerSupportedServiceTypeUris); + internal static ServiceEndpoint CreateForProviderIdentifier(Identifier providerIdentifier, ProviderEndpointDescription providerEndpoint, int? servicePriority, int? uriPriority) { + ErrorUtilities.VerifyArgumentNotNull(providerEndpoint, "providerEndpoint"); + + Protocol protocol = Protocol.Detect(providerEndpoint.Capabilities); return new ServiceEndpoint( + providerEndpoint, protocol.ClaimedIdentifierForOPIdentifier, providerIdentifier, - providerEndpoint, protocol.ClaimedIdentifierForOPIdentifier, - providerSupportedServiceTypeUris, servicePriority, uriPriority); } - internal static ServiceEndpoint CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier providerLocalIdentifier, Uri providerEndpoint, string[] providerSupportedServiceTypeUris, int? servicePriority, int? uriPriority) { - return CreateForClaimedIdentifier(claimedIdentifier, null, providerLocalIdentifier, providerEndpoint, providerSupportedServiceTypeUris, servicePriority, uriPriority); + internal static ServiceEndpoint CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier providerLocalIdentifier, ProviderEndpointDescription providerEndpoint, int? servicePriority, int? uriPriority) { + return CreateForClaimedIdentifier(claimedIdentifier, null, providerLocalIdentifier, providerEndpoint, servicePriority, uriPriority); } - internal static ServiceEndpoint CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, Uri providerEndpoint, string[] providerSupportedServiceTypeUris, int? servicePriority, int? uriPriority) { - return new ServiceEndpoint(claimedIdentifier, userSuppliedIdentifier, providerEndpoint, providerLocalIdentifier, providerSupportedServiceTypeUris, servicePriority, uriPriority); + internal static ServiceEndpoint CreateForClaimedIdentifier(Identifier claimedIdentifier, Identifier userSuppliedIdentifier, Identifier providerLocalIdentifier, ProviderEndpointDescription providerEndpoint, int? servicePriority, int? uriPriority) { + return new ServiceEndpoint(providerEndpoint, claimedIdentifier, userSuppliedIdentifier, providerLocalIdentifier, servicePriority, uriPriority); } /// <summary> diff --git a/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs b/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs index 56851cf..112506b 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs @@ -39,6 +39,12 @@ namespace DotNetOpenAuth.OpenId { /// </summary> public Protocol Protocol { get; private set; } + /// <summary> + /// Derives the highest OpenID protocol that this library and the OpenID Provider have + /// in common. + /// </summary> + /// <param name="supportedServiceTypeUris">The supported service type URIs.</param> + /// <returns>The best OpenID protocol version to use when communicating with this Provider.</returns> private static Protocol GetProtocolFromServices(string[] supportedServiceTypeUris) { Protocol protocol = Protocol.FindBestVersion(p => p.RPReturnToTypeURI, supportedServiceTypeUris); if (protocol == null) { diff --git a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs index 194dafe..af8dd66 100644 --- a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs +++ b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs @@ -196,6 +196,13 @@ namespace DotNetOpenAuth.OpenId { return true; } + /// <summary> + /// Performs discovery on the Identifier. + /// </summary> + /// <param name="requestHandler">The web request handler to use for discovery.</param> + /// <returns> + /// An initialized structure containing the discovered provider endpoint information. + /// </returns> internal override IEnumerable<ServiceEndpoint> Discover(IDirectSslWebRequestHandler requestHandler) { List<ServiceEndpoint> endpoints = new List<ServiceEndpoint>(); @@ -353,7 +360,8 @@ namespace DotNetOpenAuth.OpenId { // Choose the TypeURI to match the OpenID version detected. string[] typeURIs = { discoveredProtocol.ClaimedIdentifierServiceTypeURI }; - return ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, providerLocalIdentifier, providerEndpoint, typeURIs, (int?)null, (int?)null); + var providerDescription = new ProviderEndpointDescription(providerEndpoint, typeURIs); + return ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, providerLocalIdentifier, providerDescription, (int?)null, (int?)null); } /// <summary> diff --git a/src/DotNetOpenAuth/OpenId/XriIdentifier.cs b/src/DotNetOpenAuth/OpenId/XriIdentifier.cs index 058a8a4..22e1f7c 100644 --- a/src/DotNetOpenAuth/OpenId/XriIdentifier.cs +++ b/src/DotNetOpenAuth/OpenId/XriIdentifier.cs @@ -149,6 +149,13 @@ namespace DotNetOpenAuth.OpenId { || xri.StartsWith(XriScheme, StringComparison.OrdinalIgnoreCase); } + /// <summary> + /// Performs discovery on the Identifier. + /// </summary> + /// <param name="requestHandler">The web request handler to use for discovery.</param> + /// <returns> + /// An initialized structure containing the discovered provider endpoint information. + /// </returns> internal override IEnumerable<ServiceEndpoint> Discover(IDirectSslWebRequestHandler requestHandler) { return this.DownloadXrds(requestHandler).CreateServiceEndpoints(this); } @@ -157,6 +164,9 @@ namespace DotNetOpenAuth.OpenId { /// Performs discovery on THIS identifier, but generates <see cref="ServiceEndpoint"/> /// instances that treat another given identifier as the user-supplied identifier. /// </summary> + /// <param name="requestHandler">The request handler to use in discovery.</param> + /// <param name="userSuppliedIdentifier">The user supplied identifier, which may differ from this XRI instance due to multiple discovery steps.</param> + /// <returns>A list of service endpoints offered for this identifier.</returns> internal IEnumerable<ServiceEndpoint> Discover(IDirectSslWebRequestHandler requestHandler, XriIdentifier userSuppliedIdentifier) { return this.DownloadXrds(requestHandler).CreateServiceEndpoints(userSuppliedIdentifier); } @@ -209,6 +219,11 @@ namespace DotNetOpenAuth.OpenId { return xri; } + /// <summary> + /// Downloads the XRDS document for this XRI. + /// </summary> + /// <param name="requestHandler">The request handler.</param> + /// <returns>The XRDS document.</returns> private XrdsDocument DownloadXrds(IDirectSslWebRequestHandler requestHandler) { XrdsDocument doc; using (var xrdsResponse = Yadis.Request(requestHandler, this.XrdsUrl, this.IsDiscoverySecureEndToEnd)) { diff --git a/src/DotNetOpenAuth/Util.cs b/src/DotNetOpenAuth/Util.cs index 5ee7302..00ba56f 100644 --- a/src/DotNetOpenAuth/Util.cs +++ b/src/DotNetOpenAuth/Util.cs @@ -54,8 +54,12 @@ namespace DotNetOpenAuth { /// <summary> /// Prepares a dictionary for printing as a string. /// </summary> + /// <typeparam name="K">The type of the key.</typeparam> + /// <typeparam name="V">The type of the value.</typeparam> + /// <param name="pairs">The dictionary or sequence of name-value pairs.</param> + /// <returns>An object whose ToString method will perform the actual work of generating the string.</returns> /// <remarks> - /// The work isn't done until (and if) the + /// The work isn't done until (and if) the /// <see cref="Object.ToString"/> method is actually called, which makes it great /// for logging complex objects without being in a conditional block. /// </remarks> @@ -72,10 +76,24 @@ namespace DotNetOpenAuth { }); } + /// <summary> + /// Offers deferred ToString processing for a list of elements, that are assumed + /// to generate just a single-line string. + /// </summary> + /// <typeparam name="T">The type of elements contained in the list.</typeparam> + /// <param name="list">The list of elements.</param> + /// <returns>An object whose ToString method will perform the actual work of generating the string.</returns> internal static object ToStringDeferred<T>(this IEnumerable<T> list) { return ToStringDeferred<T>(list, false); } + /// <summary> + /// Offers deferred ToString processing for a list of elements. + /// </summary> + /// <typeparam name="T">The type of elements contained in the list.</typeparam> + /// <param name="list">The list of elements.</param> + /// <param name="multiLineElements">if set to <c>true</c>, special formatting will be applied to the output to make it clear where one element ends and the next begins.</param> + /// <returns>An object whose ToString method will perform the actual work of generating the string.</returns> internal static object ToStringDeferred<T>(this IEnumerable<T> list, bool multiLineElements) { return new DelayedToString<IEnumerable<T>>( list, @@ -119,24 +137,37 @@ namespace DotNetOpenAuth { }); } - internal static HttpWebRequest CreatePostRequest(Uri requestUri, string body) { - HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri); - request.ContentType = "application/x-www-form-urlencoded"; - request.ContentLength = body.Length; - request.Method = "POST"; - return request; - } - + /// <summary> + /// Manages an individual deferred ToString call. + /// </summary> + /// <typeparam name="T">The type of object to be serialized as a string.</typeparam> private class DelayedToString<T> { + /// <summary> + /// The object that will be serialized if called upon. + /// </summary> private T obj; + /// <summary> + /// The method used to serialize <see cref="obj"/> to string form. + /// </summary> private Func<T, string> toString; + /// <summary> + /// Initializes a new instance of the DelayedToString class. + /// </summary> + /// <param name="obj">The object that may be serialized to string form.</param> + /// <param name="toString">The method that will serialize the object if called upon.</param> public DelayedToString(T obj, Func<T, string> toString) { this.obj = obj; this.toString = toString; } + /// <summary> + /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>. + /// </summary> + /// <returns> + /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>. + /// </returns> public override string ToString() { return this.toString(this.obj); } diff --git a/src/DotNetOpenAuth/Xrds/ServiceElement.cs b/src/DotNetOpenAuth/Xrds/ServiceElement.cs index ce9cd49..69b77ba 100644 --- a/src/DotNetOpenAuth/Xrds/ServiceElement.cs +++ b/src/DotNetOpenAuth/Xrds/ServiceElement.cs @@ -7,18 +7,33 @@ namespace DotNetOpenAuth.Xrds { using System; using System.Collections.Generic; + using System.Linq; using System.Xml.XPath; using DotNetOpenAuth.OpenId; + /// <summary> + /// The Service element in an XRDS document. + /// </summary> internal class ServiceElement : XrdsNode, IComparable<ServiceElement> { + /// <summary> + /// Initializes a new instance of the <see cref="ServiceElement"/> class. + /// </summary> + /// <param name="serviceElement">The service element.</param> + /// <param name="parent">The parent.</param> public ServiceElement(XPathNavigator serviceElement, XrdElement parent) : base(serviceElement, parent) { } + /// <summary> + /// Gets the XRD parent element. + /// </summary> public XrdElement Xrd { get { return (XrdElement)ParentNode; } } + /// <summary> + /// Gets the priority. + /// </summary> public int? Priority { get { XPathNavigator n = Node.SelectSingleNode("@priority", XmlNamespaceResolver); @@ -26,6 +41,9 @@ namespace DotNetOpenAuth.Xrds { } } + /// <summary> + /// Gets the URI child elements. + /// </summary> public IEnumerable<UriElement> UriElements { get { List<UriElement> uris = new List<UriElement>(); @@ -37,6 +55,10 @@ namespace DotNetOpenAuth.Xrds { } } + /// <summary> + /// Gets the type child elements. + /// </summary> + /// <value>The type elements.</value> public IEnumerable<TypeElement> TypeElements { get { foreach (XPathNavigator node in Node.Select("xrd:Type", XmlNamespaceResolver)) { @@ -45,18 +67,18 @@ namespace DotNetOpenAuth.Xrds { } } + /// <summary> + /// Gets the type child element's URIs. + /// </summary> public string[] TypeElementUris { get { - XPathNodeIterator types = Node.Select("xrd:Type", XmlNamespaceResolver); - string[] typeUris = new string[types.Count]; - int i = 0; - foreach (XPathNavigator type in types) { - typeUris[i++] = type.Value; - } - return typeUris; + return this.TypeElements.Select(type => type.Uri).ToArray(); } } + /// <summary> + /// Gets the OP Local Identifier. + /// </summary> public Identifier ProviderLocalIdentifier { get { var n = Node.SelectSingleNode("xrd:LocalID", XmlNamespaceResolver) @@ -67,6 +89,21 @@ namespace DotNetOpenAuth.Xrds { #region IComparable<ServiceElement> Members + /// <summary> + /// Compares the current object with another object of the same type. + /// </summary> + /// <param name="other">An object to compare with this object.</param> + /// <returns> + /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has the following meanings: + /// Value + /// Meaning + /// Less than zero + /// This object is less than the <paramref name="other"/> parameter. + /// Zero + /// This object is equal to <paramref name="other"/>. + /// Greater than zero + /// This object is greater than <paramref name="other"/>. + /// </returns> public int CompareTo(ServiceElement other) { if (other == null) { return -1; diff --git a/src/DotNetOpenAuth/Xrds/TypeElement.cs b/src/DotNetOpenAuth/Xrds/TypeElement.cs index 2770108..f6c2217 100644 --- a/src/DotNetOpenAuth/Xrds/TypeElement.cs +++ b/src/DotNetOpenAuth/Xrds/TypeElement.cs @@ -7,11 +7,22 @@ namespace DotNetOpenAuth.Xrds { using System.Xml.XPath; + /// <summary> + /// The Type element in an XRDS document. + /// </summary> internal class TypeElement : XrdsNode { + /// <summary> + /// Initializes a new instance of the <see cref="TypeElement"/> class. + /// </summary> + /// <param name="typeElement">The type element.</param> + /// <param name="parent">The parent.</param> public TypeElement(XPathNavigator typeElement, ServiceElement parent) : base(typeElement, parent) { } + /// <summary> + /// Gets the URI. + /// </summary> public string Uri { get { return Node.Value; } } diff --git a/src/DotNetOpenAuth/Xrds/UriElement.cs b/src/DotNetOpenAuth/Xrds/UriElement.cs index 8dbfad1..19f1be3 100644 --- a/src/DotNetOpenAuth/Xrds/UriElement.cs +++ b/src/DotNetOpenAuth/Xrds/UriElement.cs @@ -8,11 +8,22 @@ namespace DotNetOpenAuth.Xrds { using System; using System.Xml.XPath; + /// <summary> + /// The Uri element in an XRDS document. + /// </summary> internal class UriElement : XrdsNode, IComparable<UriElement> { + /// <summary> + /// Initializes a new instance of the <see cref="UriElement"/> class. + /// </summary> + /// <param name="uriElement">The URI element.</param> + /// <param name="service">The service.</param> public UriElement(XPathNavigator uriElement, ServiceElement service) : base(uriElement, service) { } + /// <summary> + /// Gets the priority. + /// </summary> public int? Priority { get { XPathNavigator n = Node.SelectSingleNode("@priority", XmlNamespaceResolver); @@ -20,16 +31,37 @@ namespace DotNetOpenAuth.Xrds { } } + /// <summary> + /// Gets the URI. + /// </summary> public Uri Uri { get { return new Uri(Node.Value); } } + /// <summary> + /// Gets the parent service. + /// </summary> public ServiceElement Service { get { return (ServiceElement)ParentNode; } } #region IComparable<UriElement> Members + /// <summary> + /// Compares the current object with another object of the same type. + /// </summary> + /// <param name="other">An object to compare with this object.</param> + /// <returns> + /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has the following meanings: + /// Value + /// Meaning + /// Less than zero + /// This object is less than the <paramref name="other"/> parameter. + /// Zero + /// This object is equal to <paramref name="other"/>. + /// Greater than zero + /// This object is greater than <paramref name="other"/>. + /// </returns> public int CompareTo(UriElement other) { if (other == null) { return -1; diff --git a/src/DotNetOpenAuth/Xrds/XrdElement.cs b/src/DotNetOpenAuth/Xrds/XrdElement.cs index e52eb77..72c5078 100644 --- a/src/DotNetOpenAuth/Xrds/XrdElement.cs +++ b/src/DotNetOpenAuth/Xrds/XrdElement.cs @@ -13,11 +13,23 @@ namespace DotNetOpenAuth.Xrds { using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OpenId; + /// <summary> + /// The Xrd element in an XRDS document. + /// </summary> internal class XrdElement : XrdsNode { + /// <summary> + /// Initializes a new instance of the <see cref="XrdElement"/> class. + /// </summary> + /// <param name="xrdElement">The XRD element.</param> + /// <param name="parent">The parent.</param> public XrdElement(XPathNavigator xrdElement, XrdsDocument parent) : base(xrdElement, parent) { } + /// <summary> + /// Gets the child service elements. + /// </summary> + /// <value>The services.</value> public IEnumerable<ServiceElement> Services { get { // We should enumerate them in priority order @@ -30,12 +42,21 @@ namespace DotNetOpenAuth.Xrds { } } + /// <summary> + /// Gets a value indicating whether this XRD element's resolution at the XRI resolver was successful. + /// </summary> + /// <value> + /// <c>true</c> if this XRD's resolution was successful; otherwise, <c>false</c>. + /// </value> public bool IsXriResolutionSuccessful { get { return this.XriResolutionStatusCode == 100; } } + /// <summary> + /// Gets the canonical ID (i-number) for this element. + /// </summary> public string CanonicalID { get { var n = Node.SelectSingleNode("xrd:CanonicalID", XmlNamespaceResolver); @@ -43,6 +64,9 @@ namespace DotNetOpenAuth.Xrds { } } + /// <summary> + /// Gets a value indicating whether the <see cref="CanonicalID"/> was verified. + /// </summary> public bool IsCanonicalIdVerified { get { var n = Node.SelectSingleNode("xrd:Status", XmlNamespaceResolver); @@ -64,6 +88,9 @@ namespace DotNetOpenAuth.Xrds { get { return this.SearchForServiceTypeUris(p => p.ClaimedIdentifierServiceTypeURI); } } + /// <summary> + /// Gets the services that would be discoverable at an RP for return_to verification. + /// </summary> public IEnumerable<ServiceElement> OpenIdRelyingPartyReturnToServices { get { return this.SearchForServiceTypeUris(p => p.RPReturnToTypeURI); } } @@ -79,6 +106,9 @@ namespace DotNetOpenAuth.Xrds { } } + /// <summary> + /// Gets the XRI resolution status code. + /// </summary> private int XriResolutionStatusCode { get { var n = Node.SelectSingleNode("xrd:Status", XmlNamespaceResolver); @@ -90,6 +120,12 @@ namespace DotNetOpenAuth.Xrds { } } + /// <summary> + /// Searches for service sub-elements that have Type URI sub-elements that match + /// one that we have for a known OpenID protocol version. + /// </summary> + /// <param name="p">A function that selects what element of the OpenID Protocol we're interested in finding.</param> + /// <returns>A sequence of service elements that match the search criteria, sorted in XRDS @priority attribute order.</returns> private IEnumerable<ServiceElement> SearchForServiceTypeUris(Func<Protocol, string> p) { var xpath = new StringBuilder(); xpath.Append("xrd:Service["); diff --git a/src/DotNetOpenAuth/Xrds/XrdsDocument.cs b/src/DotNetOpenAuth/Xrds/XrdsDocument.cs index bc66f6e..016b58c 100644 --- a/src/DotNetOpenAuth/Xrds/XrdsDocument.cs +++ b/src/DotNetOpenAuth/Xrds/XrdsDocument.cs @@ -14,7 +14,14 @@ namespace DotNetOpenAuth.Xrds { using DotNetOpenAuth.OpenId; using DotNetOpenAuth.OpenId.RelyingParty; + /// <summary> + /// An XRDS document. + /// </summary> internal class XrdsDocument : XrdsNode { + /// <summary> + /// Initializes a new instance of the <see cref="XrdsDocument"/> class. + /// </summary> + /// <param name="xrdsNavigator">The root node of the XRDS document.</param> public XrdsDocument(XPathNavigator xrdsNavigator) : base(xrdsNavigator) { XmlNamespaceResolver.AddNamespace("xrd", XrdsNode.XrdNamespace); @@ -22,12 +29,23 @@ namespace DotNetOpenAuth.Xrds { XmlNamespaceResolver.AddNamespace("openid10", Protocol.V10.XmlNamespace); } + /// <summary> + /// Initializes a new instance of the <see cref="XrdsDocument"/> class. + /// </summary> + /// <param name="reader">The Xml reader positioned at the root node of the XRDS document.</param> public XrdsDocument(XmlReader reader) : this(new XPathDocument(reader).CreateNavigator()) { } + /// <summary> + /// Initializes a new instance of the <see cref="XrdsDocument"/> class. + /// </summary> + /// <param name="xml">The text that is the XRDS document.</param> public XrdsDocument(string xml) : this(new XPathDocument(new StringReader(xml)).CreateNavigator()) { } + /// <summary> + /// Gets the XRD child elements of the document. + /// </summary> public IEnumerable<XrdElement> XrdElements { get { // We may be looking at a full XRDS document (in the case of YADIS discovery) @@ -44,10 +62,19 @@ namespace DotNetOpenAuth.Xrds { } } + /// <summary> + /// Gets a value indicating whether all child XRD elements were resolved successfully. + /// </summary> internal bool IsXrdResolutionSuccessful { get { return this.XrdElements.All(xrd => xrd.IsXriResolutionSuccessful); } } + /// <summary> + /// Creates the service endpoints described in this document, useful for requesting + /// authentication of one of the OpenID Providers that result from it. + /// </summary> + /// <param name="claimedIdentifier">The claimed identifier that was used to discover this XRDS document.</param> + /// <returns>A sequence of OpenID Providers that can assert ownership of the <paramref name="claimedIdentifier"/>.</returns> internal IEnumerable<ServiceEndpoint> CreateServiceEndpoints(UriIdentifier claimedIdentifier) { var endpoints = new List<ServiceEndpoint>(); endpoints.AddRange(this.GenerateOPIdentifierServiceEndpoints(claimedIdentifier)); @@ -62,6 +89,12 @@ namespace DotNetOpenAuth.Xrds { return endpoints; } + /// <summary> + /// Creates the service endpoints described in this document, useful for requesting + /// authentication of one of the OpenID Providers that result from it. + /// </summary> + /// <param name="userSuppliedIdentifier">The user-supplied i-name that was used to discover this XRDS document.</param> + /// <returns>A sequence of OpenID Providers that can assert ownership of the canonical ID given in this document.</returns> internal IEnumerable<ServiceEndpoint> CreateServiceEndpoints(XriIdentifier userSuppliedIdentifier) { var endpoints = new List<ServiceEndpoint>(); endpoints.AddRange(this.GenerateOPIdentifierServiceEndpoints(userSuppliedIdentifier)); @@ -76,25 +109,52 @@ namespace DotNetOpenAuth.Xrds { return endpoints; } + /// <summary> + /// Finds the Relying Party return_to receiving endpoints. + /// </summary> + /// <returns>A sequence of Relying Party descriptors for the return_to endpoints.</returns> + /// <remarks> + /// This is useful for Providers to send unsolicited assertions to Relying Parties, + /// or for Provider's to perform RP discovery/verification as part of authentication. + /// </remarks> internal IEnumerable<RelyingPartyEndpointDescription> FindRelyingPartyReceivingEndpoints() { return from service in this.FindReturnToServices() from uri in service.UriElements select new RelyingPartyEndpointDescription(uri.Uri, service.TypeElementUris); } + /// <summary> + /// Generates OpenID Providers that can authenticate using directed identity. + /// </summary> + /// <param name="opIdentifier">The OP Identifier entered (and resolved) by the user.</param> + /// <returns>A sequence of the providers that can offer directed identity services.</returns> private IEnumerable<ServiceEndpoint> GenerateOPIdentifierServiceEndpoints(Identifier opIdentifier) { return from service in this.FindOPIdentifierServices() from uri in service.UriElements let protocol = Protocol.FindBestVersion(p => p.OPIdentifierServiceTypeURI, service.TypeElementUris) - select ServiceEndpoint.CreateForProviderIdentifier(opIdentifier, uri.Uri, service.TypeElementUris, service.Priority, uri.Priority); + let providerDescription = new ProviderEndpointDescription(uri.Uri, service.TypeElementUris) + select ServiceEndpoint.CreateForProviderIdentifier(opIdentifier, providerDescription, service.Priority, uri.Priority); } + /// <summary> + /// Generates the OpenID Providers that are capable of asserting ownership + /// of a particular URI claimed identifier. + /// </summary> + /// <param name="claimedIdentifier">The claimed identifier.</param> + /// <returns>A sequence of the providers that can assert ownership of the given identifier.</returns> private IEnumerable<ServiceEndpoint> GenerateClaimedIdentifierServiceEndpoints(UriIdentifier claimedIdentifier) { return from service in this.FindClaimedIdentifierServices() from uri in service.UriElements - select ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, service.ProviderLocalIdentifier, uri.Uri, service.TypeElementUris, service.Priority, uri.Priority); + let providerEndpoint = new ProviderEndpointDescription(uri.Uri, service.TypeElementUris) + select ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, service.ProviderLocalIdentifier, providerEndpoint, service.Priority, uri.Priority); } + /// <summary> + /// Generates the OpenID Providers that are capable of asserting ownership + /// of a particular XRI claimed identifier. + /// </summary> + /// <param name="userSuppliedIdentifier">The i-name supplied by the user.</param> + /// <returns>A sequence of the providers that can assert ownership of the given identifier.</returns> private IEnumerable<ServiceEndpoint> GenerateClaimedIdentifierServiceEndpoints(XriIdentifier userSuppliedIdentifier) { foreach (var service in this.FindClaimedIdentifierServices()) { foreach (var uri in service.UriElements) { @@ -107,11 +167,16 @@ namespace DotNetOpenAuth.Xrds { // In the case of XRI names, the ClaimedId is actually the CanonicalID. var claimedIdentifier = new XriIdentifier(service.Xrd.CanonicalID); - yield return ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, userSuppliedIdentifier, service.ProviderLocalIdentifier, uri.Uri, service.TypeElementUris, service.Priority, uri.Priority); + var providerEndpoint = new ProviderEndpointDescription(uri.Uri, service.TypeElementUris); + yield return ServiceEndpoint.CreateForClaimedIdentifier(claimedIdentifier, userSuppliedIdentifier, service.ProviderLocalIdentifier, providerEndpoint, service.Priority, uri.Priority); } } } + /// <summary> + /// Enumerates the XRDS service elements that describe OpenID Providers offering directed identity assertions. + /// </summary> + /// <returns>A sequence of service elements.</returns> private IEnumerable<ServiceElement> FindOPIdentifierServices() { return from xrd in this.XrdElements from service in xrd.OpenIdProviderIdentifierServices @@ -129,6 +194,11 @@ namespace DotNetOpenAuth.Xrds { select service; } + /// <summary> + /// Enumerates the XRDS service elements that describe OpenID Relying Party return_to URLs + /// that can receive authentication assertions. + /// </summary> + /// <returns>A sequence of service elements.</returns> private IEnumerable<ServiceElement> FindReturnToServices() { return from xrd in this.XrdElements from service in xrd.OpenIdRelyingPartyReturnToServices diff --git a/src/DotNetOpenAuth/Xrds/XrdsNode.cs b/src/DotNetOpenAuth/Xrds/XrdsNode.cs index d015dcb..5eda0e6 100644 --- a/src/DotNetOpenAuth/Xrds/XrdsNode.cs +++ b/src/DotNetOpenAuth/Xrds/XrdsNode.cs @@ -8,6 +8,9 @@ namespace DotNetOpenAuth.Xrds { using System.Xml; using System.Xml.XPath; + /// <summary> + /// A node in an XRDS document. + /// </summary> internal class XrdsNode { /// <summary> /// The XRD namespace xri://$xrd*($v*2.0) @@ -19,21 +22,39 @@ namespace DotNetOpenAuth.Xrds { /// </summary> internal const string XrdsNamespace = "xri://$xrds"; + /// <summary> + /// Initializes a new instance of the <see cref="XrdsNode"/> class. + /// </summary> + /// <param name="node">The node represented by this instance.</param> + /// <param name="parentNode">The parent node.</param> protected XrdsNode(XPathNavigator node, XrdsNode parentNode) { this.Node = node; this.ParentNode = parentNode; this.XmlNamespaceResolver = this.ParentNode.XmlNamespaceResolver; } + /// <summary> + /// Initializes a new instance of the <see cref="XrdsNode"/> class. + /// </summary> + /// <param name="document">The document's root node, which this instance represents.</param> protected XrdsNode(XPathNavigator document) { this.Node = document; this.XmlNamespaceResolver = new XmlNamespaceManager(document.NameTable); } + /// <summary> + /// Gets the node. + /// </summary> protected XPathNavigator Node { get; private set; } + /// <summary> + /// Gets the parent node, or null if this is the root node. + /// </summary> protected XrdsNode ParentNode { get; private set; } + /// <summary> + /// Gets the XML namespace resolver to use in XPath expressions. + /// </summary> protected XmlNamespaceManager XmlNamespaceResolver { get; private set; } } } diff --git a/src/DotNetOpenAuth/Yadis/HtmlParser.cs b/src/DotNetOpenAuth/Yadis/HtmlParser.cs index 3338b9b..5a00da8 100644 --- a/src/DotNetOpenAuth/Yadis/HtmlParser.cs +++ b/src/DotNetOpenAuth/Yadis/HtmlParser.cs @@ -12,16 +12,51 @@ namespace DotNetOpenAuth.Yadis { using System.Web; using System.Web.UI.HtmlControls; + /// <summary> + /// An HTML HEAD tag parser. + /// </summary> internal static class HtmlParser { - private static readonly Regex attrRe = new Regex("\n# Must start with a sequence of word-characters, followed by an equals sign\n(?<attrname>(\\w|-)+)=\n\n# Then either a quoted or unquoted attribute\n(?:\n\n # Match everything that's between matching quote marks\n (?<qopen>[\"\\'])(?<attrval>.*?)\\k<qopen>\n|\n\n # If the value is not quoted, match up to whitespace\n (?<attrval>(?:[^\\s<>/]|/(?!>))+)\n)\n\n|\n\n(?<endtag>[<>])\n ", Flags); - private const RegexOptions Flags = (RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase); + /// <summary> + /// Common flags to use on regex tests. + /// </summary> + private const RegexOptions Flags = RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase; + + /// <summary> + /// A regular expression designed to select tags (?) + /// </summary> private const string TagExpr = "\n# Starts with the tag name at a word boundary, where the tag name is\n# not a namespace\n<{0}\\b(?!:)\n \n# All of the stuff up to a \">\", hopefully attributes.\n(?<attrs>[^>]*?)\n \n(?: # Match a short tag\n />\n \n| # Match a full tag\n >\n \n (?<contents>.*?)\n \n # Closed by\n (?: # One of the specified close tags\n </?{1}\\s*>\n \n # End of the string\n | \\Z\n \n )\n \n)\n "; + + /// <summary> + /// A regular expression designed to select start tags (?) + /// </summary> private const string StartTagExpr = "\n# Starts with the tag name at a word boundary, where the tag name is\n# not a namespace\n<{0}\\b(?!:)\n \n# All of the stuff up to a \">\", hopefully attributes.\n(?<attrs>[^>]*?)\n \n(?: # Match a short tag\n />\n \n| # Match a full tag\n >\n )\n "; + /// <summary> + /// A regular expression designed to select attributes within a tag. + /// </summary> + private static readonly Regex attrRe = new Regex("\n# Must start with a sequence of word-characters, followed by an equals sign\n(?<attrname>(\\w|-)+)=\n\n# Then either a quoted or unquoted attribute\n(?:\n\n # Match everything that's between matching quote marks\n (?<qopen>[\"\\'])(?<attrval>.*?)\\k<qopen>\n|\n\n # If the value is not quoted, match up to whitespace\n (?<attrval>(?:[^\\s<>/]|/(?!>))+)\n)\n\n|\n\n(?<endtag>[<>])\n ", Flags); + + /// <summary> + /// A regular expression designed to select the HEAD tag. + /// </summary> private static readonly Regex headRe = TagMatcher("head", new[] { "body" }); + + /// <summary> + /// A regular expression designed to select the HTML tag. + /// </summary> private static readonly Regex htmlRe = TagMatcher("html", new string[0]); + + /// <summary> + /// A regular expression designed to remove all comments and scripts from a string. + /// </summary> private static readonly Regex removedRe = new Regex(@"<!--.*?-->|<!\[CDATA\[.*?\]\]>|<script\b[^>]*>.*?</script>", Flags); + /// <summary> + /// Finds all the HTML HEAD tag child elements that match the tag name of a given type. + /// </summary> + /// <typeparam name="T">The HTML tag of interest.</typeparam> + /// <param name="html">The HTML to scan.</param> + /// <returns>A sequence of the matching elements.</returns> public static IEnumerable<T> HeadTags<T>(string html) where T : HtmlControl, new() { html = removedRe.Replace(html, string.Empty); Match match = htmlRe.Match(html); @@ -52,6 +87,12 @@ namespace DotNetOpenAuth.Yadis { } } + /// <summary> + /// Generates a regular expression that will find a given HTML tag. + /// </summary> + /// <param name="tagName">Name of the tag.</param> + /// <param name="closeTags">The close tags (?).</param> + /// <returns>The created regular expression.</returns> private static Regex TagMatcher(string tagName, params string[] closeTags) { string text2; if (closeTags.Length > 0) { @@ -73,8 +114,13 @@ namespace DotNetOpenAuth.Yadis { return new Regex(string.Format(CultureInfo.InvariantCulture, TagExpr, tagName, text2), Flags); } - private static Regex StartTagMatcher(string tag_name) { - return new Regex(string.Format(CultureInfo.InvariantCulture, StartTagExpr, tag_name), Flags); + /// <summary> + /// Generates a regular expression designed to find a given tag. + /// </summary> + /// <param name="tagName">The tag to find.</param> + /// <returns>The created regular expression.</returns> + private static Regex StartTagMatcher(string tagName) { + return new Regex(string.Format(CultureInfo.InvariantCulture, StartTagExpr, tagName), Flags); } } } diff --git a/src/DotNetOpenAuth/Yadis/Yadis.cs b/src/DotNetOpenAuth/Yadis/Yadis.cs index 3a7ffef..455c653 100644 --- a/src/DotNetOpenAuth/Yadis/Yadis.cs +++ b/src/DotNetOpenAuth/Yadis/Yadis.cs @@ -15,7 +15,13 @@ namespace DotNetOpenAuth.Yadis { using DotNetOpenAuth.OpenId; using DotNetOpenAuth.Xrds; + /// <summary> + /// YADIS discovery manager. + /// </summary> internal class Yadis { + /// <summary> + /// The HTTP header to look for in responses to declare where the XRDS document should be found. + /// </summary> internal const string HeaderName = "X-XRDS-Location"; /// <summary> @@ -86,10 +92,12 @@ namespace DotNetOpenAuth.Yadis { } /// <summary> - /// Searches an HTML document for a + /// Searches an HTML document for a /// <meta http-equiv="X-XRDS-Location" content="{YadisURL}"> /// tag and returns the content of YadisURL. /// </summary> + /// <param name="html">The HTML to search.</param> + /// <returns>The URI of the XRDS document if found; otherwise <c>null</c>.</returns> public static Uri FindYadisDocumentLocationInHtmlMetaTags(string html) { foreach (var metaTag in HtmlParser.HeadTags<HtmlMeta>(html)) { if (HeaderName.Equals(metaTag.HttpEquiv, StringComparison.OrdinalIgnoreCase)) { @@ -104,6 +112,14 @@ namespace DotNetOpenAuth.Yadis { return null; } + /// <summary> + /// Sends a YADIS HTTP request as part of identifier discovery. + /// </summary> + /// <param name="requestHandler">The request handler to use to actually submit the request.</param> + /// <param name="uri">The URI to GET.</param> + /// <param name="requireSsl">Whether only HTTPS URLs should ever be retrieved.</param> + /// <param name="acceptTypes">The value of the Accept HTTP header to include in the request.</param> + /// <returns>The HTTP response retrieved from the request.</returns> internal static DirectWebResponse Request(IDirectSslWebRequestHandler requestHandler, Uri uri, bool requireSsl, params string[] acceptTypes) { ErrorUtilities.VerifyArgumentNotNull(uri, "uri"); @@ -116,6 +132,13 @@ namespace DotNetOpenAuth.Yadis { return requestHandler.GetResponse(request, requireSsl); } + /// <summary> + /// Determines whether a given HTTP response constitutes an XRDS document. + /// </summary> + /// <param name="response">The response to test.</param> + /// <returns> + /// <c>true</c> if the response constains an XRDS document; otherwise, <c>false</c>. + /// </returns> private static bool IsXrdsDocument(DirectWebResponse response) { if (response.ContentType.MediaType == ContentTypes.Xrds) { return true; |