diff options
Diffstat (limited to 'src')
7 files changed, 124 insertions, 18 deletions
diff --git a/src/DotNetOpenAuth.Core/Assumes.cs b/src/DotNetOpenAuth.Core/Assumes.cs index f29f09f..151fa2f 100644 --- a/src/DotNetOpenAuth.Core/Assumes.cs +++ b/src/DotNetOpenAuth.Core/Assumes.cs @@ -58,6 +58,14 @@ namespace DotNetOpenAuth { } /// <summary> + /// Throws an internal error exception. + /// </summary> + /// <returns>Nothing. This method always throws.</returns> + internal static Exception NotReachable() { + throw new InternalErrorException(); + } + + /// <summary> /// An internal error exception that should never be caught. /// </summary> [SuppressMessage("Microsoft.Design", "CA1064:ExceptionsShouldBePublic", Justification = "This exception should never be caught.")] diff --git a/src/DotNetOpenAuth.Core/Messaging/Channel.cs b/src/DotNetOpenAuth.Core/Messaging/Channel.cs index 2018801..672a942 100644 --- a/src/DotNetOpenAuth.Core/Messaging/Channel.cs +++ b/src/DotNetOpenAuth.Core/Messaging/Channel.cs @@ -38,6 +38,16 @@ namespace DotNetOpenAuth.Messaging { internal static readonly Encoding PostEntityEncoding = new UTF8Encoding(false); /// <summary> + /// A default set of XML dictionary reader quotas that are relatively safe from causing unbounded memory consumption. + /// </summary> + internal static readonly XmlDictionaryReaderQuotas DefaultUntrustedXmlDictionaryReaderQuotas = new XmlDictionaryReaderQuotas { + MaxArrayLength = 1, + MaxDepth = 2, + MaxBytesPerRead = 8 * 1024, + MaxStringContentLength = 16 * 1024, + }; + + /// <summary> /// The content-type used on HTTP POST requests where the POST entity is a /// URL-encoded series of key=value pairs. /// </summary> @@ -152,12 +162,7 @@ namespace DotNetOpenAuth.Messaging { this.messageTypeProvider = messageTypeProvider; this.WebRequestHandler = new StandardWebRequestHandler(); - this.XmlDictionaryReaderQuotas = new XmlDictionaryReaderQuotas { - MaxArrayLength = 1, - MaxDepth = 2, - MaxBytesPerRead = 8 * 1024, - MaxStringContentLength = 16 * 1024, - }; + this.XmlDictionaryReaderQuotas = DefaultUntrustedXmlDictionaryReaderQuotas; this.outgoingBindingElements = new List<IChannelBindingElement>(ValidateAndPrepareBindingElements(bindingElements)); this.incomingBindingElements = new List<IChannelBindingElement>(this.outgoingBindingElements); @@ -991,17 +996,7 @@ namespace DotNetOpenAuth.Messaging { [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "No apparent problem. False positive?")] protected virtual string SerializeAsJson(IMessage message) { Requires.NotNull(message, "message"); - - MessageDictionary messageDictionary = this.MessageDescriptions.GetAccessor(message); - using (var memoryStream = new MemoryStream()) { - using (var jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(memoryStream, Encoding.UTF8)) { - MessageSerializer.Serialize(messageDictionary, jsonWriter); - jsonWriter.Flush(); - } - - string json = Encoding.UTF8.GetString(memoryStream.ToArray()); - return json; - } + return MessagingUtilities.SerializeAsJson(message, this.MessageDescriptions); } /// <summary> diff --git a/src/DotNetOpenAuth.Core/Messaging/MessageSerializer.cs b/src/DotNetOpenAuth.Core/Messaging/MessageSerializer.cs index bdca190..15df48a 100644 --- a/src/DotNetOpenAuth.Core/Messaging/MessageSerializer.cs +++ b/src/DotNetOpenAuth.Core/Messaging/MessageSerializer.cs @@ -74,7 +74,7 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> - /// Reads the data from a message instance and writes a XML/JSON encoding of it. + /// Reads the data from a message instance and writes an XML/JSON encoding of it. /// </summary> /// <param name="messageDictionary">The message to be serialized.</param> /// <param name="writer">The writer to use for the serialized form.</param> diff --git a/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs index 47d3834..e821953 100644 --- a/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs +++ b/src/DotNetOpenAuth.Core/Messaging/MessagingUtilities.cs @@ -1672,6 +1672,68 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> + /// Serializes the given message as a JSON string. + /// </summary> + /// <param name="message">The message to serialize.</param> + /// <param name="messageDescriptions">The cached message descriptions to use for reflection.</param> + /// <returns>A JSON string.</returns> + [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "This Dispose is safe.")] + [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "No apparent problem. False positive?")] + internal static string SerializeAsJson(IMessage message, MessageDescriptionCollection messageDescriptions) { + Requires.NotNull(message, "message"); + Requires.NotNull(messageDescriptions, "messageDescriptions"); + + var encoding = Encoding.UTF8; + var bytes = SerializeAsJsonBytes(message, messageDescriptions, encoding); + string json = encoding.GetString(bytes); + return json; + } + + /// <summary> + /// Serializes the given message as a JSON string. + /// </summary> + /// <param name="message">The message to serialize.</param> + /// <param name="messageDescriptions">The cached message descriptions to use for reflection.</param> + /// <param name="encoding">The encoding to use. Defaults to <see cref="Encoding.UTF8"/></param> + /// <returns>A JSON string.</returns> + [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "This Dispose is safe.")] + [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "No apparent problem. False positive?")] + internal static byte[] SerializeAsJsonBytes(IMessage message, MessageDescriptionCollection messageDescriptions, Encoding encoding = null) { + Requires.NotNull(message, "message"); + Requires.NotNull(messageDescriptions, "messageDescriptions"); + + encoding = encoding ?? Encoding.UTF8; + MessageDictionary messageDictionary = messageDescriptions.GetAccessor(message); + using (var memoryStream = new MemoryStream()) { + using (var jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(memoryStream, encoding)) { + MessageSerializer.Serialize(messageDictionary, jsonWriter); + jsonWriter.Flush(); + } + + return memoryStream.ToArray(); + } + } + + /// <summary> + /// Deserializes a JSON object into a message. + /// </summary> + /// <param name="jsonBytes">The buffer containing the JSON string.</param> + /// <param name="receivingMessage">The message to deserialize the object into.</param> + /// <param name="messageDescriptions">The cache of message descriptions.</param> + /// <param name="encoding">The encoding that the JSON bytes are in.</param> + internal static void DeserializeFromJson(byte[] jsonBytes, IMessage receivingMessage, MessageDescriptionCollection messageDescriptions, Encoding encoding = null) { + Requires.NotNull(jsonBytes, "jsonBytes"); + Requires.NotNull(receivingMessage, "receivingMessage"); + Requires.NotNull(messageDescriptions, "messageDescriptions"); + + encoding = encoding ?? Encoding.UTF8; + MessageDictionary messageDictionary = messageDescriptions.GetAccessor(receivingMessage); + using (var jsonReader = JsonReaderWriterFactory.CreateJsonReader(jsonBytes, 0, jsonBytes.Length, encoding, Channel.DefaultUntrustedXmlDictionaryReaderQuotas, null)) { + MessageSerializer.Deserialize(messageDictionary, jsonReader); + } + } + + /// <summary> /// Prepares what SHOULD be simply a string value for safe injection into Javascript /// by using appropriate character escaping. /// </summary> diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj index dae4a65..84bdf7d 100644 --- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj +++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj @@ -234,6 +234,7 @@ <Compile Include="Mocks\TestBaseMessage.cs" /> <Compile Include="Mocks\TestDerivedMessage.cs" /> <Compile Include="Mocks\TestDirectResponseMessageWithHttpStatus.cs" /> + <Compile Include="Mocks\TestMessageWithDate.cs" /> <Compile Include="Mocks\TestReplayProtectedMessage.cs" /> <Compile Include="Mocks\TestDirectedMessage.cs" /> <Compile Include="Mocks\TestBadChannel.cs" /> diff --git a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs index a767d53..5c3870c 100644 --- a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs @@ -11,6 +11,7 @@ namespace DotNetOpenAuth.Test.Messaging { using System.Diagnostics; using System.IO; using System.Net; + using System.Text; using System.Text.RegularExpressions; using System.Web; using DotNetOpenAuth.Messaging; @@ -229,6 +230,27 @@ namespace DotNetOpenAuth.Test.Messaging { Assert.AreEqual(PlainText, roundTripped); } + [Test] + public void SerializeAsJsonTest() { + var message = new TestMessageWithDate() { + Age = 18, + Timestamp = DateTime.Parse("4/28/2012"), + Name = "Andrew", + }; + string json = MessagingUtilities.SerializeAsJson(message, this.MessageDescriptions); + Assert.That(json, Is.EqualTo("{\"ts\":\"2012-04-28T00:00:00Z\",\"age\":18,\"Name\":\"Andrew\"}")); + } + + [Test] + public void DeserializeFromJson() { + var message = new TestMessageWithDate(); + string json = "{\"ts\":\"2012-04-28T00:00:00Z\",\"age\":18,\"Name\":\"Andrew\"}"; + MessagingUtilities.DeserializeFromJson(Encoding.UTF8.GetBytes(json), message, this.MessageDescriptions); + Assert.That(message.Age, Is.EqualTo(18)); + Assert.That(message.Timestamp, Is.EqualTo(DateTime.Parse("4/28/2012"))); + Assert.That(message.Name, Is.EqualTo("Andrew")); + } + /// <summary> /// Verifies that the time-independent string equality check works accurately. /// </summary> diff --git a/src/DotNetOpenAuth.Test/Mocks/TestMessageWithDate.cs b/src/DotNetOpenAuth.Test/Mocks/TestMessageWithDate.cs new file mode 100644 index 0000000..b0b89a0 --- /dev/null +++ b/src/DotNetOpenAuth.Test/Mocks/TestMessageWithDate.cs @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------- +// <copyright file="TestMessageWithDate.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.Mocks { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using DotNetOpenAuth.Messaging; + + internal class TestMessageWithDate : TestBaseMessage { + [MessagePart("ts", IsRequired = true)] + internal DateTime Timestamp { get; set; } + } +} |