summaryrefslogtreecommitdiffstats
path: root/src/DotNetOpenAuth.OpenId/Xrds/XrdElement.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/DotNetOpenAuth.OpenId/Xrds/XrdElement.cs')
-rw-r--r--src/DotNetOpenAuth.OpenId/Xrds/XrdElement.cs160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/DotNetOpenAuth.OpenId/Xrds/XrdElement.cs b/src/DotNetOpenAuth.OpenId/Xrds/XrdElement.cs
new file mode 100644
index 0000000..2cdc720
--- /dev/null
+++ b/src/DotNetOpenAuth.OpenId/Xrds/XrdElement.cs
@@ -0,0 +1,160 @@
+//-----------------------------------------------------------------------
+// <copyright file="XrdElement.cs" company="Andrew Arnott, Scott Hanselman">
+// Copyright (c) Andrew Arnott, Scott Hanselman. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+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;
+
+ /// <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
+ List<ServiceElement> services = new List<ServiceElement>();
+ foreach (XPathNavigator node in Node.Select("xrd:Service", XmlNamespaceResolver)) {
+ services.Add(new ServiceElement(node, this));
+ }
+ services.Sort();
+ return services;
+ }
+ }
+
+ /// <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);
+ return n != null ? n.Value : null;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the <see cref="CanonicalID"/> was verified.
+ /// </summary>
+ public bool IsCanonicalIdVerified {
+ get {
+ var n = Node.SelectSingleNode("xrd:Status", XmlNamespaceResolver);
+ return n != null && string.Equals(n.GetAttribute("cid", string.Empty), "verified", StringComparison.Ordinal);
+ }
+ }
+
+ /// <summary>
+ /// Gets the services for OP Identifiers.
+ /// </summary>
+ public IEnumerable<ServiceElement> OpenIdProviderIdentifierServices {
+ get { return this.SearchForServiceTypeUris(p => p.OPIdentifierServiceTypeURI); }
+ }
+
+ /// <summary>
+ /// Gets the services for Claimed Identifiers.
+ /// </summary>
+ public IEnumerable<ServiceElement> OpenIdClaimedIdentifierServices {
+ 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); }
+ }
+
+ /// <summary>
+ /// Gets the services that would be discoverable at an RP for the UI extension icon.
+ /// </summary>
+ public IEnumerable<ServiceElement> OpenIdRelyingPartyIcons {
+ get { return this.SearchForServiceTypeUris(p => "http://specs.openid.net/extensions/ui/icon"); }
+ }
+
+ /// <summary>
+ /// Gets an enumeration of all Service/URI elements, sorted in priority order.
+ /// </summary>
+ public IEnumerable<UriElement> ServiceUris {
+ get {
+ return from service in this.Services
+ from uri in service.UriElements
+ select uri;
+ }
+ }
+
+ /// <summary>
+ /// Gets the XRI resolution status code.
+ /// </summary>
+ 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;
+ }
+ }
+
+ /// <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>
+ internal IEnumerable<ServiceElement> SearchForServiceTypeUris(Func<Protocol, string> 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<ServiceElement>();
+ 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;
+ }
+ }
+}