//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation, Scott Hanselman. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.Xrds { using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.XPath; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OpenId; /// /// The Xrd element in an XRDS document. /// internal class XrdElement : XrdsNode { /// /// Initializes a new instance of the class. /// /// The XRD element. /// The parent. public XrdElement(XPathNavigator xrdElement, XrdsDocument parent) : base(xrdElement, parent) { } /// /// Gets the child service elements. /// /// The services. public IEnumerable Services { get { // We should enumerate them in priority order List services = new List(); foreach (XPathNavigator node in Node.Select("xrd:Service", XmlNamespaceResolver)) { services.Add(new ServiceElement(node, this)); } services.Sort(); return services; } } /// /// Gets a value indicating whether this XRD element's resolution at the XRI resolver was successful. /// /// /// true if this XRD's resolution was successful; otherwise, false. /// public bool IsXriResolutionSuccessful { get { return this.XriResolutionStatusCode == 100; } } /// /// Gets the canonical ID (i-number) for this element. /// public string CanonicalID { get { var n = Node.SelectSingleNode("xrd:CanonicalID", XmlNamespaceResolver); return n != null ? n.Value : null; } } /// /// Gets a value indicating whether the was verified. /// public bool IsCanonicalIdVerified { get { var n = Node.SelectSingleNode("xrd:Status", XmlNamespaceResolver); return n != null && string.Equals(n.GetAttribute("cid", string.Empty), "verified", StringComparison.Ordinal); } } /// /// Gets the services for OP Identifiers. /// public IEnumerable OpenIdProviderIdentifierServices { get { return this.SearchForServiceTypeUris(p => p.OPIdentifierServiceTypeURI); } } /// /// Gets the services for Claimed Identifiers. /// public IEnumerable OpenIdClaimedIdentifierServices { get { return this.SearchForServiceTypeUris(p => p.ClaimedIdentifierServiceTypeURI); } } /// /// Gets the services that would be discoverable at an RP for return_to verification. /// public IEnumerable OpenIdRelyingPartyReturnToServices { get { return this.SearchForServiceTypeUris(p => p.RPReturnToTypeURI); } } /// /// Gets the services that would be discoverable at an RP for the UI extension icon. /// public IEnumerable OpenIdRelyingPartyIcons { get { return this.SearchForServiceTypeUris(p => "http://specs.openid.net/extensions/ui/icon"); } } /// /// Gets an enumeration of all Service/URI elements, sorted in priority order. /// public IEnumerable ServiceUris { get { return from service in this.Services from uri in service.UriElements select uri; } } /// /// Gets the XRI resolution status code. /// private int XriResolutionStatusCode { get { var n = Node.SelectSingleNode("xrd:Status", XmlNamespaceResolver); string codeString = null; ErrorUtilities.VerifyProtocol(n != null && !string.IsNullOrEmpty(codeString = n.GetAttribute("code", string.Empty)), XrdsStrings.XriResolutionStatusMissing); int code; ErrorUtilities.VerifyProtocol(int.TryParse(codeString, out code) && code >= 100 && code < 400, XrdsStrings.XriResolutionStatusMissing); return code; } } /// /// Searches for service sub-elements that have Type URI sub-elements that match /// one that we have for a known OpenID protocol version. /// /// A function that selects what element of the OpenID Protocol we're interested in finding. /// A sequence of service elements that match the search criteria, sorted in XRDS @priority attribute order. internal IEnumerable SearchForServiceTypeUris(Func p) { var xpath = new StringBuilder(); xpath.Append("xrd:Service["); foreach (var protocol in Protocol.AllVersions) { string typeUri = p(protocol); if (typeUri == null) { continue; } xpath.Append("xrd:Type/text()='"); xpath.Append(typeUri); xpath.Append("' or "); } xpath.Length -= 4; xpath.Append("]"); var services = new List(); foreach (XPathNavigator service in Node.Select(xpath.ToString(), XmlNamespaceResolver)) { services.Add(new ServiceElement(service, this)); } // Put the services in their own defined priority order services.Sort(); return services; } } }