summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-01-17 20:40:36 -0800
committerAndrew <andrewarnott@gmail.com>2009-01-17 20:40:36 -0800
commit07efff0df7929c836dfe38a0076cc7ee6ed316ff (patch)
tree377b83cb63b3bc7613a90c684088fb60f8894a89
parentf69dda1b9a4551597f3afebfcba684468604ce03 (diff)
downloadDotNetOpenAuth-07efff0df7929c836dfe38a0076cc7ee6ed316ff.zip
DotNetOpenAuth-07efff0df7929c836dfe38a0076cc7ee6ed316ff.tar.gz
DotNetOpenAuth-07efff0df7929c836dfe38a0076cc7ee6ed316ff.tar.bz2
Added GetHashCode() methods to the AX classes, and fixed their Equals methods.
StyleCop clean.
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs3
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj1
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXUtilities.cs111
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs19
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs55
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs65
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs126
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs57
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs36
9 files changed, 363 insertions, 110 deletions
diff --git a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs
index a765d57..aee9f30 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Extensions/ExtensionTestUtilities.cs
@@ -20,6 +20,9 @@ namespace DotNetOpenAuth.Test.OpenId.Extensions {
/// <summary>
/// Simulates an extension request and response.
/// </summary>
+ /// <param name="protocol">The protocol to use in the roundtripping.</param>
+ /// <param name="requests">The extensions to add to the request message.</param>
+ /// <param name="responses">The extensions to add to the response message.</param>
/// <remarks>
/// This method relies on the extension objects' Equals methods to verify
/// accurate transport. The Equals methods should be verified by separate tests.
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index 626bc1f..736d273 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -186,6 +186,7 @@
<Compile Include="OpenId\Extensions\AliasManager.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\AttributeRequest.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\AttributeValues.cs" />
+ <Compile Include="OpenId\Extensions\AttributeExchange\AXUtilities.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\Constants.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\FetchRequest.cs" />
<Compile Include="OpenId\Extensions\AttributeExchange\FetchResponse.cs" />
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXUtilities.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXUtilities.cs
new file mode 100644
index 0000000..b9faedb
--- /dev/null
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AXUtilities.cs
@@ -0,0 +1,111 @@
+//-----------------------------------------------------------------------
+// <copyright file="AXUtilities.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
+ using System;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using DotNetOpenAuth.Messaging;
+
+ /// <summary>
+ /// Helper methods shared by multiple messages in the Attribute Exchange extension.
+ /// </summary>
+ internal class AXUtilities {
+ /// <summary>
+ /// Serializes a set of attribute values to a dictionary of fields to send in the message.
+ /// </summary>
+ /// <param name="fields">The dictionary to fill with serialized attributes.</param>
+ /// <param name="attributes">The attributes.</param>
+ internal static void SerializeAttributes(IDictionary<string, string> fields, IEnumerable<AttributeValues> attributes) {
+ ErrorUtilities.VerifyArgumentNotNull(fields, "fields");
+ ErrorUtilities.VerifyArgumentNotNull(attributes, "attributes");
+
+ AliasManager aliasManager = new AliasManager();
+ foreach (var att in attributes) {
+ string alias = aliasManager.GetAlias(att.TypeUri);
+ fields.Add("type." + alias, att.TypeUri);
+ if (att.Values == null) {
+ continue;
+ }
+ if (att.Values.Count != 1) {
+ fields.Add("count." + alias, att.Values.Count.ToString(CultureInfo.InvariantCulture));
+ for (int i = 0; i < att.Values.Count; i++) {
+ fields.Add(string.Format(CultureInfo.InvariantCulture, "value.{0}.{1}", alias, i + 1), att.Values[i]);
+ }
+ } else {
+ fields.Add("value." + alias, att.Values[0]);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Deserializes attribute values from an incoming set of message data.
+ /// </summary>
+ /// <param name="fields">The data coming in with the message.</param>
+ /// <returns>The attribute values found in the message.</returns>
+ internal static IEnumerable<AttributeValues> DeserializeAttributes(IDictionary<string, string> fields) {
+ AliasManager aliasManager = ParseAliases(fields);
+ foreach (string alias in aliasManager.Aliases) {
+ AttributeValues att = new AttributeValues(aliasManager.ResolveAlias(alias));
+ int count = 1;
+ bool countSent = false;
+ string countString;
+ if (fields.TryGetValue("count." + alias, out countString)) {
+ if (!int.TryParse(countString, out count) || count <= 0) {
+ Logger.ErrorFormat("Failed to parse count.{0} value to a positive integer.", alias);
+ continue;
+ }
+ countSent = true;
+ }
+ if (countSent) {
+ for (int i = 1; i <= count; i++) {
+ string value;
+ if (fields.TryGetValue(string.Format(CultureInfo.InvariantCulture, "value.{0}.{1}", alias, i), out value)) {
+ att.Values.Add(value);
+ } else {
+ Logger.ErrorFormat("Missing value for attribute '{0}'.", att.TypeUri);
+ continue;
+ }
+ }
+ } else {
+ string value;
+ if (fields.TryGetValue("value." + alias, out value)) {
+ att.Values.Add(value);
+ } else {
+ Logger.ErrorFormat("Missing value for attribute '{0}'.", att.TypeUri);
+ continue;
+ }
+ }
+ yield return att;
+ }
+ }
+
+ /// <summary>
+ /// Reads through the attributes included in the response to discover
+ /// the alias-TypeURI relationships.
+ /// </summary>
+ /// <param name="fields">The data included in the extension message.</param>
+ /// <returns>The alias manager that provides lookup between aliases and type URIs.</returns>
+ private static AliasManager ParseAliases(IDictionary<string, string> fields) {
+ ErrorUtilities.VerifyArgumentNotNull(fields, "fields");
+
+ AliasManager aliasManager = new AliasManager();
+ const string TypePrefix = "type.";
+ foreach (var pair in fields) {
+ if (!pair.Key.StartsWith(TypePrefix, StringComparison.Ordinal)) {
+ continue;
+ }
+ string alias = pair.Key.Substring(TypePrefix.Length);
+ if (alias.IndexOfAny(FetchRequest.IllegalAliasCharacters) >= 0) {
+ Logger.ErrorFormat("Illegal characters in alias name '{0}'.", alias);
+ continue;
+ }
+ aliasManager.SetAlias(alias, pair.Value);
+ }
+ return aliasManager;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs
index 6520be8..2f8559d 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs
@@ -89,6 +89,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// Used by a Provider to create a response to a request for an attribute's value(s)
/// using a given array of strings.
/// </summary>
+ /// <param name="values">The values for the requested attribute.</param>
/// <returns>
/// The newly created <see cref="AttributeValues"/> object that should be added to
/// the <see cref="FetchResponse"/> object.
@@ -129,5 +130,23 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
return true;
}
+
+ /// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>
+ /// A hash code for the current <see cref="T:System.Object"/>.
+ /// </returns>
+ public override int GetHashCode() {
+ int hashCode = this.IsRequired ? 1 : 0;
+ unchecked {
+ hashCode += this.Count;
+ if (this.TypeUri != null) {
+ hashCode += this.TypeUri.GetHashCode();
+ }
+ }
+
+ return hashCode;
+ }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs
index db333ef..e87e188 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs
@@ -19,6 +19,18 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// <summary>
/// Initializes a new instance of the <see cref="AttributeValues"/> class.
/// </summary>
+ /// <param name="typeUri">The TypeURI that uniquely identifies the attribute.</param>
+ /// <param name="values">The values for the attribute.</param>
+ public AttributeValues(string typeUri, params string[] values) {
+ ErrorUtilities.VerifyNonZeroLength(typeUri, "typeUri");
+
+ this.TypeUri = typeUri;
+ this.Values = (IList<string>)values ?? EmptyList<string>.Instance;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AttributeValues"/> class.
+ /// </summary>
/// <remarks>
/// This is internal because web sites should be using the
/// <see cref="AttributeRequest.Respond"/> method to instantiate.
@@ -39,18 +51,6 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
}
/// <summary>
- /// Initializes a new instance of the <see cref="AttributeValues"/> class.
- /// </summary>
- /// <param name="typeUri">The TypeURI that uniquely identifies the attribute.</param>
- /// <param name="values">The values for the attribute.</param>
- public AttributeValues(string typeUri, params string[] values) {
- ErrorUtilities.VerifyNonZeroLength(typeUri, "typeUri");
-
- this.TypeUri = typeUri;
- this.Values = (IList<string>)values ?? EmptyList<string>.Instance;
- }
-
- /// <summary>
/// Gets the URI uniquely identifying the attribute whose value is being supplied.
/// </summary>
public string TypeUri { get; internal set; }
@@ -60,6 +60,16 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// </summary>
public IList<string> Values { get; private set; }
+ /// <summary>
+ /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
+ /// <returns>
+ /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
+ /// </returns>
+ /// <exception cref="T:System.NullReferenceException">
+ /// The <paramref name="obj"/> parameter is null.
+ /// </exception>
public override bool Equals(object obj) {
AttributeValues other = obj as AttributeValues;
if (other == null) {
@@ -76,5 +86,26 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
return true;
}
+
+ /// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>
+ /// A hash code for the current <see cref="T:System.Object"/>.
+ /// </returns>
+ public override int GetHashCode() {
+ int hashCode = 0;
+ unchecked {
+ if (this.TypeUri != null) {
+ hashCode += this.TypeUri.GetHashCode();
+ }
+
+ foreach (string value in this.Values) {
+ hashCode += value.GetHashCode();
+ }
+ }
+
+ return hashCode;
+ }
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs
index b29d873..8386bce 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs
@@ -30,11 +30,22 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
return null;
};
+ /// <summary>
+ /// Characters that may not appear in an attribute alias list.
+ /// </summary>
+ internal static readonly char[] IllegalAliasListCharacters = new[] { '.', '\n' };
+
+ /// <summary>
+ /// Characters that may not appear in an attribute Type URI alias.
+ /// </summary>
+ internal static readonly char[] IllegalAliasCharacters = new[] { '.', ',', ':' };
+
+ /// <summary>
+ /// The value for the 'mode' parameter.
+ /// </summary>
[MessagePart("mode", IsRequired = true)]
private const string Mode = "fetch_request";
- private static readonly char[] IllegalAliasListCharacters = new[] { '.', '\n' };
-
/// <summary>
/// The list of requested attributes. This field will never be null.
/// </summary>
@@ -78,8 +89,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
private string RequiredAliases { get; set; }
/// <summary>
- /// Used by the Relying Party to add a request for the values of a given attribute.
+ /// Adds a request for the values of a given attribute.
+ /// Applicable to Relying Parties.
/// </summary>
+ /// <param name="attribute">The attribute.</param>
public void AddAttribute(AttributeRequest attribute) {
ErrorUtilities.VerifyArgumentNotNull(attribute, "attribute");
ErrorUtilities.VerifyArgumentNamed(!this.ContainsAttribute(attribute.TypeUri), "attribute", OpenIdStrings.AttributeAlreadyAdded, attribute.TypeUri);
@@ -87,9 +100,13 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
}
/// <summary>
- /// Used by the Provider to find out whether the value(s) of a given attribute is requested.
+ /// Find out whether the value(s) of a given attribute are being requested by the Relying Party.
+ /// Applicable to Providers.
/// </summary>
- /// <returns>Null if the Relying Party did not ask for the values of the given attribute.</returns>
+ /// <param name="attributeTypeUri">The type URI of the attribute.</param>
+ /// <returns>
+ /// The details of a Relying Party's request for the given attribute; or <c>null</c> if the relyign party did not ask for the values of the given attribute.
+ /// </returns>
public AttributeRequest GetAttribute(string attributeTypeUri) {
return this.attributesRequested.SingleOrDefault(attribute => string.Equals(attribute.TypeUri, attributeTypeUri, StringComparison.Ordinal));
}
@@ -110,6 +127,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
return false;
}
+ if (this.Version != other.Version) {
+ return false;
+ }
+
if (this.UpdateUrl != other.UpdateUrl) {
return false;
}
@@ -121,6 +142,28 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
return true;
}
+ /// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>
+ /// A hash code for the current <see cref="T:System.Object"/>.
+ /// </returns>
+ public override int GetHashCode() {
+ unchecked {
+ int hashCode = this.Version.GetHashCode();
+
+ if (this.UpdateUrl != null) {
+ hashCode += this.UpdateUrl.GetHashCode();
+ }
+
+ foreach (AttributeRequest att in this.Attributes) {
+ hashCode += att.GetHashCode();
+ }
+
+ return hashCode;
+ }
+ }
+
#region IMessageWithEvents Members
/// <summary>
@@ -240,6 +283,11 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
}
}
+ /// <summary>
+ /// Splits a list of aliases by their commas.
+ /// </summary>
+ /// <param name="aliasList">The comma-delimited list of aliases. May be null or empty.</param>
+ /// <returns>The list of aliases. Never null, but may be empty.</returns>
private static IList<string> ParseAliasList(string aliasList) {
if (string.IsNullOrEmpty(aliasList)) {
return EmptyList<string>.Instance;
@@ -248,6 +296,13 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
return aliasList.Split(',');
}
+ /// <summary>
+ /// Determines whether some attribute has values in this fetch request.
+ /// </summary>
+ /// <param name="typeUri">The type URI of the attribute in question.</param>
+ /// <returns>
+ /// <c>true</c> if the specified attribute appears in the fetch request; otherwise, <c>false</c>.
+ /// </returns>
private bool ContainsAttribute(string typeUri) {
return this.GetAttribute(typeUri) != null;
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs
index 3411012..1b3c05b 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs
@@ -31,6 +31,9 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
return null;
};
+ /// <summary>
+ /// The value of the 'mode' parameter.
+ /// </summary>
[MessagePart("mode", IsRequired = true)]
private const string Mode = "fetch_response";
@@ -69,8 +72,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
public Uri UpdateUrl { get; set; }
/// <summary>
- /// Used by the Provider to add attributes to the response for the relying party.
+ /// Adds attributes to the response for the relying party.
+ /// Applicable to Providers.
/// </summary>
+ /// <param name="attribute">The attribute and values to add to the response.</param>
public void AddAttribute(AttributeValues attribute) {
ErrorUtilities.VerifyArgumentNotNull(attribute, "attribute");
ErrorUtilities.VerifyArgumentNamed(!this.ContainsAttribute(attribute.TypeUri), "attribute", OpenIdStrings.AttributeAlreadyAdded, attribute.TypeUri);
@@ -78,9 +83,12 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
}
/// <summary>
- /// Used by the Relying Party to get the value(s) returned by the OpenID Provider
+ /// Gets the value(s) returned by the OpenID Provider
/// for a given attribute, or null if that attribute was not provided.
+ /// Applicable to Relying Parties.
/// </summary>
+ /// <param name="attributeTypeUri">The type URI of the attribute.</param>
+ /// <returns>The values given by the Provider for the given attribute; or <c>null</c> if the attribute was not included in the message.</returns>
public AttributeValues GetAttribute(string attributeTypeUri) {
return this.attributesProvided.SingleOrDefault(attribute => string.Equals(attribute.TypeUri, attributeTypeUri, StringComparison.Ordinal));
}
@@ -101,6 +109,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
return false;
}
+ if (this.Version != other.Version) {
+ return false;
+ }
+
if (this.UpdateUrl != other.UpdateUrl) {
return false;
}
@@ -112,6 +124,28 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
return true;
}
+ /// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>
+ /// A hash code for the current <see cref="T:System.Object"/>.
+ /// </returns>
+ public override int GetHashCode() {
+ unchecked {
+ int hashCode = this.Version.GetHashCode();
+
+ if (this.UpdateUrl != null) {
+ hashCode += this.UpdateUrl.GetHashCode();
+ }
+
+ foreach (AttributeValues value in this.Attributes) {
+ hashCode += value.GetHashCode();
+ }
+
+ return hashCode;
+ }
+ }
+
#region IMessageWithEvents Members
/// <summary>
@@ -120,7 +154,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// </summary>
void IMessageWithEvents.OnSending() {
var extraData = ((IMessage)this).ExtraData;
- SerializeAttributes(extraData, this.attributesProvided);
+ AXUtilities.SerializeAttributes(extraData, this.attributesProvided);
}
/// <summary>
@@ -129,72 +163,13 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// </summary>
void IMessageWithEvents.OnReceiving() {
var extraData = ((IMessage)this).ExtraData;
- foreach (var att in DeserializeAttributes(extraData)) {
+ foreach (var att in AXUtilities.DeserializeAttributes(extraData)) {
this.AddAttribute(att);
}
}
#endregion
- internal static void SerializeAttributes(IDictionary<string, string> fields, IEnumerable<AttributeValues> attributes) {
- ErrorUtilities.VerifyArgumentNotNull(fields, "fields");
- ErrorUtilities.VerifyArgumentNotNull(attributes, "attributes");
-
- AliasManager aliasManager = new AliasManager();
- foreach (var att in attributes) {
- string alias = aliasManager.GetAlias(att.TypeUri);
- fields.Add("type." + alias, att.TypeUri);
- if (att.Values == null) {
- continue;
- }
- if (att.Values.Count != 1) {
- fields.Add("count." + alias, att.Values.Count.ToString(CultureInfo.InvariantCulture));
- for (int i = 0; i < att.Values.Count; i++) {
- fields.Add(string.Format(CultureInfo.InvariantCulture, "value.{0}.{1}", alias, i + 1), att.Values[i]);
- }
- } else {
- fields.Add("value." + alias, att.Values[0]);
- }
- }
- }
-
- internal static IEnumerable<AttributeValues> DeserializeAttributes(IDictionary<string, string> fields) {
- AliasManager aliasManager = ParseAliases(fields);
- foreach (string alias in aliasManager.Aliases) {
- AttributeValues att = new AttributeValues(aliasManager.ResolveAlias(alias));
- int count = 1;
- bool countSent = false;
- string countString;
- if (fields.TryGetValue("count." + alias, out countString)) {
- if (!int.TryParse(countString, out count) || count <= 0) {
- Logger.ErrorFormat("Failed to parse count.{0} value to a positive integer.", alias);
- continue;
- }
- countSent = true;
- }
- if (countSent) {
- for (int i = 1; i <= count; i++) {
- string value;
- if (fields.TryGetValue(string.Format(CultureInfo.InvariantCulture, "value.{0}.{1}", alias, i), out value)) {
- att.Values.Add(value);
- } else {
- Logger.ErrorFormat("Missing value for attribute '{0}'.", att.TypeUri);
- continue;
- }
- }
- } else {
- string value;
- if (fields.TryGetValue("value." + alias, out value)) {
- att.Values.Add(value);
- } else {
- Logger.ErrorFormat("Missing value for attribute '{0}'.", att.TypeUri);
- continue;
- }
- }
- yield return att;
- }
- }
-
/// <summary>
/// Checks the message state for conformity to the protocol specification
/// and throws an exception if the message is invalid.
@@ -216,24 +191,13 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
}
}
- private static AliasManager ParseAliases(IDictionary<string, string> fields) {
- ErrorUtilities.VerifyArgumentNotNull(fields, "fields");
-
- AliasManager aliasManager = new AliasManager();
- foreach (var pair in fields) {
- if (!pair.Key.StartsWith("type.", StringComparison.Ordinal)) {
- continue;
- }
- string alias = pair.Key.Substring(5);
- if (alias.IndexOfAny(new[] { '.', ',', ':' }) >= 0) {
- Logger.ErrorFormat("Illegal characters in alias name '{0}'.", alias);
- continue;
- }
- aliasManager.SetAlias(alias, pair.Value);
- }
- return aliasManager;
- }
-
+ /// <summary>
+ /// Determines whether some attribute has values in this fetch response.
+ /// </summary>
+ /// <param name="typeUri">The type URI of the attribute in question.</param>
+ /// <returns>
+ /// <c>true</c> if the specified attribute appears in the fetch response; otherwise, <c>false</c>.
+ /// </returns>
private bool ContainsAttribute(string typeUri) {
return this.GetAttribute(typeUri) != null;
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs
index 8124039..41f5a2f 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreRequest.cs
@@ -15,9 +15,6 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// The Attribute Exchange Store message, request leg.
/// </summary>
public sealed class StoreRequest : ExtensionBase, IMessageWithEvents {
- [MessagePart("mode", IsRequired = true)]
- private const string Mode = "store_request";
-
/// <summary>
/// The factory method that may be used in deserialization of this message.
/// </summary>
@@ -33,6 +30,12 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
};
/// <summary>
+ /// The value of the 'mode' parameter.
+ /// </summary>
+ [MessagePart("mode", IsRequired = true)]
+ private const string Mode = "store_request";
+
+ /// <summary>
/// The list of provided attribute values. This field will never be null.
/// </summary>
private readonly List<AttributeValues> attributesProvided = new List<AttributeValues>();
@@ -52,9 +55,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
}
/// <summary>
- /// Used by the Relying Party to add a given attribute with one or more values
- /// to the request for storage.
+ /// Adds a given attribute with one or more values to the request for storage.
+ /// Applicable to Relying Parties only.
/// </summary>
+ /// <param name="attribute">The attribute values.</param>
public void AddAttribute(AttributeValues attribute) {
ErrorUtilities.VerifyArgumentNotNull(attribute, "attribute");
ErrorUtilities.VerifyArgumentNamed(!this.ContainsAttribute(attribute.TypeUri), "attribute", OpenIdStrings.AttributeAlreadyAdded, attribute.TypeUri);
@@ -62,17 +66,21 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
}
/// <summary>
- /// Used by the Relying Party to add a given attribute with one or more values
- /// to the request for storage.
+ /// Adds a given attribute with one or more values to the request for storage.
+ /// Applicable to Relying Parties only.
/// </summary>
+ /// <param name="typeUri">The type URI of the attribute.</param>
+ /// <param name="values">The attribute values.</param>
public void AddAttribute(string typeUri, params string[] values) {
this.AddAttribute(new AttributeValues(typeUri, values));
}
/// <summary>
- /// Used by the Provider to gets the value(s) associated with a given attribute
- /// that should be stored.
+ /// Gets the value(s) associated with a given attribute that should be stored.
+ /// Applicable to Providers only.
/// </summary>
+ /// <param name="attributeTypeUri">The type URI of the attribute whose values are being sought.</param>
+ /// <returns>The attribute values.</returns>
public AttributeValues GetAttribute(string attributeTypeUri) {
return this.attributesProvided.SingleOrDefault(attribute => string.Equals(attribute.TypeUri, attributeTypeUri, StringComparison.Ordinal));
}
@@ -87,7 +95,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
var fields = ((IMessage)this).ExtraData;
fields.Clear();
- FetchResponse.SerializeAttributes(fields, this.attributesProvided);
+ AXUtilities.SerializeAttributes(fields, this.attributesProvided);
}
/// <summary>
@@ -96,7 +104,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
/// </summary>
void IMessageWithEvents.OnReceiving() {
var fields = ((IMessage)this).ExtraData;
- foreach (var att in FetchResponse.DeserializeAttributes(fields)) {
+ foreach (var att in AXUtilities.DeserializeAttributes(fields)) {
this.AddAttribute(att);
}
}
@@ -119,6 +127,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
return false;
}
+ if (this.Version != other.Version) {
+ return false;
+ }
+
if (!MessagingUtilities.AreEquivalentUnordered(this.Attributes.ToList(), other.Attributes.ToList())) {
return false;
}
@@ -126,6 +138,29 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
return true;
}
+ /// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>
+ /// A hash code for the current <see cref="T:System.Object"/>.
+ /// </returns>
+ public override int GetHashCode() {
+ unchecked {
+ int hashCode = this.Version.GetHashCode();
+ foreach (AttributeValues att in this.Attributes) {
+ hashCode += att.GetHashCode();
+ }
+ return hashCode;
+ }
+ }
+
+ /// <summary>
+ /// Determines whether some attribute has values in this store request.
+ /// </summary>
+ /// <param name="typeUri">The type URI of the attribute in question.</param>
+ /// <returns>
+ /// <c>true</c> if the specified attribute appears in the store request; otherwise, <c>false</c>.
+ /// </returns>
private bool ContainsAttribute(string typeUri) {
return this.GetAttribute(typeUri) != null;
}
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs
index c883433..97178b6 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/StoreResponse.cs
@@ -79,12 +79,26 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
[MessagePart("mode", IsRequired = true)]
private string Mode { get; set; }
+ /// <summary>
+ /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
+ /// <returns>
+ /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
+ /// </returns>
+ /// <exception cref="T:System.NullReferenceException">
+ /// The <paramref name="obj"/> parameter is null.
+ /// </exception>
public override bool Equals(object obj) {
var other = obj as StoreResponse;
if (other == null) {
return false;
}
+ if (this.Version != other.Version) {
+ return false;
+ }
+
if (this.Succeeded != other.Succeeded) {
return false;
}
@@ -97,6 +111,24 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
}
/// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>
+ /// A hash code for the current <see cref="T:System.Object"/>.
+ /// </returns>
+ public override int GetHashCode() {
+ unchecked {
+ int hashCode = this.Version.GetHashCode();
+ hashCode += this.Succeeded ? 0 : 1;
+ if (this.FailureReason != null) {
+ hashCode += this.FailureReason.GetHashCode();
+ }
+
+ return hashCode;
+ }
+ }
+
+ /// <summary>
/// Checks the message state for conformity to the protocol specification
/// and throws an exception if the message is invalid.
/// </summary>
@@ -113,7 +145,9 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange {
ErrorUtilities.VerifyProtocol(
this.Mode == SuccessMode || this.Mode == FailureMode,
- MessagingStrings.UnexpectedMessagePartValue, "mode", this.Mode);
+ MessagingStrings.UnexpectedMessagePartValue,
+ "mode",
+ this.Mode);
}
}
}