summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj2
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/MultiPartPostPartTests.cs24
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs99
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj2
-rw-r--r--src/DotNetOpenAuth/GlobalSuppressions.cs1
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingUtilities.cs4
-rw-r--r--src/DotNetOpenAuth/Messaging/MultiPartPostPart.cs18
-rw-r--r--src/DotNetOpenAuth/Messaging/MultipartPostPart.cs202
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs46
9 files changed, 351 insertions, 47 deletions
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index f21e4dc..84dfb97 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -137,7 +137,7 @@
<Compile Include="Messaging\EnumerableCacheTests.cs" />
<Compile Include="Messaging\ErrorUtilitiesTests.cs" />
<Compile Include="Messaging\MessageSerializerTests.cs" />
- <Compile Include="Messaging\MultiPartPostPartTests.cs" />
+ <Compile Include="Messaging\MultipartPostPartTests.cs" />
<Compile Include="Messaging\Reflection\MessageDescriptionTests.cs" />
<Compile Include="Messaging\Reflection\MessageDictionaryTests.cs" />
<Compile Include="Messaging\MessagingTestBase.cs" />
diff --git a/src/DotNetOpenAuth.Test/Messaging/MultiPartPostPartTests.cs b/src/DotNetOpenAuth.Test/Messaging/MultiPartPostPartTests.cs
index 95404a4..f87ae59 100644
--- a/src/DotNetOpenAuth.Test/Messaging/MultiPartPostPartTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/MultiPartPostPartTests.cs
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------
-// <copyright file="MultiPartPostPartTests.cs" company="Andrew Arnott">
+// <copyright file="MultipartPostPartTests.cs" company="Andrew Arnott">
// Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
@@ -14,13 +14,13 @@ namespace DotNetOpenAuth.Test.Messaging {
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
- public class MultiPartPostPartTests : TestBase {
+ public class MultipartPostPartTests : TestBase {
/// <summary>
/// Verifies that the Length property matches the length actually serialized.
/// </summary>
[TestMethod]
public void FormDataSerializeMatchesLength() {
- var part = MultiPartPostPart.CreateFormPart("a", "b");
+ var part = MultipartPostPart.CreateFormPart("a", "b");
VerifyLength(part);
}
@@ -32,7 +32,7 @@ namespace DotNetOpenAuth.Test.Messaging {
using (TempFileCollection tfc = new TempFileCollection()) {
string file = tfc.AddExtension(".txt");
File.WriteAllText(file, "sometext");
- var part = MultiPartPostPart.CreateFormFilePart("someformname", file, "text/plain");
+ var part = MultipartPostPart.CreateFormFilePart("someformname", file, "text/plain");
VerifyLength(part);
}
}
@@ -45,9 +45,9 @@ namespace DotNetOpenAuth.Test.Messaging {
using (TempFileCollection tfc = new TempFileCollection()) {
string file = tfc.AddExtension("txt");
File.WriteAllText(file, "sometext");
- this.VerifyFullPost(new List<MultiPartPostPart> {
- MultiPartPostPart.CreateFormPart("a", "b"),
- MultiPartPostPart.CreateFormFilePart("SomeFormField", file, "text/plain"),
+ this.VerifyFullPost(new List<MultipartPostPart> {
+ MultipartPostPart.CreateFormPart("a", "b"),
+ MultipartPostPart.CreateFormFilePart("SomeFormField", file, "text/plain"),
});
}
}
@@ -60,14 +60,14 @@ namespace DotNetOpenAuth.Test.Messaging {
using (TempFileCollection tfc = new TempFileCollection()) {
string file = tfc.AddExtension("txt");
File.WriteAllText(file, "\x1020\x818");
- this.VerifyFullPost(new List<MultiPartPostPart> {
- MultiPartPostPart.CreateFormPart("a", "\x987"),
- MultiPartPostPart.CreateFormFilePart("SomeFormField", file, "text/plain"),
+ this.VerifyFullPost(new List<MultipartPostPart> {
+ MultipartPostPart.CreateFormPart("a", "\x987"),
+ MultipartPostPart.CreateFormFilePart("SomeFormField", file, "text/plain"),
});
}
}
- private static void VerifyLength(MultiPartPostPart part) {
+ private static void VerifyLength(MultipartPostPart part) {
Contract.Requires(part != null);
var expectedLength = part.Length;
@@ -79,7 +79,7 @@ namespace DotNetOpenAuth.Test.Messaging {
Assert.AreEqual(expectedLength, actualLength);
}
- private void VerifyFullPost(List<MultiPartPostPart> parts) {
+ private void VerifyFullPost(List<MultipartPostPart> parts) {
var request = (HttpWebRequest)WebRequest.Create("http://localhost");
var handler = new Mocks.TestWebRequestHandler();
bool posted = false;
diff --git a/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs b/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs
new file mode 100644
index 0000000..f87ae59
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs
@@ -0,0 +1,99 @@
+//-----------------------------------------------------------------------
+// <copyright file="MultipartPostPartTests.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Messaging {
+ using System.CodeDom.Compiler;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.IO;
+ using System.Net;
+ using DotNetOpenAuth.Messaging;
+ using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+ [TestClass]
+ public class MultipartPostPartTests : TestBase {
+ /// <summary>
+ /// Verifies that the Length property matches the length actually serialized.
+ /// </summary>
+ [TestMethod]
+ public void FormDataSerializeMatchesLength() {
+ var part = MultipartPostPart.CreateFormPart("a", "b");
+ VerifyLength(part);
+ }
+
+ /// <summary>
+ /// Verifies that the length property matches the length actually serialized.
+ /// </summary>
+ [TestMethod]
+ public void FileSerializeMatchesLength() {
+ using (TempFileCollection tfc = new TempFileCollection()) {
+ string file = tfc.AddExtension(".txt");
+ File.WriteAllText(file, "sometext");
+ var part = MultipartPostPart.CreateFormFilePart("someformname", file, "text/plain");
+ VerifyLength(part);
+ }
+ }
+
+ /// <summary>
+ /// Verifies MultiPartPost sends the right number of bytes.
+ /// </summary>
+ [TestMethod]
+ public void MultiPartPostAscii() {
+ using (TempFileCollection tfc = new TempFileCollection()) {
+ string file = tfc.AddExtension("txt");
+ File.WriteAllText(file, "sometext");
+ this.VerifyFullPost(new List<MultipartPostPart> {
+ MultipartPostPart.CreateFormPart("a", "b"),
+ MultipartPostPart.CreateFormFilePart("SomeFormField", file, "text/plain"),
+ });
+ }
+ }
+
+ /// <summary>
+ /// Verifies MultiPartPost sends the right number of bytes.
+ /// </summary>
+ [TestMethod]
+ public void MultiPartPostMultiByteCharacters() {
+ using (TempFileCollection tfc = new TempFileCollection()) {
+ string file = tfc.AddExtension("txt");
+ File.WriteAllText(file, "\x1020\x818");
+ this.VerifyFullPost(new List<MultipartPostPart> {
+ MultipartPostPart.CreateFormPart("a", "\x987"),
+ MultipartPostPart.CreateFormFilePart("SomeFormField", file, "text/plain"),
+ });
+ }
+ }
+
+ private static void VerifyLength(MultipartPostPart part) {
+ Contract.Requires(part != null);
+
+ var expectedLength = part.Length;
+ var ms = new MemoryStream();
+ var sw = new StreamWriter(ms);
+ part.Serialize(sw);
+ sw.Flush();
+ var actualLength = ms.Length;
+ Assert.AreEqual(expectedLength, actualLength);
+ }
+
+ private void VerifyFullPost(List<MultipartPostPart> parts) {
+ var request = (HttpWebRequest)WebRequest.Create("http://localhost");
+ var handler = new Mocks.TestWebRequestHandler();
+ bool posted = false;
+ handler.Callback = req => {
+ foreach (string header in req.Headers) {
+ TestContext.WriteLine("{0}: {1}", header, req.Headers[header]);
+ }
+ TestContext.WriteLine(handler.RequestEntityAsString);
+ Assert.AreEqual(req.ContentLength, handler.RequestEntityStream.Length);
+ posted = true;
+ return null;
+ };
+ request.PostMultipart(handler, parts);
+ Assert.IsTrue(posted, "HTTP POST never sent.");
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index 3c42217..341b722 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -252,7 +252,7 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="Messaging\IProtocolMessageWithExtensions.cs" />
<Compile Include="Messaging\InternalErrorException.cs" />
<Compile Include="Messaging\KeyedCollectionDelegate.cs" />
- <Compile Include="Messaging\MultiPartPostPart.cs" />
+ <Compile Include="Messaging\MultipartPostPart.cs" />
<Compile Include="Messaging\NetworkDirectWebResponse.cs" />
<Compile Include="Messaging\OutgoingWebResponseActionResult.cs" />
<Compile Include="Messaging\Reflection\IMessagePartEncoder.cs" />
diff --git a/src/DotNetOpenAuth/GlobalSuppressions.cs b/src/DotNetOpenAuth/GlobalSuppressions.cs
index d0e0d05..313eaeb 100644
--- a/src/DotNetOpenAuth/GlobalSuppressions.cs
+++ b/src/DotNetOpenAuth/GlobalSuppressions.cs
@@ -48,3 +48,4 @@
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "icam", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "idmanagement", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "no-pii", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "runat", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
index 62a4f64..93c0b6b 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
@@ -148,7 +148,7 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="requestHandler">The request handler.</param>
/// <param name="parts">The parts to include in the POST entity.</param>
/// <returns>The HTTP response.</returns>
- public static IncomingWebResponse PostMultipart(this HttpWebRequest request, IDirectWebRequestHandler requestHandler, IEnumerable<MultiPartPostPart> parts) {
+ public static IncomingWebResponse PostMultipart(this HttpWebRequest request, IDirectWebRequestHandler requestHandler, IEnumerable<MultipartPostPart> parts) {
ErrorUtilities.VerifyArgumentNotNull(request, "request");
ErrorUtilities.VerifyArgumentNotNull(requestHandler, "requestHandler");
ErrorUtilities.VerifyArgumentNotNull(parts, "parts");
@@ -644,7 +644,7 @@ namespace DotNetOpenAuth.Messaging {
/// Gets the <see cref="HttpDeliveryMethods"/> enum value for a given HTTP verb.
/// </summary>
/// <param name="httpVerb">The HTTP verb.</param>
- /// <returns>A <see cref="HttpDeliveryMethod"/> enum value that is within the <see cref="HttpDeliveryMethods.HttpVerbMask"/>.</returns>
+ /// <returns>A <see cref="HttpDeliveryMethods"/> enum value that is within the <see cref="HttpDeliveryMethods.HttpVerbMask"/>.</returns>
internal static HttpDeliveryMethods GetHttpDeliveryMethod(string httpVerb) {
if (httpVerb == "GET") {
return HttpDeliveryMethods.GetRequest;
diff --git a/src/DotNetOpenAuth/Messaging/MultiPartPostPart.cs b/src/DotNetOpenAuth/Messaging/MultiPartPostPart.cs
index 5cdda48..7ef89a4 100644
--- a/src/DotNetOpenAuth/Messaging/MultiPartPostPart.cs
+++ b/src/DotNetOpenAuth/Messaging/MultiPartPostPart.cs
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------
-// <copyright file="MultiPartPostPart.cs" company="Andrew Arnott">
+// <copyright file="MultipartPostPart.cs" company="Andrew Arnott">
// Copyright (c) Andrew Arnott. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
@@ -16,7 +16,7 @@ namespace DotNetOpenAuth.Messaging {
/// <summary>
/// Represents a single part in a HTTP multipart POST request.
/// </summary>
- public class MultiPartPostPart : IDisposable {
+ public class MultipartPostPart : IDisposable {
/// <summary>
/// The "Content-Disposition" string.
/// </summary>
@@ -28,10 +28,10 @@ namespace DotNetOpenAuth.Messaging {
private const string NewLine = "\r\n";
/// <summary>
- /// Initializes a new instance of the <see cref="MultiPartPostPart"/> class.
+ /// Initializes a new instance of the <see cref="MultipartPostPart"/> class.
/// </summary>
/// <param name="contentDisposition">The content disposition of the part.</param>
- public MultiPartPostPart(string contentDisposition) {
+ public MultipartPostPart(string contentDisposition) {
Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(contentDisposition));
this.ContentDisposition = contentDisposition;
@@ -98,11 +98,11 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="name">The name of the form field.</param>
/// <param name="value">The value.</param>
/// <returns>The constructed part.</returns>
- public static MultiPartPostPart CreateFormPart(string name, string value) {
+ public static MultipartPostPart CreateFormPart(string name, string value) {
Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(name));
Contract.Requires<ArgumentException>(value != null);
- var part = new MultiPartPostPart("form-data");
+ var part = new MultipartPostPart("form-data");
part.ContentAttributes["name"] = name;
part.Content = new MemoryStream(Encoding.UTF8.GetBytes(value));
return part;
@@ -115,7 +115,7 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="filePath">The path to the file to send.</param>
/// <param name="contentType">Type of the content in HTTP Content-Type format.</param>
/// <returns>The constructed part.</returns>
- public static MultiPartPostPart CreateFormFilePart(string name, string filePath, string contentType) {
+ public static MultipartPostPart CreateFormFilePart(string name, string filePath, string contentType) {
string fileName = Path.GetFileName(filePath);
return CreateFormFilePart(name, fileName, contentType, File.OpenRead(filePath));
}
@@ -128,13 +128,13 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="contentType">Type of the content in HTTP Content-Type format.</param>
/// <param name="content">The content of the file.</param>
/// <returns>The constructed part.</returns>
- public static MultiPartPostPart CreateFormFilePart(string name, string fileName, string contentType, Stream content) {
+ public static MultipartPostPart CreateFormFilePart(string name, string fileName, string contentType, Stream content) {
Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(name));
Contract.Requires<ArgumentException>(fileName != null);
Contract.Requires<ArgumentException>(contentType != null);
Contract.Requires<ArgumentException>(content != null);
- var part = new MultiPartPostPart("form-data");
+ var part = new MultipartPostPart("form-data");
part.ContentAttributes["name"] = name;
part.ContentAttributes["filename"] = fileName;
part.PartHeaders[HttpRequestHeader.ContentType] = contentType;
diff --git a/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs b/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs
new file mode 100644
index 0000000..7ef89a4
--- /dev/null
+++ b/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs
@@ -0,0 +1,202 @@
+//-----------------------------------------------------------------------
+// <copyright file="MultipartPostPart.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Messaging {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.IO;
+ using System.Net;
+ using System.Text;
+
+ /// <summary>
+ /// Represents a single part in a HTTP multipart POST request.
+ /// </summary>
+ public class MultipartPostPart : IDisposable {
+ /// <summary>
+ /// The "Content-Disposition" string.
+ /// </summary>
+ private const string ContentDispositionHeader = "Content-Disposition";
+
+ /// <summary>
+ /// The two-character \r\n newline character sequence to use.
+ /// </summary>
+ private const string NewLine = "\r\n";
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MultipartPostPart"/> class.
+ /// </summary>
+ /// <param name="contentDisposition">The content disposition of the part.</param>
+ public MultipartPostPart(string contentDisposition) {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(contentDisposition));
+
+ this.ContentDisposition = contentDisposition;
+ this.ContentAttributes = new Dictionary<string, string>();
+ this.PartHeaders = new WebHeaderCollection();
+ }
+
+ /// <summary>
+ /// Gets the content disposition.
+ /// </summary>
+ /// <value>The content disposition.</value>
+ public string ContentDisposition { get; private set; }
+
+ /// <summary>
+ /// Gets the key=value attributes that appear on the same line as the Content-Disposition.
+ /// </summary>
+ /// <value>The content attributes.</value>
+ public IDictionary<string, string> ContentAttributes { get; private set; }
+
+ /// <summary>
+ /// Gets the headers that appear on subsequent lines after the Content-Disposition.
+ /// </summary>
+ public WebHeaderCollection PartHeaders { get; private set; }
+
+ /// <summary>
+ /// Gets or sets the content of the part.
+ /// </summary>
+ public Stream Content { get; set; }
+
+ /// <summary>
+ /// Gets the length of this entire part.
+ /// </summary>
+ /// <remarks>Useful for calculating the ContentLength HTTP header to send before actually serializing the content.</remarks>
+ public long Length {
+ get {
+ ErrorUtilities.VerifyOperation(this.Content != null && this.Content.Length >= 0, MessagingStrings.StreamMustHaveKnownLength);
+
+ long length = 0;
+ length += ContentDispositionHeader.Length;
+ length += ": ".Length;
+ length += this.ContentDisposition.Length;
+ foreach (var pair in this.ContentAttributes) {
+ length += "; ".Length + pair.Key.Length + "=\"".Length + pair.Value.Length + "\"".Length;
+ }
+
+ length += NewLine.Length;
+ foreach (string headerName in this.PartHeaders) {
+ length += headerName.Length;
+ length += ": ".Length;
+ length += this.PartHeaders[headerName].Length;
+ length += NewLine.Length;
+ }
+
+ length += NewLine.Length;
+ length += this.Content.Length;
+
+ return length;
+ }
+ }
+
+ /// <summary>
+ /// Creates a part that represents a simple form field.
+ /// </summary>
+ /// <param name="name">The name of the form field.</param>
+ /// <param name="value">The value.</param>
+ /// <returns>The constructed part.</returns>
+ public static MultipartPostPart CreateFormPart(string name, string value) {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(name));
+ Contract.Requires<ArgumentException>(value != null);
+
+ var part = new MultipartPostPart("form-data");
+ part.ContentAttributes["name"] = name;
+ part.Content = new MemoryStream(Encoding.UTF8.GetBytes(value));
+ return part;
+ }
+
+ /// <summary>
+ /// Creates a part that represents a file attachment.
+ /// </summary>
+ /// <param name="name">The name of the form field.</param>
+ /// <param name="filePath">The path to the file to send.</param>
+ /// <param name="contentType">Type of the content in HTTP Content-Type format.</param>
+ /// <returns>The constructed part.</returns>
+ public static MultipartPostPart CreateFormFilePart(string name, string filePath, string contentType) {
+ string fileName = Path.GetFileName(filePath);
+ return CreateFormFilePart(name, fileName, contentType, File.OpenRead(filePath));
+ }
+
+ /// <summary>
+ /// Creates a part that represents a file attachment.
+ /// </summary>
+ /// <param name="name">The name of the form field.</param>
+ /// <param name="fileName">Name of the file as the server should see it.</param>
+ /// <param name="contentType">Type of the content in HTTP Content-Type format.</param>
+ /// <param name="content">The content of the file.</param>
+ /// <returns>The constructed part.</returns>
+ public static MultipartPostPart CreateFormFilePart(string name, string fileName, string contentType, Stream content) {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(name));
+ Contract.Requires<ArgumentException>(fileName != null);
+ Contract.Requires<ArgumentException>(contentType != null);
+ Contract.Requires<ArgumentException>(content != null);
+
+ var part = new MultipartPostPart("form-data");
+ part.ContentAttributes["name"] = name;
+ part.ContentAttributes["filename"] = fileName;
+ part.PartHeaders[HttpRequestHeader.ContentType] = contentType;
+ if (!contentType.StartsWith("text/", StringComparison.Ordinal)) {
+ part.PartHeaders["Content-Transfer-Encoding"] = "binary";
+ }
+ part.Content = content;
+ return part;
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose() {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Serializes the part to a stream.
+ /// </summary>
+ /// <param name="streamWriter">The stream writer.</param>
+ internal void Serialize(StreamWriter streamWriter) {
+ // VERY IMPORTANT: any changes at all made to this must be kept in sync with the
+ // Length property which calculates exactly how many bytes this method will write.
+ streamWriter.NewLine = NewLine;
+ streamWriter.Write("{0}: {1}", ContentDispositionHeader, this.ContentDisposition);
+ foreach (var pair in this.ContentAttributes) {
+ streamWriter.Write("; {0}=\"{1}\"", pair.Key, pair.Value);
+ }
+
+ streamWriter.WriteLine();
+ foreach (string headerName in this.PartHeaders) {
+ streamWriter.WriteLine("{0}: {1}", headerName, this.PartHeaders[headerName]);
+ }
+
+ streamWriter.WriteLine();
+ streamWriter.Flush();
+ this.Content.CopyTo(streamWriter.BaseStream);
+ }
+
+ /// <summary>
+ /// Releases unmanaged and - optionally - managed resources
+ /// </summary>
+ /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ this.Content.Dispose();
+ }
+ }
+
+#if CONTRACTS_FULL
+ /// <summary>
+ /// Verifies conditions that should be true for any valid state of this object.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "Called by code contracts.")]
+ [ContractInvariantMethod]
+ private void Invariant() {
+ Contract.Invariant(!string.IsNullOrEmpty(this.ContentDisposition));
+ Contract.Invariant(this.PartHeaders != null);
+ Contract.Invariant(this.ContentAttributes != null);
+ }
+#endif
+ }
+}
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
index ef65c72..5cf630a 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
@@ -67,9 +67,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
#region Property viewstate keys
/// <summary>
- /// The viewstate key to use for storing the value of the <see cref="AutoPostback"/> property.
+ /// The viewstate key to use for storing the value of the <see cref="AutoPostBack"/> property.
/// </summary>
- private const string AutoPostbackViewStateKey = "AutoPostback";
+ private const string AutoPostBackViewStateKey = "AutoPostback";
/// <summary>
/// The viewstate key to use for the <see cref="Text"/> property.
@@ -167,18 +167,18 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const string RetryTextViewStateKey = "RetryText";
/// <summary>
- /// The viewstate key to use for storing the value of the <see cref="DownloadYui"/> property.
+ /// The viewstate key to use for storing the value of the <see cref="DownloadYahooUILibrary"/> property.
/// </summary>
- private const string DownloadYuiViewStateKey = "DownloadYui";
+ private const string DownloadYahooUILibraryViewStateKey = "DownloadYahooUILibrary";
#endregion
#region Property defaults
/// <summary>
- /// The default value for the <see cref="AutoPostback"/> property.
+ /// The default value for the <see cref="AutoPostBack"/> property.
/// </summary>
- private const bool AutoPostbackDefault = false;
+ private const bool AutoPostBackDefault = false;
/// <summary>
/// The default value for the <see cref="Columns"/> property.
@@ -256,9 +256,9 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
private const string RetryTextDefault = "RETRY";
/// <summary>
- /// The default vlaue for the <see cref="DownloadYui"/> property.
+ /// The default vlaue for the <see cref="DownloadYahooUILibrary"/> property.
/// </summary>
- private const bool DownloadYuiDefault = true;
+ private const bool DownloadYahooUILibraryDefault = true;
#endregion
@@ -334,19 +334,19 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets a value indicating whether a postback is made to fire the
- /// <see cref="LoggedIn"/> event as soon as authentication has completed
+ /// <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event as soon as authentication has completed
/// successfully.
/// </summary>
/// <value>
/// <c>true</c> if a postback should be made automatically upon authentication;
- /// otherwise, <c>false</c> to delay the <see cref="LoggedIn"/> event from firing
- /// at the server until a postback is made by some other control.
+ /// otherwise, <c>false</c> to delay the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/>
+ /// event from firing at the server until a postback is made by some other control.
/// </value>
- [Bindable(true), Category(BehaviorCategory), DefaultValue(AutoPostbackDefault)]
+ [Bindable(true), Category(BehaviorCategory), DefaultValue(AutoPostBackDefault)]
[Description("Whether the LoggedIn event fires on the server as soon as authentication completes successfully.")]
- public bool AutoPostback {
- get { return (bool)(this.ViewState[AutoPostbackViewStateKey] ?? AutoPostbackDefault); }
- set { this.ViewState[AutoPostbackViewStateKey] = value; }
+ public bool AutoPostBack {
+ get { return (bool)(this.ViewState[AutoPostBackViewStateKey] ?? AutoPostBackDefault); }
+ set { this.ViewState[AutoPostBackViewStateKey] = value; }
}
/// <summary>
@@ -569,11 +569,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <remarks>
/// The split button brings in about 180KB of YUI javascript dependencies.
/// </remarks>
- [Bindable(true), DefaultValue(DownloadYuiDefault), Category(BehaviorCategory)]
+ [Bindable(true), DefaultValue(DownloadYahooUILibraryDefault), Category(BehaviorCategory)]
[Description("Whether a split button will be used for the \"log in\" when the user provides an identifier that delegates to more than one Provider.")]
- public bool DownloadYui {
- get { return (bool)(this.ViewState[DownloadYuiViewStateKey] ?? DownloadYuiDefault); }
- set { this.ViewState[DownloadYuiViewStateKey] = value; }
+ public bool DownloadYahooUILibrary {
+ get { return (bool)(this.ViewState[DownloadYahooUILibraryViewStateKey] ?? DownloadYahooUILibraryDefault); }
+ set { this.ViewState[DownloadYahooUILibraryViewStateKey] = value; }
}
#endregion
@@ -632,6 +632,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// When implemented by a class, enables a server control to process an event raised when a form is posted to the server.
/// </summary>
/// <param name="eventArgument">A <see cref="T:System.String"/> that represents an optional event argument to be passed to the event handler.</param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Signature predefined.")]
void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) {
this.RaisePostBackEvent(eventArgument);
}
@@ -663,7 +664,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
protected override void OnPreRender(EventArgs e) {
base.OnPreRender(e);
- if (this.DownloadYui) {
+ if (this.DownloadYahooUILibrary) {
string yuiLoadScript = @"var loader = new YAHOO.util.YUILoader({
require: ['button', 'menu'],
loadOptional: false,
@@ -753,7 +754,7 @@ loader.insert();";
/// <summary>
/// When implemented by a class, signals the server control to notify the ASP.NET application that the state of the control has changed.
/// </summary>
- [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Preserve signature of interface we're implementing.")]
+ [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Predefined signature.")]
protected virtual void RaisePostDataChangedEvent() {
this.OnTextChanged();
}
@@ -762,6 +763,7 @@ loader.insert();";
/// When implemented by a class, enables a server control to process an event raised when a form is posted to the server.
/// </summary>
/// <param name="eventArgument">A <see cref="T:System.String"/> that represents an optional event argument to be passed to the event handler.</param>
+ [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Preserve signature of interface we're implementing.")]
protected virtual void RaisePostBackEvent(string eventArgument) {
}
@@ -807,7 +809,7 @@ loader.insert();";
MessagingUtilities.GetSafeJavascriptValue(this.AuthenticationSucceededToolTip),
MessagingUtilities.GetSafeJavascriptValue(this.AuthenticatedAsToolTip),
MessagingUtilities.GetSafeJavascriptValue(this.AuthenticationFailedToolTip),
- this.AutoPostback ? Page.ClientScript.GetPostBackEventReference(this, null) : null,
+ this.AutoPostBack ? Page.ClientScript.GetPostBackEventReference(this, null) : null,
Environment.NewLine);
startupScript.AppendLine("</script>");