summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.proj21
-rw-r--r--lib/DotNetOpenAuth.BuildTasks.dllbin65536 -> 66560 bytes
-rw-r--r--lib/DotNetOpenAuth.BuildTasks.pdbbin165376 -> 167424 bytes
-rw-r--r--samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs40
-rw-r--r--samples/OAuthConsumer/Twitter.aspx16
-rw-r--r--samples/OAuthConsumer/Twitter.aspx.cs16
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Code/State.vb46
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Code/TracePageAppender.vb10
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Default.aspx18
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Default.aspx.designer.vb26
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Default.aspx.vb8
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Global.asax1
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Global.asax.vb66
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Login.aspx28
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Login.aspx.designer.vb53
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Login.aspx.vb52
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx15
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx.designer.vb71
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx.vb76
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/Default.aspx34
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/ProfileFieldsDisplay.ascx91
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/Web.config18
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/My Project/Application.Designer.vb13
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/My Project/Application.myapp10
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/My Project/AssemblyInfo.vb34
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/My Project/MyExtensions/MyWebExtension.vb73
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/My Project/Resources.Designer.vb62
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/My Project/Resources.resx117
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/My Project/Settings.Designer.vb73
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/My Project/Settings.settings7
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/OpenIdRelyingPartyWebFormsVB.vbproj224
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/PrivacyPolicy.aspx7
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Site.Master39
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx16
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx.designer.vb53
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx.vb13
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Web.config112
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/favicon.icobin0 -> 1150 bytes
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/images/DotNetOpenAuth.pngbin0 -> 25212 bytes
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/images/attention.pngbin0 -> 714 bytes
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/images/openid_login.gifbin0 -> 237 bytes
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/images/yahoo.pngbin0 -> 7607 bytes
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/styles.css10
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/xrds.aspx29
-rw-r--r--samples/Samples.sln9
-rw-r--r--src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj4
-rw-r--r--src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs50
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs76
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/MultiPartPostPartTests.cs99
-rw-r--r--src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs9
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/TestDirectedMessage.cs4
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs7
-rw-r--r--src/DotNetOpenAuth.sln10
-rw-r--r--src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs1
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj1
-rw-r--r--src/DotNetOpenAuth/GlobalSuppressions.cs1
-rw-r--r--src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs3
-rw-r--r--src/DotNetOpenAuth/Messaging/Channel.cs54
-rw-r--r--src/DotNetOpenAuth/Messaging/EmptyDictionary.cs2
-rw-r--r--src/DotNetOpenAuth/Messaging/EmptyList.cs4
-rw-r--r--src/DotNetOpenAuth/Messaging/EnumerableCache.cs2
-rw-r--r--src/DotNetOpenAuth/Messaging/HttpDeliveryMethods.cs7
-rw-r--r--src/DotNetOpenAuth/Messaging/IDirectWebRequestHandler.cs5
-rw-r--r--src/DotNetOpenAuth/Messaging/IMessageWithBinaryData.cs152
-rw-r--r--src/DotNetOpenAuth/Messaging/ITamperProtectionChannelBindingElement.cs100
-rw-r--r--src/DotNetOpenAuth/Messaging/MessageReceivingEndpoint.cs1
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs9
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingStrings.resx3
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingUtilities.cs95
-rw-r--r--src/DotNetOpenAuth/Messaging/MultipartPostPart.cs10
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessageDictionary.cs2
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs3
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs39
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs22
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementChain.cs4
-rw-r--r--src/DotNetOpenAuth/OAuth/ConsumerBase.cs22
-rw-r--r--src/DotNetOpenAuth/OAuth/Messages/AccessProtectedResourceRequest.cs27
-rw-r--r--src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs9
-rw-r--r--src/DotNetOpenAuth/OAuth/OAuthStrings.resx3
-rw-r--r--src/DotNetOpenAuth/OAuth/ServiceProviderDescription.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs3
-rw-r--r--src/DotNetOpenAuth/OpenId/IIdentifierDiscoveryService.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/RequestBase.cs8
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs1
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/StandardRelyingPartyApplicationStore.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/XriDiscoveryProxyService.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/XriIdentifier.cs4
-rw-r--r--src/DotNetOpenAuth/Reporting.cs6
-rw-r--r--src/DotNetOpenAuth/Yadis/Yadis.cs2
-rw-r--r--src/version.txt2
94 files changed, 2306 insertions, 187 deletions
diff --git a/build.proj b/build.proj
index bb0cbdc..9843456 100644
--- a/build.proj
+++ b/build.proj
@@ -24,7 +24,7 @@
<UsingTask AssemblyFile="$(ProjectRoot)lib\MSBuild.Community.Tasks.dll" TaskName="NUnit" />
<ItemGroup>
- <SampleProjects Include="$(ProjectRoot)samples\**\*.csproj" />
+ <SampleProjects Include="$(ProjectRoot)samples\**\*.csproj;$(ProjectRoot)samples\**\*.vbproj" />
<SampleSites Include="OAuthConsumer;OAuthServiceProvider;InfoCardRelyingParty" />
<ProjectTemplates Include="$(ProjectRoot)projecttemplates\**\*.csproj" />
<ILMergeInputAssemblies Include="$(OutputPath)$(ProductName).dll;
@@ -113,22 +113,27 @@
<ItemGroup>
<ToolProjects Include="$(ProjectRoot)Samples\OpenIdOfflineProvider\OpenIdOfflineProvider.csproj" />
+ </ItemGroup>
+
+ <MSBuild Projects="@(ToolProjects)" />
+
+ <ItemGroup>
<OfflineProvider Include="
- $(ProjectRoot)Samples\OpenIdOfflineProvider\bin\$(TargetFrameworkVersion)\$(Configuration)\**\*.dll;
- $(ILMergeOutputAssembly).*;
- $(ProjectRoot)Samples\OpenIdOfflineProvider\bin\$(TargetFrameworkVersion)\$(Configuration)\OpenIdOfflineProvider.exe"
- Exclude="
- $(ProjectRoot)Samples\OpenIdOfflineProvider\bin\$(TargetFrameworkVersion)\$(Configuration)\$(ProductName).*;
+ $(OutputPath)**\*.dll;
+ $(OutputPath)OpenIdOfflineProvider.exe"
+ Exclude="
+ $(OutputPath)$(ProductName).*;
+ $(ILMergeOutputAssembly);
"/>
<OfflineProviderTargets Include="
@(OfflineProvider->'$(ToolsDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/>
+ <OfflineProvider Include="$(ILMergeOutputAssembly)" />
+ <OfflineProviderTargets Include="$(ToolsDirectory)$(ProductName).dll" />
<AllToolSources Include="@(OfflineProvider)" />
<AllToolTargets Include="@(OfflineProviderTargets)" />
</ItemGroup>
- <MSBuild Projects="@(ToolProjects)" />
-
<MakeDir Directories="@(ToolsDirectory)" />
<Copy SourceFiles="@(AllToolSources)" DestinationFiles="@(AllToolTargets)" SkipUnchangedFiles="true" />
diff --git a/lib/DotNetOpenAuth.BuildTasks.dll b/lib/DotNetOpenAuth.BuildTasks.dll
index f3a61b3..fc5788a 100644
--- a/lib/DotNetOpenAuth.BuildTasks.dll
+++ b/lib/DotNetOpenAuth.BuildTasks.dll
Binary files differ
diff --git a/lib/DotNetOpenAuth.BuildTasks.pdb b/lib/DotNetOpenAuth.BuildTasks.pdb
index 091c3ca..8d6282e 100644
--- a/lib/DotNetOpenAuth.BuildTasks.pdb
+++ b/lib/DotNetOpenAuth.BuildTasks.pdb
Binary files differ
diff --git a/samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs b/samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs
index 2a98ffe..29973c2 100644
--- a/samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs
+++ b/samples/DotNetOpenAuth.ApplicationBlock/TwitterConsumer.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.ApplicationBlock {
using System;
using System.Collections.Generic;
using System.IO;
+ using System.Net;
using System.Xml;
using System.Xml.Linq;
using DotNetOpenAuth.Messaging;
@@ -38,6 +39,18 @@ namespace DotNetOpenAuth.ApplicationBlock {
/// </summary>
private static readonly MessageReceivingEndpoint GetFriendTimelineStatusEndpoint = new MessageReceivingEndpoint("http://twitter.com/statuses/friends_timeline.xml", HttpDeliveryMethods.GetRequest);
+ private static readonly MessageReceivingEndpoint UpdateProfileBackgroundImageEndpoint = new MessageReceivingEndpoint("http://twitter.com/account/update_profile_background_image.xml", HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
+
+ private static readonly MessageReceivingEndpoint UpdateProfileImageEndpoint = new MessageReceivingEndpoint("http://twitter.com/account/update_profile_image.xml", HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
+
+ /// <summary>
+ /// Initializes static members of the <see cref="TwitterConsumer"/> class.
+ /// </summary>
+ static TwitterConsumer() {
+ // Twitter can't handle the Expect 100 Continue HTTP header.
+ ServicePointManager.FindServicePoint(GetFavoritesEndpoint.Location).Expect100Continue = false;
+ }
+
public static XDocument GetUpdates(ConsumerBase twitter, string accessToken) {
IncomingWebResponse response = twitter.PrepareAuthorizedRequestAndSend(GetFriendTimelineStatusEndpoint, accessToken);
return XDocument.Load(XmlReader.Create(response.GetResponseReader()));
@@ -47,5 +60,32 @@ namespace DotNetOpenAuth.ApplicationBlock {
IncomingWebResponse response = twitter.PrepareAuthorizedRequestAndSend(GetFavoritesEndpoint, accessToken);
return XDocument.Load(XmlReader.Create(response.GetResponseReader()));
}
+
+ public static XDocument UpdateProfileBackgroundImage(ConsumerBase twitter, string accessToken, string image, bool tile) {
+ var parts = new[] {
+ MultipartPostPart.CreateFormFilePart("image", image, "image/" + Path.GetExtension(image).Substring(1).ToLowerInvariant()),
+ MultipartPostPart.CreateFormPart("tile", tile.ToString().ToLowerInvariant()),
+ };
+ HttpWebRequest request = twitter.PrepareAuthorizedRequest(UpdateProfileBackgroundImageEndpoint, accessToken, parts);
+ request.ServicePoint.Expect100Continue = false;
+ IncomingWebResponse response = twitter.Channel.WebRequestHandler.GetResponse(request);
+ string responseString = response.GetResponseReader().ReadToEnd();
+ return XDocument.Parse(responseString);
+ }
+
+ public static XDocument UpdateProfileImage(ConsumerBase twitter, string accessToken, string pathToImage) {
+ string contentType = "image/" + Path.GetExtension(pathToImage).Substring(1).ToLowerInvariant();
+ return UpdateProfileImage(twitter, accessToken, File.OpenRead(pathToImage), contentType);
+ }
+
+ public static XDocument UpdateProfileImage(ConsumerBase twitter, string accessToken, Stream image, string contentType) {
+ var parts = new[] {
+ MultipartPostPart.CreateFormFilePart("image", "twitterPhoto", contentType, image),
+ };
+ HttpWebRequest request = twitter.PrepareAuthorizedRequest(UpdateProfileImageEndpoint, accessToken, parts);
+ IncomingWebResponse response = twitter.Channel.WebRequestHandler.GetResponse(request);
+ string responseString = response.GetResponseReader().ReadToEnd();
+ return XDocument.Parse(responseString);
+ }
}
}
diff --git a/samples/OAuthConsumer/Twitter.aspx b/samples/OAuthConsumer/Twitter.aspx
index a659533..30ce2a0 100644
--- a/samples/OAuthConsumer/Twitter.aspx
+++ b/samples/OAuthConsumer/Twitter.aspx
@@ -16,9 +16,19 @@
</asp:View>
<asp:View runat="server">
<h2>Updates</h2>
- <p>Ok, Twitter has authorized us to download your feeds. Click 'Get updates' to download
- updates to this sample. Notice how we never asked you for your Twitter username
- or password. </p>
+ <p>Ok, Twitter has authorized us to download your feeds. Notice how we never asked
+ you for your Twitter username or password. </p>
+ <p>
+ Upload a new profile photo:
+ <asp:FileUpload ID="profilePhoto" runat="server" />
+ &nbsp;<asp:Button ID="uploadProfilePhotoButton" runat="server"
+ onclick="uploadProfilePhotoButton_Click" Text="Upload photo" />
+ &nbsp;<asp:Label ID="photoUploadedLabel" runat="server" EnableViewState="False"
+ Text="Done!" Visible="False"></asp:Label>
+ </p>
+ <p>
+ Click &#39;Get updates&#39; to download updates to this sample.
+ </p>
<asp:Button ID="downloadUpdates" runat="server" Text="Get updates" OnClick="downloadUpdates_Click" />
<asp:PlaceHolder runat="server" ID="resultsPlaceholder" />
</asp:View>
diff --git a/samples/OAuthConsumer/Twitter.aspx.cs b/samples/OAuthConsumer/Twitter.aspx.cs
index 9b9eced..f309396 100644
--- a/samples/OAuthConsumer/Twitter.aspx.cs
+++ b/samples/OAuthConsumer/Twitter.aspx.cs
@@ -75,4 +75,20 @@ public partial class Twitter : System.Web.UI.Page {
tableBuilder.Append("</table>");
resultsPlaceholder.Controls.Add(new Literal { Text = tableBuilder.ToString() });
}
+
+ protected void uploadProfilePhotoButton_Click(object sender, EventArgs e) {
+ if (profilePhoto.PostedFile.ContentType == null) {
+ photoUploadedLabel.Visible = true;
+ photoUploadedLabel.Text = "Select a file first.";
+ return;
+ }
+
+ var twitter = new WebConsumer(TwitterConsumer.ServiceDescription, this.TokenManager);
+ XDocument imageResult = TwitterConsumer.UpdateProfileImage(
+ twitter,
+ this.AccessToken,
+ profilePhoto.PostedFile.InputStream,
+ profilePhoto.PostedFile.ContentType);
+ photoUploadedLabel.Visible = true;
+ }
}
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Code/State.vb b/samples/OpenIdRelyingPartyWebFormsVB/Code/State.vb
new file mode 100644
index 0000000..e00cb4f
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Code/State.vb
@@ -0,0 +1,46 @@
+Imports DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy
+Imports DotNetOpenAuth.OpenId.Extensions.SimpleRegistration
+Imports DotNetOpenAuth.OpenId.Extensions.AttributeExchange
+
+Public Class State
+ Public Shared Property ProfileFields() As ClaimsResponse
+ Get
+ Return HttpContext.Current.Session("ProfileFields")
+ End Get
+ Set(ByVal value As ClaimsResponse)
+ HttpContext.Current.Session("ProfileFields") = value
+ End Set
+ End Property
+
+ Public Shared Property FetchResponse() As FetchResponse
+ Get
+ Return HttpContext.Current.Session("FetchResponse")
+ End Get
+ Set(ByVal value As FetchResponse)
+ HttpContext.Current.Session("FetchResponse") = value
+ End Set
+ End Property
+
+ Public Shared Property FriendlyLoginName() As String
+ Get
+ Return HttpContext.Current.Session("FriendlyLoginName")
+ End Get
+ Set(ByVal value As String)
+ HttpContext.Current.Session("FriendlyLoginName") = value
+ End Set
+ End Property
+
+ Public Shared Property PapePolicies() As PolicyResponse
+ Get
+ Return HttpContext.Current.Session("PapePolicies")
+ End Get
+ Set(ByVal value As PolicyResponse)
+ HttpContext.Current.Session("PapePolicies") = value
+ End Set
+ End Property
+
+ Public Shared Sub Clear()
+ FriendlyLoginName = Nothing
+ End Sub
+
+End Class
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Code/TracePageAppender.vb b/samples/OpenIdRelyingPartyWebFormsVB/Code/TracePageAppender.vb
new file mode 100644
index 0000000..dfc2db5
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Code/TracePageAppender.vb
@@ -0,0 +1,10 @@
+Imports System.IO
+
+Public Class TracePageAppender
+ Inherits log4net.Appender.AppenderSkeleton
+
+ Protected Overrides Sub Append(ByVal loggingEvent As log4net.Core.LoggingEvent)
+ Dim sw As StringWriter = New StringWriter(Global_asax.LogMessages)
+ Layout.Format(sw, loggingEvent)
+ End Sub
+End Class \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Default.aspx b/samples/OpenIdRelyingPartyWebFormsVB/Default.aspx
new file mode 100644
index 0000000..53f6dfc
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Default.aspx
@@ -0,0 +1,18 @@
+<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="OpenIdRelyingPartyWebFormsVB._Default"
+ MasterPageFile="~/Site.Master" %>
+
+<%@ Register Assembly="DotNetOpenAuth" Namespace="DotNetOpenAuth" TagPrefix="openid" %>
+<asp:Content runat="server" ContentPlaceHolderID="head">
+ <openid:XrdsPublisher ID="XrdsPublisher1" runat="server" XrdsUrl="~/xrds.aspx" />
+</asp:Content>
+<asp:Content runat="server" ContentPlaceHolderID="main">
+ <h2>
+ Relying Party
+ </h2>
+ <p>
+ Visit the
+ <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/MembersOnly/Default.aspx"
+ Text="Members Only" />
+ area. (This will trigger a login demo).
+ </p>
+</asp:Content>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Default.aspx.designer.vb b/samples/OpenIdRelyingPartyWebFormsVB/Default.aspx.designer.vb
new file mode 100644
index 0000000..ce59c43
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Default.aspx.designer.vb
@@ -0,0 +1,26 @@
+'------------------------------------------------------------------------------
+' <auto-generated>
+' This code was generated by a tool.
+' Runtime Version:2.0.50727.4927
+'
+' Changes to this file may cause incorrect behavior and will be lost if
+' the code is regenerated.
+' </auto-generated>
+'------------------------------------------------------------------------------
+
+Option Strict On
+Option Explicit On
+
+
+
+Partial Public Class _Default
+
+ '''<summary>
+ '''form1 control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents form1 As Global.System.Web.UI.HtmlControls.HtmlForm
+End Class
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Default.aspx.vb b/samples/OpenIdRelyingPartyWebFormsVB/Default.aspx.vb
new file mode 100644
index 0000000..3e023c0
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Default.aspx.vb
@@ -0,0 +1,8 @@
+Partial Public Class _Default
+ Inherits System.Web.UI.Page
+
+ Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
+
+ End Sub
+
+End Class \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Global.asax b/samples/OpenIdRelyingPartyWebFormsVB/Global.asax
new file mode 100644
index 0000000..92716f1
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Global.asax
@@ -0,0 +1 @@
+<%@ Application Codebehind="Global.asax.vb" Inherits="OpenIdRelyingPartyWebFormsVB.Global_asax" Language="vb" %>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Global.asax.vb b/samples/OpenIdRelyingPartyWebFormsVB/Global.asax.vb
new file mode 100644
index 0000000..60ab0cc
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Global.asax.vb
@@ -0,0 +1,66 @@
+Imports System
+Imports System.Collections.Specialized
+Imports System.Configuration
+Imports System.IO
+Imports System.Text
+Imports System.Web
+Imports DotNetOpenAuth.ApplicationBlock
+Imports DotNetOpenAuth.OAuth
+Imports OpenIdRelyingPartyWebFormsVB
+
+Public Class Global_asax
+ Inherits HttpApplication
+
+ Public Shared Logger As log4net.ILog = log4net.LogManager.GetLogger(GetType(Global_asax))
+
+ Friend Shared LogMessages As StringBuilder = New StringBuilder
+
+ Public Shared Function CollectionToString(ByVal collection As NameValueCollection) As String
+ Dim sw As StringWriter = New StringWriter
+ For Each key As String In collection.Keys
+ sw.WriteLine("{0} = '{1}'", key, collection(key))
+ Next
+ Return sw.ToString
+ End Function
+
+ Protected Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
+ log4net.Config.XmlConfigurator.Configure()
+ Logger.Info("Sample starting...")
+ End Sub
+
+ Protected Sub Application_End(ByVal sender As Object, ByVal e As EventArgs)
+ Logger.Info("Sample shutting down...")
+ ' this would be automatic, but in partial trust scenarios it is not.
+ log4net.LogManager.Shutdown()
+ End Sub
+
+ Protected Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
+ ' System.Diagnostics.Debugger.Launch();
+ Logger.DebugFormat("Processing {0} on {1} ", Request.HttpMethod, stripQueryString(Request.Url))
+ If (Request.QueryString.Count > 0) Then
+ Logger.DebugFormat("Querystring follows: " & vbLf & "{0}", CollectionToString(Request.QueryString))
+ End If
+ If (Request.Form.Count > 0) Then
+ Logger.DebugFormat("Posted form follows: " & vbLf & "{0}", CollectionToString(Request.Form))
+ End If
+ End Sub
+
+ Protected Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)
+ Logger.DebugFormat("User {0} authenticated.", (Not (HttpContext.Current.User) Is Nothing))
+ 'TODO: Warning!!!, inline IF is not supported ?
+ End Sub
+
+ Protected Sub Application_EndRequest(ByVal sender As Object, ByVal e As EventArgs)
+
+ End Sub
+
+ Protected Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
+ Logger.ErrorFormat("An unhandled exception was raised. Details follow: {0}", HttpContext.Current.Server.GetLastError)
+ End Sub
+
+ Private Shared Function stripQueryString(ByVal uri As Uri) As String
+ Dim builder As UriBuilder = New UriBuilder(uri)
+ builder.Query = Nothing
+ Return builder.ToString
+ End Function
+End Class \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Login.aspx b/samples/OpenIdRelyingPartyWebFormsVB/Login.aspx
new file mode 100644
index 0000000..d0e978b
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Login.aspx
@@ -0,0 +1,28 @@
+<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Login.aspx.vb" Inherits="OpenIdRelyingPartyWebFormsVB.Login"
+ ValidateRequest="false" MasterPageFile="~/Site.Master" %>
+
+<%@ Register Assembly="DotNetOpenAuth" Namespace="DotNetOpenAuth.OpenId.RelyingParty" TagPrefix="rp" %>
+<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="Main">
+ <h2>Login Page </h2>
+ <rp:OpenIdLogin ID="OpenIdLogin1" runat="server" CssClass="openid_login" RequestCountry="Request"
+ RequestEmail="Require" RequestGender="Require" RequestPostalCode="Require" RequestTimeZone="Require"
+ RememberMeVisible="True" PolicyUrl="~/PrivacyPolicy.aspx" TabIndex="1" />
+ <fieldset title="Knobs">
+ <asp:CheckBox ID="requireSslCheckBox" runat="server"
+ Text="RequireSsl (high security) mode"
+ oncheckedchanged="requireSslCheckBox_CheckedChanged" /><br />
+ <h4 style="margin-top: 0; margin-bottom: 0">PAPE policies</h4>
+ <asp:CheckBoxList runat="server" ID="papePolicies">
+ <asp:ListItem Text="Request phishing resistant authentication" Value="http://schemas.openid.net/pape/policies/2007/06/phishing-resistant" />
+ <asp:ListItem Text="Request multi-factor authentication" Value="http://schemas.openid.net/pape/policies/2007/06/multi-factor" />
+ <asp:ListItem Text="Request physical multi-factor authentication" Value="http://schemas.openid.net/pape/policies/2007/06/multi-factor-physical" />
+ <asp:ListItem Text="Request PPID identifier" Value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier" />
+ </asp:CheckBoxList>
+ <p>Try the PPID identifier functionality against the OpenIDProviderMvc sample.</p>
+ </fieldset>
+ <p><a href="loginGoogleApps.aspx">Log in using Google Apps for Domains</a>. </p>
+ <p>
+ <rp:OpenIdButton runat="server" ImageUrl="~/images/yahoo.png" Text="Login with Yahoo!" ID="yahooLoginButton"
+ Identifier="https://me.yahoo.com/" OnLoggingIn="OpenIdLogin1_LoggingIn" OnLoggedIn="OpenIdLogin1_LoggedIn" />
+ </p>
+</asp:Content>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Login.aspx.designer.vb b/samples/OpenIdRelyingPartyWebFormsVB/Login.aspx.designer.vb
new file mode 100644
index 0000000..4cf1a96
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Login.aspx.designer.vb
@@ -0,0 +1,53 @@
+'------------------------------------------------------------------------------
+' <auto-generated>
+' This code was generated by a tool.
+' Runtime Version:2.0.50727.4927
+'
+' Changes to this file may cause incorrect behavior and will be lost if
+' the code is regenerated.
+' </auto-generated>
+'------------------------------------------------------------------------------
+
+Option Strict On
+Option Explicit On
+
+
+
+Partial Public Class Login
+
+ '''<summary>
+ '''OpenIdLogin1 control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents OpenIdLogin1 As Global.DotNetOpenAuth.OpenId.RelyingParty.OpenIdLogin
+
+ '''<summary>
+ '''requireSslCheckBox control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents requireSslCheckBox As Global.System.Web.UI.WebControls.CheckBox
+
+ '''<summary>
+ '''papePolicies control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents papePolicies As Global.System.Web.UI.WebControls.CheckBoxList
+
+ '''<summary>
+ '''yahooLoginButton control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents yahooLoginButton As Global.DotNetOpenAuth.OpenId.RelyingParty.OpenIdButton
+End Class
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Login.aspx.vb b/samples/OpenIdRelyingPartyWebFormsVB/Login.aspx.vb
new file mode 100644
index 0000000..339f62c
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Login.aspx.vb
@@ -0,0 +1,52 @@
+Imports DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy
+Imports DotNetOpenAuth.OpenId.RelyingParty
+Imports DotNetOpenAuth.OpenId.Extensions.SimpleRegistration
+
+Partial Public Class Login
+ Inherits System.Web.UI.Page
+
+ Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
+ OpenIdLogin1.Focus()
+ End Sub
+
+ Protected Sub requireSslCheckBox_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs)
+ OpenIdLogin1.RequireSsl = requireSslCheckBox.Checked
+ End Sub
+
+ Protected Sub OpenIdLogin1_LoggingIn(ByVal sender As Object, ByVal e As DotNetOpenAuth.OpenId.RelyingParty.OpenIdEventArgs) Handles OpenIdLogin1.LoggingIn
+ prepareRequest(e.Request)
+ End Sub
+
+ ''' <summary>
+ ''' Fired upon login.
+ ''' </summary>
+ ''' <param name="sender">The source of the event.</param>
+ ''' <param name="e">The <see cref="DotNetOpenAuth.OpenId.RelyingParty.OpenIdEventArgs"/> instance containing the event data.</param>
+ ''' <remarks>
+ ''' Note, that straight after login, forms auth will redirect the user
+ ''' to their original page. So this page may never be rendererd.
+ ''' </remarks>
+ Protected Sub OpenIdLogin1_LoggedIn(ByVal sender As Object, ByVal e As DotNetOpenAuth.OpenId.RelyingParty.OpenIdEventArgs) Handles OpenIdLogin1.LoggedIn
+ State.FriendlyLoginName = e.Response.FriendlyIdentifierForDisplay
+ State.ProfileFields = e.Response.GetExtension(Of ClaimsResponse)()
+ State.PapePolicies = e.Response.GetExtension(Of PolicyResponse)()
+ End Sub
+
+ Private Sub prepareRequest(ByVal request As IAuthenticationRequest)
+ ' Collect the PAPE policies requested by the user.
+ Dim policies As New List(Of String)
+ For Each item As ListItem In Me.papePolicies.Items
+ If item.Selected Then
+ policies.Add(item.Value)
+ End If
+ Next
+ ' Add the PAPE extension if any policy was requested.
+ If (policies.Count > 0) Then
+ Dim pape As New PolicyRequest
+ For Each policy As String In policies
+ pape.PreferredPolicies.Add(policy)
+ Next
+ request.AddExtension(pape)
+ End If
+ End Sub
+End Class \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx b/samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx
new file mode 100644
index 0000000..7f1fa0e
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx
@@ -0,0 +1,15 @@
+<%@ Page Language="vb" AutoEventWireup="true" CodeBehind="loginProgrammatic.aspx.vb"
+ Inherits="OpenIdRelyingPartyWebFormsVB.LoginProgrammatic" MasterPageFile="~/Site.Master" %>
+<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="Main">
+ <h2>Login Page </h2>
+ <asp:Label ID="Label1" runat="server" Text="OpenID Login" />
+ <asp:TextBox ID="openIdBox" runat="server" />
+ <asp:Button ID="loginButton" runat="server" Text="Login" OnClick="loginButton_Click" />
+ <asp:CustomValidator runat="server" ID="openidValidator" ErrorMessage="Invalid OpenID Identifier"
+ ControlToValidate="openIdBox" EnableViewState="false" OnServerValidate="openidValidator_ServerValidate" />
+ <br />
+ <asp:Label ID="loginFailedLabel" runat="server" EnableViewState="False" Text="Login failed"
+ Visible="False" />
+ <asp:Label ID="loginCanceledLabel" runat="server" EnableViewState="False" Text="Login canceled"
+ Visible="False" />
+</asp:Content> \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx.designer.vb b/samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx.designer.vb
new file mode 100644
index 0000000..907fcda
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx.designer.vb
@@ -0,0 +1,71 @@
+'------------------------------------------------------------------------------
+' <auto-generated>
+' This code was generated by a tool.
+' Runtime Version:2.0.50727.4927
+'
+' Changes to this file may cause incorrect behavior and will be lost if
+' the code is regenerated.
+' </auto-generated>
+'------------------------------------------------------------------------------
+
+Option Strict On
+Option Explicit On
+
+
+
+Partial Public Class LoginProgrammatic
+
+ '''<summary>
+ '''Label1 control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents Label1 As Global.System.Web.UI.WebControls.Label
+
+ '''<summary>
+ '''openIdBox control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents openIdBox As Global.System.Web.UI.WebControls.TextBox
+
+ '''<summary>
+ '''loginButton control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents loginButton As Global.System.Web.UI.WebControls.Button
+
+ '''<summary>
+ '''openidValidator control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents openidValidator As Global.System.Web.UI.WebControls.CustomValidator
+
+ '''<summary>
+ '''loginFailedLabel control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents loginFailedLabel As Global.System.Web.UI.WebControls.Label
+
+ '''<summary>
+ '''loginCanceledLabel control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents loginCanceledLabel As Global.System.Web.UI.WebControls.Label
+End Class
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx.vb b/samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx.vb
new file mode 100644
index 0000000..6cac182
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/LoginProgrammatic.aspx.vb
@@ -0,0 +1,76 @@
+Imports System.Net
+Imports System.Web.Security
+Imports DotNetOpenAuth.Messaging
+Imports DotNetOpenAuth.OpenId
+Imports DotNetOpenAuth.OpenId.Extensions.SimpleRegistration
+Imports DotNetOpenAuth.OpenId.RelyingParty
+
+Public Class LoginProgrammatic
+ Inherits System.Web.UI.Page
+
+ Private Shared relyingParty As New OpenIdRelyingParty
+
+ Protected Sub openidValidator_ServerValidate(ByVal source As Object, ByVal args As ServerValidateEventArgs)
+ ' This catches common typos that result in an invalid OpenID Identifier.
+ args.IsValid = Identifier.IsValid(args.Value)
+ End Sub
+
+ Protected Sub loginButton_Click(ByVal sender As Object, ByVal e As EventArgs)
+ If Not Me.Page.IsValid Then
+ Return
+ ' don't login if custom validation failed.
+ End If
+ Try
+ Dim request As IAuthenticationRequest = relyingParty.CreateRequest(Me.openIdBox.Text)
+ ' This is where you would add any OpenID extensions you wanted
+ ' to include in the authentication request.
+ request.AddExtension(New ClaimsRequest() With { _
+ .Country = DemandLevel.Request, _
+ .Email = DemandLevel.Request, _
+ .Gender = DemandLevel.Require, _
+ .PostalCode = DemandLevel.Require, _
+ .TimeZone = DemandLevel.Require _
+ })
+ ' Send your visitor to their Provider for authentication.
+ request.RedirectToProvider()
+ Catch ex As ProtocolException
+ ' The user probably entered an Identifier that
+ ' was not a valid OpenID endpoint.
+ Me.openidValidator.Text = ex.Message
+ Me.openidValidator.IsValid = False
+ End Try
+ End Sub
+
+ Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
+ Me.openIdBox.Focus()
+ ' For debugging/testing, we allow remote clearing of all associations...
+ ' NOT a good idea on a production site.
+ If (Request.QueryString("clearAssociations") = "1") Then
+ Application.Remove("DotNetOpenAuth.OpenId.RelyingParty.OpenIdRelyingParty.ApplicationStore")
+ ' Force a redirect now to prevent the user from logging in while associations
+ ' are constantly being cleared.
+ Dim builder As UriBuilder = New UriBuilder(Request.Url)
+ builder.Query = Nothing
+ Me.Response.Redirect(builder.Uri.AbsoluteUri)
+ End If
+ Dim response As IAuthenticationResponse = relyingParty.GetResponse
+ If response IsNot Nothing Then
+ Select Case response.Status
+ Case AuthenticationStatus.Authenticated
+ ' This is where you would look for any OpenID extension responses included
+ ' in the authentication assertion.
+ Dim claimsResponse As ClaimsResponse = response.GetExtension(Of ClaimsResponse)()
+ State.ProfileFields = claimsResponse
+ ' Store off the "friendly" username to display -- NOT for username lookup
+ State.FriendlyLoginName = response.FriendlyIdentifierForDisplay
+ ' Use FormsAuthentication to tell ASP.NET that the user is now logged in,
+ ' with the OpenID Claimed Identifier as their username.
+ FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, False)
+ Case AuthenticationStatus.Canceled
+ Me.loginCanceledLabel.Visible = True
+ Case AuthenticationStatus.Failed
+ Me.loginFailedLabel.Visible = True
+ End Select
+ End If
+ End Sub
+End Class \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/Default.aspx b/samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/Default.aspx
new file mode 100644
index 0000000..441ef84
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/Default.aspx
@@ -0,0 +1,34 @@
+<%@ Page Language="VB" AutoEventWireup="true" MasterPageFile="~/Site.Master" %>
+<%@ Import Namespace="OpenIdRelyingPartyWebFormsVB" %>
+<%@ Register Src="~/MembersOnly/ProfileFieldsDisplay.ascx" TagPrefix="cc1" TagName="ProfileFieldsDisplay" %>
+<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="Main">
+ <h2>
+ Members Only Area
+ </h2>
+ <p>
+ Congratulations, <b><asp:LoginName ID="LoginName1" runat="server" /></b>.
+ You have completed the OpenID login process.
+ </p>
+
+<% If (State.PapePolicies IsNot Nothing) Then%>
+ <p>A PAPE extension was included in the authentication with this content: </p>
+ <ul>
+ <% If (State.PapePolicies.NistAssuranceLevel.HasValue) Then%>
+ <li>Nist: <%=HttpUtility.HtmlEncode(State.PapePolicies.NistAssuranceLevel.Value.ToString())%></li>
+ <% End If
+ For Each policy As String In State.PapePolicies.ActualPolicies%>
+ <li><%=HttpUtility.HtmlEncode(policy)%></li>
+ <% Next%>
+ </ul>
+<% End If %>
+
+<% If State.ProfileFields IsNot Nothing Then
+ profileFieldsDisplay.ProfileValues = State.ProfileFields%>
+ <p>
+ In addition to authenticating you, your OpenID Provider may
+ have told us something about you using the
+ Simple Registration extension:
+ </p>
+ <cc1:ProfileFieldsDisplay runat="server" ID="profileFieldsDisplay" />
+<% End If%>
+</asp:Content>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/ProfileFieldsDisplay.ascx b/samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/ProfileFieldsDisplay.ascx
new file mode 100644
index 0000000..f6864e9
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/ProfileFieldsDisplay.ascx
@@ -0,0 +1,91 @@
+<%@ Control Language="VB" AutoEventWireup="true" %>
+<%@ Import Namespace="DotNetOpenAuth.OpenId.Extensions.SimpleRegistration" %>
+
+<script runat="server">
+
+ Private _profileValues As ClaimsResponse
+ Public Property ProfileValues() As ClaimsResponse
+ Get
+ Return _profileValues
+ End Get
+ Set(ByVal value As ClaimsResponse)
+ _profileValues = value
+ End Set
+ End Property
+
+</script>
+
+<table id="profileFieldsTable" runat="server">
+ <tr>
+ <td>
+ Nickname
+ </td>
+ <td>
+ <%=ProfileValues.Nickname %>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Email
+ </td>
+ <td>
+ <%=ProfileValues.Email%>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ FullName
+ </td>
+ <td>
+ <%=ProfileValues.FullName%>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Date of Birth
+ </td>
+ <td>
+ <%=ProfileValues.BirthDate.ToString()%>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Gender
+ </td>
+ <td>
+ <%=ProfileValues.Gender.ToString()%>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Post Code
+ </td>
+ <td>
+ <%=ProfileValues.PostalCode%>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Country
+ </td>
+ <td>
+ <%=ProfileValues.Country%>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Language
+ </td>
+ <td>
+ <%=ProfileValues.Language%>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Timezone
+ </td>
+ <td>
+ <%=ProfileValues.TimeZone%>
+ </td>
+ </tr>
+</table>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/Web.config b/samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/Web.config
new file mode 100644
index 0000000..3cfad05
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/MembersOnly/Web.config
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!--
+ Note: As an alternative to hand editing this file you can use the
+ web admin tool to configure settings for your application. Use
+ the Website->Asp.Net Configuration option in Visual Studio.
+ A full list of settings and comments can be found in
+ machine.config.comments usually located in
+ \Windows\Microsoft.Net\Framework\v2.x\Config
+-->
+<configuration>
+ <appSettings/>
+ <connectionStrings/>
+ <system.web>
+ <authorization>
+ <deny users="?"/>
+ </authorization>
+ </system.web>
+</configuration>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/My Project/Application.Designer.vb b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Application.Designer.vb
new file mode 100644
index 0000000..8a621ae
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Application.Designer.vb
@@ -0,0 +1,13 @@
+'------------------------------------------------------------------------------
+' <auto-generated>
+' This code was generated by a tool.
+' Runtime Version:2.0.50727.42
+'
+' Changes to this file may cause incorrect behavior and will be lost if
+' the code is regenerated.
+' </auto-generated>
+'------------------------------------------------------------------------------
+
+Option Strict On
+Option Explicit On
+
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/My Project/Application.myapp b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Application.myapp
new file mode 100644
index 0000000..758895d
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Application.myapp
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <MySubMain>false</MySubMain>
+ <SingleInstance>false</SingleInstance>
+ <ShutdownMode>0</ShutdownMode>
+ <EnableVisualStyles>true</EnableVisualStyles>
+ <AuthenticationMode>0</AuthenticationMode>
+ <ApplicationType>1</ApplicationType>
+ <SaveMySettingsOnExit>true</SaveMySettingsOnExit>
+</MyApplicationData>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/My Project/AssemblyInfo.vb b/samples/OpenIdRelyingPartyWebFormsVB/My Project/AssemblyInfo.vb
new file mode 100644
index 0000000..813551f
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/My Project/AssemblyInfo.vb
@@ -0,0 +1,34 @@
+Imports System
+Imports System.Reflection
+Imports System.Runtime.InteropServices
+
+' General Information about an assembly is controlled through the following
+' set of attributes. Change these attribute values to modify the information
+' associated with an assembly.
+
+' Review the values of the assembly attributes
+<Assembly: AssemblyTitle("OpenIdRelyingPartyWebFormsVB")>
+<Assembly: AssemblyDescription("")>
+<Assembly: AssemblyCompany("")>
+<Assembly: AssemblyProduct("OpenIdRelyingPartyWebFormsVB")>
+<Assembly: AssemblyCopyright("Copyright © 2010")>
+<Assembly: AssemblyTrademark("")>
+
+<Assembly: ComVisible(False)>
+
+'The following GUID is for the ID of the typelib if this project is exposed to COM
+<Assembly: Guid("334e9cee-0d47-4d70-924b-b5098a3432cb")>
+
+' Version information for an assembly consists of the following four values:
+'
+' Major Version
+' Minor Version
+' Build Number
+' Revision
+'
+' You can specify all the values or you can default the Build and Revision Numbers
+' by using the '*' as shown below:
+' <Assembly: AssemblyVersion("1.0.*")>
+
+<Assembly: AssemblyVersion("1.0.0.0")>
+<Assembly: AssemblyFileVersion("1.0.0.0")>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/My Project/MyExtensions/MyWebExtension.vb b/samples/OpenIdRelyingPartyWebFormsVB/My Project/MyExtensions/MyWebExtension.vb
new file mode 100644
index 0000000..78c7c19
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/My Project/MyExtensions/MyWebExtension.vb
@@ -0,0 +1,73 @@
+#If _MyType <> "Empty" Then
+
+Namespace My
+ ''' <summary>
+ ''' Module used to define the properties that are available in the My Namespace for Web projects.
+ ''' </summary>
+ ''' <remarks></remarks>
+ <Global.Microsoft.VisualBasic.HideModuleName()> _
+ Module MyWebExtension
+ Private s_Computer As New ThreadSafeObjectProvider(Of Global.Microsoft.VisualBasic.Devices.ServerComputer)
+ Private s_User As New ThreadSafeObjectProvider(Of Global.Microsoft.VisualBasic.ApplicationServices.WebUser)
+ Private s_Log As New ThreadSafeObjectProvider(Of Global.Microsoft.VisualBasic.Logging.AspLog)
+ ''' <summary>
+ ''' Returns information about the host computer.
+ ''' </summary>
+ <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")> _
+ Friend ReadOnly Property Computer() As Global.Microsoft.VisualBasic.Devices.ServerComputer
+ Get
+ Return s_Computer.GetInstance()
+ End Get
+ End Property
+ ''' <summary>
+ ''' Returns information for the current Web user.
+ ''' </summary>
+ <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")> _
+ Friend ReadOnly Property User() As Global.Microsoft.VisualBasic.ApplicationServices.WebUser
+ Get
+ Return s_User.GetInstance()
+ End Get
+ End Property
+ ''' <summary>
+ ''' Returns Request object.
+ ''' </summary>
+ <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")> _
+ <Global.System.ComponentModel.Design.HelpKeyword("My.Request")> _
+ Friend ReadOnly Property Request() As Global.System.Web.HttpRequest
+ <Global.System.Diagnostics.DebuggerHidden()> _
+ Get
+ Dim CurrentContext As Global.System.Web.HttpContext = Global.System.Web.HttpContext.Current
+ If CurrentContext IsNot Nothing Then
+ Return CurrentContext.Request
+ End If
+ Return Nothing
+ End Get
+ End Property
+ ''' <summary>
+ ''' Returns Response object.
+ ''' </summary>
+ <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")> _
+ <Global.System.ComponentModel.Design.HelpKeyword("My.Response")> _
+ Friend ReadOnly Property Response() As Global.System.Web.HttpResponse
+ <Global.System.Diagnostics.DebuggerHidden()> _
+ Get
+ Dim CurrentContext As Global.System.Web.HttpContext = Global.System.Web.HttpContext.Current
+ If CurrentContext IsNot Nothing Then
+ Return CurrentContext.Response
+ End If
+ Return Nothing
+ End Get
+ End Property
+ ''' <summary>
+ ''' Returns the Asp log object.
+ ''' </summary>
+ <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")> _
+ Friend ReadOnly Property Log() As Global.Microsoft.VisualBasic.Logging.AspLog
+ Get
+ Return s_Log.GetInstance()
+ End Get
+ End Property
+ End Module
+End Namespace
+
+#End If \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/My Project/Resources.Designer.vb b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Resources.Designer.vb
new file mode 100644
index 0000000..b38f687
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Resources.Designer.vb
@@ -0,0 +1,62 @@
+'------------------------------------------------------------------------------
+' <auto-generated>
+' This code was generated by a tool.
+' Runtime Version:2.0.50727.42
+'
+' Changes to this file may cause incorrect behavior and will be lost if
+' the code is regenerated.
+' </auto-generated>
+'------------------------------------------------------------------------------
+
+Option Strict On
+Option Explicit On
+
+
+Namespace My.Resources
+
+ 'This class was auto-generated by the StronglyTypedResourceBuilder
+ 'class via a tool like ResGen or Visual Studio.
+ 'To add or remove a member, edit your .ResX file then rerun ResGen
+ 'with the /str option, or rebuild your VS project.
+ '<summary>
+ ' A strongly-typed resource class, for looking up localized strings, etc.
+ '</summary>
+ <Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0"), _
+ Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
+ Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
+ Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
+ Friend Module Resources
+
+ Private resourceMan As Global.System.Resources.ResourceManager
+
+ Private resourceCulture As Global.System.Globalization.CultureInfo
+
+ '<summary>
+ ' Returns the cached ResourceManager instance used by this class.
+ '</summary>
+ <Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
+ Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
+ Get
+ If Object.ReferenceEquals(resourceMan, Nothing) Then
+ Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("OpenIdRelyingPartyWebFormsVB.Resources", GetType(Resources).Assembly)
+ resourceMan = temp
+ End If
+ Return resourceMan
+ End Get
+ End Property
+
+ '<summary>
+ ' Overrides the current thread's CurrentUICulture property for all
+ ' resource lookups using this strongly typed resource class.
+ '</summary>
+ <Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
+ Friend Property Culture() As Global.System.Globalization.CultureInfo
+ Get
+ Return resourceCulture
+ End Get
+ Set(ByVal value As Global.System.Globalization.CultureInfo)
+ resourceCulture = value
+ End Set
+ End Property
+ End Module
+End Namespace
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/My Project/Resources.resx b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Resources.resx
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/My Project/Settings.Designer.vb b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Settings.Designer.vb
new file mode 100644
index 0000000..82c5982
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Settings.Designer.vb
@@ -0,0 +1,73 @@
+'------------------------------------------------------------------------------
+' <auto-generated>
+' This code was generated by a tool.
+' Runtime Version:2.0.50727.42
+'
+' Changes to this file may cause incorrect behavior and will be lost if
+' the code is regenerated.
+' </auto-generated>
+'------------------------------------------------------------------------------
+
+Option Strict On
+Option Explicit On
+
+
+Namespace My
+
+ <Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
+ Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0"), _
+ Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
+ Partial Friend NotInheritable Class MySettings
+ Inherits Global.System.Configuration.ApplicationSettingsBase
+
+ Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings)
+
+#Region "My.Settings Auto-Save Functionality"
+#If _MyType = "WindowsForms" Then
+ Private Shared addedHandler As Boolean
+
+ Private Shared addedHandlerLockObject As New Object
+
+ <Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
+ Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
+ If My.Application.SaveMySettingsOnExit Then
+ My.Settings.Save()
+ End If
+ End Sub
+#End If
+#End Region
+
+ Public Shared ReadOnly Property [Default]() As MySettings
+ Get
+
+#If _MyType = "WindowsForms" Then
+ If Not addedHandler Then
+ SyncLock addedHandlerLockObject
+ If Not addedHandler Then
+ AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
+ addedHandler = True
+ End If
+ End SyncLock
+ End If
+#End If
+ Return defaultInstance
+ End Get
+ End Property
+ End Class
+End Namespace
+
+Namespace My
+
+ <Global.Microsoft.VisualBasic.HideModuleNameAttribute(), _
+ Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
+ Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
+ Friend Module MySettingsProperty
+
+ <Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")> _
+ Friend ReadOnly Property Settings() As Global.OpenIdRelyingPartyWebFormsVB.My.MySettings
+ Get
+ Return Global.OpenIdRelyingPartyWebFormsVB.My.MySettings.Default
+ End Get
+ End Property
+ End Module
+End Namespace
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/My Project/Settings.settings b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Settings.settings
new file mode 100644
index 0000000..85b890b
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/My Project/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/OpenIdRelyingPartyWebFormsVB.vbproj b/samples/OpenIdRelyingPartyWebFormsVB/OpenIdRelyingPartyWebFormsVB.vbproj
new file mode 100644
index 0000000..a43008c
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/OpenIdRelyingPartyWebFormsVB.vbproj
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>9.0.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F289B925-4307-4BEC-B411-885CE70E3379}</ProjectGuid>
+ <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}</ProjectTypeGuids>
+ <OutputType>Library</OutputType>
+ <RootNamespace>OpenIdRelyingPartyWebFormsVB</RootNamespace>
+ <AssemblyName>OpenIdRelyingPartyWebFormsVB</AssemblyName>
+ <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+ <MyType>Custom</MyType>
+ <OptionExplicit>On</OptionExplicit>
+ <OptionCompare>Binary</OptionCompare>
+ <OptionStrict>Off</OptionStrict>
+ <OptionInfer>On</OptionInfer>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <DefineDebug>true</DefineDebug>
+ <DefineTrace>true</DefineTrace>
+ <OutputPath>bin\</OutputPath>
+ <DocumentationFile>OpenIdRelyingPartyWebFormsVB.xml</DocumentationFile>
+ <NoWarn>41999,42016,42020,42021,42022</NoWarn>
+ <WarningsAsErrors>42017,42018,42019,42032,42036</WarningsAsErrors>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <DefineDebug>false</DefineDebug>
+ <DefineTrace>true</DefineTrace>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\</OutputPath>
+ <DocumentationFile>OpenIdRelyingPartyWebFormsVB.xml</DocumentationFile>
+ <NoWarn>41999,42016,42020,42021,42022</NoWarn>
+ <WarningsAsErrors>42017,42018,42019,42032,42036</WarningsAsErrors>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\lib\log4net.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Core">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Data.DataSetExtensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Web.Extensions">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Xml.Linq">
+ <RequiredTargetFramework>3.5</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="System.Web" />
+ <Reference Include="System.Xml" />
+ <Reference Include="System.Configuration" />
+ <Reference Include="System.Web.Services" />
+ <Reference Include="System.EnterpriseServices" />
+ <Reference Include="System.Web.Mobile" />
+ </ItemGroup>
+ <ItemGroup>
+ <Import Include="Microsoft.VisualBasic" />
+ <Import Include="System" />
+ <Import Include="System.Collections" />
+ <Import Include="System.Collections.Generic" />
+ <Import Include="System.Data" />
+ <Import Include="System.Linq" />
+ <Import Include="System.Xml.Linq" />
+ <Import Include="System.Diagnostics" />
+ <Import Include="System.Collections.Specialized" />
+ <Import Include="System.Configuration" />
+ <Import Include="System.Text" />
+ <Import Include="System.Text.RegularExpressions" />
+ <Import Include="System.Web" />
+ <Import Include="System.Web.Caching" />
+ <Import Include="System.Web.SessionState" />
+ <Import Include="System.Web.Security" />
+ <Import Include="System.Web.Profile" />
+ <Import Include="System.Web.UI" />
+ <Import Include="System.Web.UI.WebControls" />
+ <Import Include="System.Web.UI.WebControls.WebParts" />
+ <Import Include="System.Web.UI.HtmlControls" />
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Default.aspx" />
+ <Content Include="Login.aspx" />
+ <Content Include="Web.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Code\State.vb" />
+ <Compile Include="Code\TracePageAppender.vb" />
+ <Compile Include="Default.aspx.vb">
+ <SubType>ASPXCodeBehind</SubType>
+ <DependentUpon>Default.aspx</DependentUpon>
+ </Compile>
+ <Compile Include="Default.aspx.designer.vb">
+ <DependentUpon>Default.aspx</DependentUpon>
+ </Compile>
+ <Compile Include="Global.asax.vb">
+ <DependentUpon>Global.asax</DependentUpon>
+ </Compile>
+ <Compile Include="Login.aspx.designer.vb">
+ <DependentUpon>Login.aspx</DependentUpon>
+ </Compile>
+ <Compile Include="Login.aspx.vb">
+ <DependentUpon>Login.aspx</DependentUpon>
+ <SubType>ASPXCodebehind</SubType>
+ </Compile>
+ <Compile Include="LoginProgrammatic.aspx.designer.vb">
+ <DependentUpon>LoginProgrammatic.aspx</DependentUpon>
+ </Compile>
+ <Compile Include="LoginProgrammatic.aspx.vb">
+ <DependentUpon>LoginProgrammatic.aspx</DependentUpon>
+ <SubType>ASPXCodebehind</SubType>
+ </Compile>
+ <Compile Include="My Project\AssemblyInfo.vb" />
+ <Compile Include="My Project\Application.Designer.vb">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Application.myapp</DependentUpon>
+ </Compile>
+ <Compile Include="My Project\MyExtensions\MyWebExtension.vb">
+ <VBMyExtensionTemplateID>Microsoft.VisualBasic.Web.MyExtension</VBMyExtensionTemplateID>
+ <VBMyExtensionTemplateVersion>1.0.0.0</VBMyExtensionTemplateVersion>
+ </Compile>
+ <Compile Include="My Project\Resources.Designer.vb">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="My Project\Settings.Designer.vb">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <Compile Include="TracePage.aspx.designer.vb">
+ <DependentUpon>TracePage.aspx</DependentUpon>
+ </Compile>
+ <Compile Include="TracePage.aspx.vb">
+ <DependentUpon>TracePage.aspx</DependentUpon>
+ <SubType>ASPXCodebehind</SubType>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="My Project\Resources.resx">
+ <Generator>VbMyResourcesResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.vb</LastGenOutput>
+ <CustomToolNamespace>My.Resources</CustomToolNamespace>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="Global.asax" />
+ <Content Include="LoginProgrammatic.aspx" />
+ <Content Include="MembersOnly\ProfileFieldsDisplay.ascx" />
+ <Content Include="MembersOnly\Web.config" />
+ <None Include="My Project\Application.myapp">
+ <Generator>MyApplicationCodeGenerator</Generator>
+ <LastGenOutput>Application.Designer.vb</LastGenOutput>
+ </None>
+ <None Include="My Project\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <CustomToolNamespace>My</CustomToolNamespace>
+ <LastGenOutput>Settings.Designer.vb</LastGenOutput>
+ </None>
+ <Content Include="favicon.ico" />
+ <Content Include="images\attention.png" />
+ <Content Include="images\DotNetOpenAuth.png" />
+ <Content Include="images\openid_login.gif" />
+ <Content Include="images\yahoo.png" />
+ <Content Include="MembersOnly\Default.aspx" />
+ <Content Include="PrivacyPolicy.aspx" />
+ <Content Include="Site.Master" />
+ <Content Include="styles.css" />
+ <Content Include="TracePage.aspx" />
+ <Content Include="xrds.aspx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\src\DotNetOpenAuth\DotNetOpenAuth.csproj">
+ <Project>{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}</Project>
+ <Name>DotNetOpenAuth</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\DotNetOpenAuth.ApplicationBlock\DotNetOpenAuth.ApplicationBlock.csproj">
+ <Project>{AA78D112-D889-414B-A7D4-467B34C7B663}</Project>
+ <Name>DotNetOpenAuth.ApplicationBlock</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="App_Data\" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />
+ <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <ProjectExtensions>
+ <VisualStudio>
+ <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
+ <WebProjectProperties>
+ <UseIIS>False</UseIIS>
+ <AutoAssignPort>True</AutoAssignPort>
+ <DevelopmentServerPort>27433</DevelopmentServerPort>
+ <DevelopmentServerVPath>/</DevelopmentServerVPath>
+ <IISUrl>
+ </IISUrl>
+ <NTLMAuthentication>False</NTLMAuthentication>
+ <UseCustomServer>False</UseCustomServer>
+ <CustomServerUrl>
+ </CustomServerUrl>
+ <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
+ </WebProjectProperties>
+ </FlavorProperties>
+ </VisualStudio>
+ </ProjectExtensions>
+</Project> \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/PrivacyPolicy.aspx b/samples/OpenIdRelyingPartyWebFormsVB/PrivacyPolicy.aspx
new file mode 100644
index 0000000..7b72cd4
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/PrivacyPolicy.aspx
@@ -0,0 +1,7 @@
+<%@ Page Language="VB" AutoEventWireup="true" MasterPageFile="~/Site.Master" %>
+<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="Main">
+ <h2>Privacy Policy</h2>
+ <p>
+ Some privacy policy would go here.
+ </p>
+</asp:Content> \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Site.Master b/samples/OpenIdRelyingPartyWebFormsVB/Site.Master
new file mode 100644
index 0000000..48a8e50
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Site.Master
@@ -0,0 +1,39 @@
+<%@ Master Language="VB" AutoEventWireup="true" %>
+<%@ Import Namespace="OpenIdRelyingPartyWebFormsVB" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<script runat="server">
+ Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
+ friendlyUsername.Text = State.FriendlyLoginName
+ End Sub
+
+ Protected Sub LoginStatus1_LoggedOut(ByVal sender As Object, ByVal e As EventArgs)
+ State.Clear()
+ End Sub
+</script>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head runat="server">
+ <title>OpenID Relying Party, by DotNetOpenAuth</title>
+ <link href="styles.css" rel="stylesheet" type="text/css" />
+ <asp:ContentPlaceHolder ID="head" runat="server" />
+</head>
+<body>
+ <form id="form1" runat="server">
+ <span style="float: right">
+ <asp:Image runat="server" ID="openIdUsernameImage" ImageUrl="~/images/openid_login.gif"
+ EnableViewState="false" />
+ <asp:Label runat="server" ID="friendlyUsername" Text="" EnableViewState="false" />
+ <asp:LoginStatus ID="LoginStatus1" runat="server" OnLoggedOut="LoginStatus1_LoggedOut" />
+ </span>
+ <div>
+ <a href="http://dotnetopenauth.net">
+ <img runat="server" src="~/images/DotNetOpenAuth.png" title="Jump to the project web site."
+ alt="DotNetOpenAuth" border='0' /></a>
+ </div>
+ <div>
+ <asp:ContentPlaceHolder ID="Main" runat="server" />
+ </div>
+ </form>
+</body>
+</html>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx b/samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx
new file mode 100644
index 0000000..8df914b
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx
@@ -0,0 +1,16 @@
+<%@ Page Language="VB" AutoEventWireup="true" CodeBehind="TracePage.aspx.vb" Inherits="OpenIdRelyingPartyWebFormsVB.TracePage" %>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head id="Head1" runat="server">
+ <title></title>
+</head>
+<body>
+ <form id="form1" runat="server">
+ <p align="right">
+ <asp:Button runat="server" Text="Clear log" ID="clearLogButton" OnClick="clearLogButton_Click" />
+ </p>
+ <pre><asp:PlaceHolder runat="server" ID="placeHolder1" /></pre>
+ </form>
+</body>
+</html>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx.designer.vb b/samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx.designer.vb
new file mode 100644
index 0000000..9928c68
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx.designer.vb
@@ -0,0 +1,53 @@
+'------------------------------------------------------------------------------
+' <auto-generated>
+' This code was generated by a tool.
+' Runtime Version:2.0.50727.4927
+'
+' Changes to this file may cause incorrect behavior and will be lost if
+' the code is regenerated.
+' </auto-generated>
+'------------------------------------------------------------------------------
+
+Option Strict On
+Option Explicit On
+
+
+
+Partial Public Class TracePage
+
+ '''<summary>
+ '''Head1 control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents Head1 As Global.System.Web.UI.HtmlControls.HtmlHead
+
+ '''<summary>
+ '''form1 control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents form1 As Global.System.Web.UI.HtmlControls.HtmlForm
+
+ '''<summary>
+ '''clearLogButton control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents clearLogButton As Global.System.Web.UI.WebControls.Button
+
+ '''<summary>
+ '''placeHolder1 control.
+ '''</summary>
+ '''<remarks>
+ '''Auto-generated field.
+ '''To modify move field declaration from designer file to code-behind file.
+ '''</remarks>
+ Protected WithEvents placeHolder1 As Global.System.Web.UI.WebControls.PlaceHolder
+End Class
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx.vb b/samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx.vb
new file mode 100644
index 0000000..9a1b8c1
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/TracePage.aspx.vb
@@ -0,0 +1,13 @@
+Public Class TracePage
+ Inherits System.Web.UI.Page
+
+ Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
+ Me.placeHolder1.Controls.Add(New Label() With {.Text = HttpUtility.HtmlEncode(Global_asax.LogMessages.ToString())})
+ End Sub
+
+ Protected Sub clearLogButton_Click(ByVal sender As Object, ByVal e As EventArgs)
+ Global_asax.LogMessages.Length = 0
+ ' clear the page immediately, and allow for F5 without a Postback warning.
+ Me.Response.Redirect(Me.Request.Url.AbsoluteUri)
+ End Sub
+End Class \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Web.config b/samples/OpenIdRelyingPartyWebFormsVB/Web.config
new file mode 100644
index 0000000..f488900
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Web.config
@@ -0,0 +1,112 @@
+<?xml version="1.0"?>
+<configuration>
+ <configSections>
+ <section name="uri" type="System.Configuration.UriSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+ <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler" requirePermission="false" />
+ <section name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection" requirePermission="false" allowLocation="true"/>
+ </configSections>
+
+ <!-- The uri section is necessary to turn on .NET 3.5 support for IDN (international domain names),
+ which is necessary for OpenID urls with unicode characters in the domain/host name.
+ It is also required to put the Uri class into RFC 3986 escaping mode, which OpenID and OAuth require. -->
+ <uri>
+ <idn enabled="All"/>
+ <iriParsing enabled="true"/>
+ </uri>
+
+ <system.net>
+ <defaultProxy enabled="true" />
+ <settings>
+ <!-- This setting causes .NET to check certificate revocation lists (CRL)
+ before trusting HTTPS certificates. But this setting tends to not
+ be allowed in shared hosting environments. -->
+ <!--<servicePointManager checkCertificateRevocationList="true"/>-->
+ </settings>
+ </system.net>
+
+ <!-- this is an optional configuration section where aspects of dotnetopenauth can be customized -->
+ <dotNetOpenAuth>
+ <openid>
+ <relyingParty>
+ <security requireSsl="false" />
+ <behaviors>
+ <!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible
+ with OPs that use Attribute Exchange (in various formats). -->
+ <add type="DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform, DotNetOpenAuth" />
+ <!--<add type="DotNetOpenAuth.OpenId.Behaviors.GsaIcamProfile, DotNetOpenAuth" />-->
+ </behaviors>
+ <!-- Uncomment the following to activate the sample custom store. -->
+ <!--<store type="OpenIdRelyingPartyWebFormsVB.CustomStore, OpenIdRelyingPartyWebFormsVB" />-->
+ </relyingParty>
+ </openid>
+ <messaging>
+ <untrustedWebRequest>
+ <whitelistHosts>
+ <!-- since this is a sample, and will often be used with localhost -->
+ <add name="localhost" />
+ </whitelistHosts>
+ </untrustedWebRequest>
+ </messaging>
+ <!-- Allow DotNetOpenAuth to publish usage statistics to library authors to improve the library. -->
+ <reporting enabled="true" />
+ </dotNetOpenAuth>
+
+ <appSettings>
+ <!-- Fill in your various consumer keys and secrets here to make the sample work. -->
+ <!-- You must get these values by signing up with each individual service provider. -->
+ <!-- Google sign-up: https://www.google.com/accounts/ManageDomains -->
+ <add key="googleConsumerKey" value="demo.dotnetopenauth.net"/>
+ <add key="googleConsumerSecret" value="5Yv1TfKm1551QrXZ9GpqepeD"/>
+ </appSettings>
+
+ <system.web>
+ <!--<sessionState cookieless="true" />-->
+ <compilation debug="true"/>
+ <customErrors mode="RemoteOnly"/>
+ <authentication mode="Forms">
+ <forms name="OpenIdRelyingPartyVBSession"/> <!-- named cookie prevents conflicts with other samples -->
+ </authentication>
+ <trace enabled="false" writeToDiagnosticsTrace="true" />
+ <!-- Trust level discussion:
+ Full: everything works (this is required for Google Apps for Domains support)
+ High: TRACE compilation symbol must NOT be defined
+ Medium: doesn't work unless originUrl=".*" or WebPermission.Connect is extended, and Google Apps doesn't work.
+ Low: doesn't work because WebPermission.Connect is denied.
+ -->
+ <trust level="Medium" originUrl=".*"/>
+ </system.web>
+
+ <!-- log4net is a 3rd party (free) logger library that DotNetOpenAuth will use if present but does not require. -->
+ <log4net>
+ <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
+ <file value="RelyingParty.log" />
+ <appendToFile value="true" />
+ <rollingStyle value="Size" />
+ <maxSizeRollBackups value="10" />
+ <maximumFileSize value="100KB" />
+ <staticLogFileName value="true" />
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%date (GMT%date{%z}) [%thread] %-5level %logger - %message%newline" />
+ </layout>
+ </appender>
+ <appender name="TracePageAppender" type="OpenIdRelyingPartyWebFormsVB.TracePageAppender, OpenIdRelyingPartyWebFormsVB">
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%date (GMT%date{%z}) [%thread] %-5level %logger - %message%newline" />
+ </layout>
+ </appender>
+ <!-- Setup the root category, add the appenders and set the default level -->
+ <root>
+ <level value="INFO" />
+ <!--<appender-ref ref="RollingFileAppender" />-->
+ <appender-ref ref="TracePageAppender" />
+ </root>
+ <!-- Specify the level for some specific categories -->
+ <logger name="DotNetOpenAuth">
+ <level value="INFO" />
+ </logger>
+ </log4net>
+
+ <runtime>
+ <legacyHMACWarning enabled="0" />
+ </runtime>
+</configuration>
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/favicon.ico b/samples/OpenIdRelyingPartyWebFormsVB/favicon.ico
new file mode 100644
index 0000000..e227dbe
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/favicon.ico
Binary files differ
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/images/DotNetOpenAuth.png b/samples/OpenIdRelyingPartyWebFormsVB/images/DotNetOpenAuth.png
new file mode 100644
index 0000000..442b986
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/images/DotNetOpenAuth.png
Binary files differ
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/images/attention.png b/samples/OpenIdRelyingPartyWebFormsVB/images/attention.png
new file mode 100644
index 0000000..8003700
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/images/attention.png
Binary files differ
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/images/openid_login.gif b/samples/OpenIdRelyingPartyWebFormsVB/images/openid_login.gif
new file mode 100644
index 0000000..cde836c
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/images/openid_login.gif
Binary files differ
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/images/yahoo.png b/samples/OpenIdRelyingPartyWebFormsVB/images/yahoo.png
new file mode 100644
index 0000000..3129217
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/images/yahoo.png
Binary files differ
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/styles.css b/samples/OpenIdRelyingPartyWebFormsVB/styles.css
new file mode 100644
index 0000000..2e4d3db
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/styles.css
@@ -0,0 +1,10 @@
+h2
+{
+ font-style: italic;
+}
+
+body
+{
+ font-family: Cambria, Arial, Times New Roman;
+ font-size: 12pt;
+} \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/xrds.aspx b/samples/OpenIdRelyingPartyWebFormsVB/xrds.aspx
new file mode 100644
index 0000000..130ca30
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebFormsVB/xrds.aspx
@@ -0,0 +1,29 @@
+<%@ Page Language="VB" AutoEventWireup="true" ContentType="application/xrds+xml" %><?xml version="1.0" encoding="UTF-8"?>
+<%--
+This page is a required for relying party discovery per OpenID 2.0.
+It allows Providers to call back to the relying party site to confirm the
+identity that it is claiming in the realm and return_to URLs.
+This page should be pointed to by the 'realm' home page, which in this sample
+is default.aspx.
+--%>
+<xrds:XRDS
+ xmlns:xrds="xri://$xrds"
+ xmlns:openid="http://openid.net/xmlns/1.0"
+ xmlns="xri://$xrd*($v*2.0)">
+ <XRD>
+ <Service priority="1">
+ <Type>http://specs.openid.net/auth/2.0/return_to</Type>
+ <%-- Every page with an OpenID login should be listed here. --%>
+ <URI priority="1"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/login.aspx"))%></URI>
+ <URI priority="2"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/loginProgrammatic.aspx"))%></URI>
+ <URI priority="3"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/ajaxlogin.aspx"))%></URI>
+ <URI priority="4"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/NoIdentityOpenId.aspx"))%></URI>
+ <URI priority="5"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/loginPlusOAuth.aspx"))%></URI>
+ <URI priority="6"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/loginPlusOAuthSampleOP.aspx"))%></URI>
+ </Service>
+ <Service>
+ <Type>http://specs.openid.net/extensions/ui/icon</Type>
+ <URI><%=New Uri(Request.Url, Response.ApplyAppPathModifier("~/images/DotNetOpenAuth.png"))%></URI>
+ </Service>
+ </XRD>
+</xrds:XRDS>
diff --git a/samples/Samples.sln b/samples/Samples.sln
index 2761358..0a138cc 100644
--- a/samples/Samples.sln
+++ b/samples/Samples.sln
@@ -106,6 +106,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdWebRingSsoRelyingPart
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdOfflineProvider", "OpenIdOfflineProvider\OpenIdOfflineProvider.csproj", "{5C65603B-235F-47E6-B536-06385C60DE7F}"
EndProject
+Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "OpenIdRelyingPartyWebFormsVB", "OpenIdRelyingPartyWebFormsVB\OpenIdRelyingPartyWebFormsVB.vbproj", "{F289B925-4307-4BEC-B411-885CE70E3379}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CodeAnalysis|Any CPU = CodeAnalysis|Any CPU
@@ -191,6 +193,12 @@ Global
{5C65603B-235F-47E6-B536-06385C60DE7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C65603B-235F-47E6-B536-06385C60DE7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C65603B-235F-47E6-B536-06385C60DE7F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -204,6 +212,7 @@ Global
{0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4} = {A4059F7E-8E6F-4FA2-A1D5-1B9B46C93F82}
{B64A1E7E-6A15-4B91-AF13-7D48F7DA5942} = {A4059F7E-8E6F-4FA2-A1D5-1B9B46C93F82}
{5C65603B-235F-47E6-B536-06385C60DE7F} = {A4059F7E-8E6F-4FA2-A1D5-1B9B46C93F82}
+ {F289B925-4307-4BEC-B411-885CE70E3379} = {A4059F7E-8E6F-4FA2-A1D5-1B9B46C93F82}
{5100F73C-3082-4B81-95DD-F443F90B8EA7} = {812D828E-C91A-45AB-BAE9-3FC6D9560F9F}
{DD52C0C8-F986-495A-AAA1-090CFE2F801F} = {812D828E-C91A-45AB-BAE9-3FC6D9560F9F}
{6EC36418-DBC5-4AD1-A402-413604AA7A08} = {812D828E-C91A-45AB-BAE9-3FC6D9560F9F}
diff --git a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj
index daf6327..3f76f78 100644
--- a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj
+++ b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj
@@ -80,7 +80,9 @@
<Reference Include="Microsoft.Build.Utilities.v3.5">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
- <Reference Include="Microsoft.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=736440c9b414ea16, processorArchitecture=MSIL" />
+ <Reference Include="Microsoft.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=736440c9b414ea16, processorArchitecture=MSIL">
+ <Private>False</Private>
+ </Reference>
<Reference Include="Microsoft.Web.Administration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>$(SystemRoot)\System32\inetsrv\Microsoft.Web.Administration.dll</HintPath>
diff --git a/src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs b/src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs
index 48b5d5c..23db9a6 100644
--- a/src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs
+++ b/src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.IO;
using System.Linq;
using System.Text;
-using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
-using System.IO;
+using Microsoft.Build.Utilities;
namespace DotNetOpenAuth.BuildTasks {
public class GetBuildVersion : Task {
@@ -52,18 +54,54 @@ namespace DotNetOpenAuth.BuildTasks {
return string.Empty;
}
- string headContent = string.Empty;
+ string commitId = string.Empty;
+
+ // First try asking Git for the HEAD commit id
+ try {
+ string cmdPath = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.System), "cmd.exe");
+ ProcessStartInfo psi = new ProcessStartInfo(cmdPath, "/c git rev-parse HEAD");
+ psi.WindowStyle = ProcessWindowStyle.Hidden;
+ psi.RedirectStandardOutput = true;
+ psi.UseShellExecute = false;
+ Process git = Process.Start(psi);
+ commitId = git.StandardOutput.ReadLine();
+ git.WaitForExit();
+ if (git.ExitCode != 0) {
+ commitId = string.Empty;
+ }
+ if (commitId != null) {
+ commitId = commitId.Trim();
+ if (commitId.Length == 40) {
+ return commitId;
+ }
+ }
+ } catch (InvalidOperationException) {
+ } catch (Win32Exception) {
+ }
+
+ // Failing being able to use the git command to figure out the HEAD commit ID, try the filesystem directly.
try {
- headContent = File.ReadAllText(Path.Combine(this.GitRepoRoot, @".git/HEAD")).Trim();
+ string headContent = File.ReadAllText(Path.Combine(this.GitRepoRoot, @".git/HEAD")).Trim();
if (headContent.StartsWith("ref:", StringComparison.Ordinal)) {
string refName = headContent.Substring(5).Trim();
- headContent = File.ReadAllText(Path.Combine(this.GitRepoRoot, @".git/" + refName)).Trim();
+ string refPath = Path.Combine(this.GitRepoRoot, ".git/" + refName);
+ if (File.Exists(refPath)) {
+ commitId = File.ReadAllText(refPath).Trim();
+ } else {
+ string packedRefPath = Path.Combine(this.GitRepoRoot, ".git/packed-refs");
+ string matchingLine = File.ReadAllLines(packedRefPath).FirstOrDefault(line => line.EndsWith(refName));
+ if (matchingLine != null) {
+ commitId = matchingLine.Substring(0, matchingLine.IndexOf(' '));
+ }
+ }
+ } else {
+ commitId = headContent;
}
} catch (FileNotFoundException) {
} catch (DirectoryNotFoundException) {
}
- return headContent.Trim();
+ return commitId.Trim();
}
private Version ReadVersionFromFile() {
diff --git a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs
index ce0928e..8a8ae25 100644
--- a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs
@@ -11,8 +11,10 @@ namespace DotNetOpenAuth.Test.Messaging
using System.Collections.Specialized;
using System.IO;
using System.Net;
+ using System.Text.RegularExpressions;
using System.Web;
using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.Test.Mocks;
using NUnit.Framework;
[TestFixture]
@@ -139,5 +141,79 @@ namespace DotNetOpenAuth.Test.Messaging
Assert.AreEqual("%C2%80", MessagingUtilities.EscapeUriDataStringRfc3986("\u0080"));
Assert.AreEqual("%E3%80%81", MessagingUtilities.EscapeUriDataStringRfc3986("\u3001"));
}
+
+ /// <summary>
+ /// Verifies the overall format of the multipart POST is correct.
+ /// </summary>
+ [TestCase]
+ public void PostMultipart() {
+ var httpHandler = new TestWebRequestHandler();
+ bool callbackTriggered = false;
+ httpHandler.Callback = req => {
+ Match m = Regex.Match(req.ContentType, "multipart/form-data; boundary=(.+)");
+ Assert.IsTrue(m.Success, "Content-Type HTTP header not set correctly.");
+ string boundary = m.Groups[1].Value;
+ string expectedEntity = "--{0}\r\nContent-Disposition: form-data; name=\"a\"\r\n\r\nb\r\n--{0}--\r\n";
+ expectedEntity = string.Format(expectedEntity, boundary);
+ string actualEntity = httpHandler.RequestEntityAsString;
+ Assert.AreEqual(expectedEntity, actualEntity);
+ callbackTriggered = true;
+ Assert.AreEqual(req.ContentLength, actualEntity.Length);
+ IncomingWebResponse resp = new CachedDirectWebResponse();
+ return resp;
+ };
+ var request = (HttpWebRequest)WebRequest.Create("http://someserver");
+ var parts = new[] {
+ MultipartPostPart.CreateFormPart("a", "b"),
+ };
+ request.PostMultipart(httpHandler, parts);
+ Assert.IsTrue(callbackTriggered);
+ }
+
+ /// <summary>
+ /// Verifies proper behavior of GetHttpVerb
+ /// </summary>
+ [TestCase]
+ public void GetHttpVerbTest() {
+ Assert.AreEqual("GET", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.GetRequest));
+ Assert.AreEqual("POST", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.PostRequest));
+ Assert.AreEqual("HEAD", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.HeadRequest));
+ Assert.AreEqual("DELETE", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.DeleteRequest));
+ Assert.AreEqual("PUT", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.PutRequest));
+
+ Assert.AreEqual("GET", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest));
+ Assert.AreEqual("POST", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest));
+ Assert.AreEqual("HEAD", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.HeadRequest | HttpDeliveryMethods.AuthorizationHeaderRequest));
+ Assert.AreEqual("DELETE", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.DeleteRequest | HttpDeliveryMethods.AuthorizationHeaderRequest));
+ Assert.AreEqual("PUT", MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.PutRequest | HttpDeliveryMethods.AuthorizationHeaderRequest));
+ }
+
+ /// <summary>
+ /// Verifies proper behavior of GetHttpVerb on invalid input.
+ /// </summary>
+ [TestCase, ExpectedException(typeof(ArgumentException))]
+ public void GetHttpVerbOutOfRangeTest() {
+ MessagingUtilities.GetHttpVerb(HttpDeliveryMethods.PutRequest | HttpDeliveryMethods.PostRequest);
+ }
+
+ /// <summary>
+ /// Verifies proper behavior of GetHttpDeliveryMethod
+ /// </summary>
+ [TestCase]
+ public void GetHttpDeliveryMethodTest() {
+ Assert.AreEqual(HttpDeliveryMethods.GetRequest, MessagingUtilities.GetHttpDeliveryMethod("GET"));
+ Assert.AreEqual(HttpDeliveryMethods.PostRequest, MessagingUtilities.GetHttpDeliveryMethod("POST"));
+ Assert.AreEqual(HttpDeliveryMethods.HeadRequest, MessagingUtilities.GetHttpDeliveryMethod("HEAD"));
+ Assert.AreEqual(HttpDeliveryMethods.PutRequest, MessagingUtilities.GetHttpDeliveryMethod("PUT"));
+ Assert.AreEqual(HttpDeliveryMethods.DeleteRequest, MessagingUtilities.GetHttpDeliveryMethod("DELETE"));
+ }
+
+ /// <summary>
+ /// Verifies proper behavior of GetHttpDeliveryMethod for an unexpected input
+ /// </summary>
+ [TestCase, ExpectedException(typeof(ArgumentException))]
+ public void GetHttpDeliveryMethodOutOfRangeTest() {
+ MessagingUtilities.GetHttpDeliveryMethod("UNRECOGNIZED");
+ }
}
}
diff --git a/src/DotNetOpenAuth.Test/Messaging/MultiPartPostPartTests.cs b/src/DotNetOpenAuth.Test/Messaging/MultiPartPostPartTests.cs
deleted file mode 100644
index a293895..0000000
--- a/src/DotNetOpenAuth.Test/Messaging/MultiPartPostPartTests.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-//-----------------------------------------------------------------------
-// <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 NUnit.Framework;
-
- [TestFixture]
- public class MultipartPostPartTests : TestBase {
- /// <summary>
- /// Verifies that the Length property matches the length actually serialized.
- /// </summary>
- [TestCase]
- public void FormDataSerializeMatchesLength() {
- var part = MultipartPostPart.CreateFormPart("a", "b");
- VerifyLength(part);
- }
-
- /// <summary>
- /// Verifies that the length property matches the length actually serialized.
- /// </summary>
- [TestCase]
- 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>
- [TestCase]
- 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>
- [TestCase]
- 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) {
- TestUtilities.TestLogger.InfoFormat("{0}: {1}", header, req.Headers[header]);
- }
- TestUtilities.TestLogger.InfoFormat(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.Test/Messaging/MultipartPostPartTests.cs b/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs
index a293895..08524b2 100644
--- a/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs
+++ b/src/DotNetOpenAuth.Test/Messaging/MultipartPostPartTests.cs
@@ -38,6 +38,15 @@ namespace DotNetOpenAuth.Test.Messaging {
}
/// <summary>
+ /// Verifies file multiparts identify themselves as files and not merely form-data.
+ /// </summary>
+ [TestCase]
+ public void FilePartAsFile() {
+ var part = MultipartPostPart.CreateFormFilePart("somename", "somefile", "plain/text", new MemoryStream());
+ Assert.AreEqual("file", part.ContentDisposition);
+ }
+
+ /// <summary>
/// Verifies MultiPartPost sends the right number of bytes.
/// </summary>
[TestCase]
diff --git a/src/DotNetOpenAuth.Test/Mocks/TestDirectedMessage.cs b/src/DotNetOpenAuth.Test/Mocks/TestDirectedMessage.cs
index 342a303..1b3c2b2 100644
--- a/src/DotNetOpenAuth.Test/Mocks/TestDirectedMessage.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/TestDirectedMessage.cs
@@ -11,11 +11,11 @@ namespace DotNetOpenAuth.Test.Mocks {
internal class TestDirectedMessage : TestMessage, IDirectedProtocolMessage {
internal TestDirectedMessage() {
- this.HttpMethods = HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.PostRequest;
+ this.HttpMethods = HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.HeadRequest;
}
internal TestDirectedMessage(MessageTransport transport) : base(transport) {
- this.HttpMethods = HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.PostRequest;
+ this.HttpMethods = HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.HeadRequest;
}
#region IDirectedProtocolMessage Members
diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
index 5f068d1..c7b9f89 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
@@ -227,6 +227,11 @@ namespace DotNetOpenAuth.Test.ChannelElements {
this.ParameterizedRequestTest(HttpDeliveryMethods.PostRequest);
}
+ [TestCase]
+ public void RequestUsingHead() {
+ this.ParameterizedRequestTest(HttpDeliveryMethods.HeadRequest);
+ }
+
/// <summary>
/// Verifies that messages asking for special HTTP status codes get them.
/// </summary>
@@ -323,7 +328,7 @@ namespace DotNetOpenAuth.Test.ChannelElements {
this.webRequestHandler.Callback = (req) => {
Assert.IsNotNull(req);
HttpRequestInfo reqInfo = ConvertToRequestInfo(req, this.webRequestHandler.RequestEntityStream);
- Assert.AreEqual(scheme == HttpDeliveryMethods.PostRequest ? "POST" : "GET", reqInfo.HttpMethod);
+ Assert.AreEqual(MessagingUtilities.GetHttpVerb(scheme), reqInfo.HttpMethod);
var incomingMessage = this.channel.ReadFromRequest(reqInfo) as TestMessage;
Assert.IsNotNull(incomingMessage);
Assert.AreEqual(request.Age, incomingMessage.Age);
diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln
index d55996c..55d43e8 100644
--- a/src/DotNetOpenAuth.sln
+++ b/src/DotNetOpenAuth.sln
@@ -185,6 +185,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdWebRingSsoRelyingPart
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIdWebRingSsoProvider", "..\samples\OpenIdWebRingSsoProvider\OpenIdWebRingSsoProvider.csproj", "{0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}"
EndProject
+Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "OpenIdRelyingPartyWebFormsVB", "..\samples\OpenIdRelyingPartyWebFormsVB\OpenIdRelyingPartyWebFormsVB.vbproj", "{F289B925-4307-4BEC-B411-885CE70E3379}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CodeAnalysis|Any CPU = CodeAnalysis|Any CPU
@@ -315,6 +317,12 @@ Global
{0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.CodeAnalysis|Any CPU.ActiveCfg = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.CodeAnalysis|Any CPU.Build.0 = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F289B925-4307-4BEC-B411-885CE70E3379}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -332,6 +340,8 @@ Global
{BBACD972-014D-478F-9B07-56B9E1D4CC73} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
{B64A1E7E-6A15-4B91-AF13-7D48F7DA5942} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
{0B4EB2A8-283D-48FB-BCD0-85B8DFFE05E4} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
+ {6EB90284-BD15-461C-BBF2-131CF55F7C8B} = {8A5CEDB9-7F8A-4BE2-A1B9-97130F453277}
+ {F289B925-4307-4BEC-B411-885CE70E3379} = {034D5B5B-7D00-4A9D-8AFE-4A476E0575B1}
{6EC36418-DBC5-4AD1-A402-413604AA7A08} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6}
{9ADBE36D-9960-48F6-82E9-B4AC559E9AC3} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6}
{7ADCCD5C-AC2B-4340-9410-FE3A31A48191} = {1E2CBAA5-60A3-4AED-912E-541F5753CDC6}
diff --git a/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs b/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs
index 5ac88da..0335af5 100644
--- a/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs
+++ b/src/DotNetOpenAuth/Configuration/TypeConfigurationElement.cs
@@ -126,6 +126,7 @@ namespace DotNetOpenAuth.Configuration {
/// be present.
/// </remarks>
private static T CreateInstanceFromXaml(Stream xaml) {
+ Contract.Ensures(Contract.Result<T>() != null);
return (T)XamlReader.Load(xaml);
}
}
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index ee271f3..3bfecae 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -327,6 +327,7 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="OAuth\ConsumerSecuritySettings.cs" />
<Compile Include="OAuth\DesktopConsumer.cs" />
<Compile Include="GlobalSuppressions.cs" />
+ <Compile Include="Messaging\IMessageWithBinaryData.cs" />
<Compile Include="OAuth\Messages\ITokenSecretContainingMessage.cs" />
<Compile Include="Messaging\ChannelEventArgs.cs" />
<Compile Include="Messaging\ITamperProtectionChannelBindingElement.cs" />
diff --git a/src/DotNetOpenAuth/GlobalSuppressions.cs b/src/DotNetOpenAuth/GlobalSuppressions.cs
index a3343ba..e436846 100644
--- a/src/DotNetOpenAuth/GlobalSuppressions.cs
+++ b/src/DotNetOpenAuth/GlobalSuppressions.cs
@@ -56,3 +56,4 @@
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.OnOutgoingResponse(DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.OnIncomingRequest(DotNetOpenAuth.OpenId.Provider.IRequest)")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.ApplySecuritySettings(DotNetOpenAuth.OpenId.Provider.ProviderSecuritySettings)")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly")]
diff --git a/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs b/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
index b37c93a..dd34d90 100644
--- a/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
+++ b/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
@@ -153,10 +153,13 @@ namespace DotNetOpenAuth.Messaging {
/// <returns>The seekable Stream instance that contains a copy of what was returned in the HTTP response.</returns>
private static MemoryStream CacheNetworkStreamAndClose(HttpWebResponse response, int maximumBytesToRead) {
Contract.Requires<ArgumentNullException>(response != null);
+ Contract.Ensures(Contract.Result<MemoryStream>() != null);
// Now read and cache the network stream
Stream networkStream = response.GetResponseStream();
MemoryStream cachedStream = new MemoryStream(response.ContentLength < 0 ? 4 * 1024 : Math.Min((int)response.ContentLength, maximumBytesToRead));
+ Contract.Assume(networkStream.CanRead, "HttpWebResponse.GetResponseStream() always returns a readable stream."); // CC missing
+ Contract.Assume(cachedStream.CanWrite, "This is a MemoryStream -- it's always writable."); // CC missing
networkStream.CopyTo(cachedStream);
cachedStream.Seek(0, SeekOrigin.Begin);
diff --git a/src/DotNetOpenAuth/Messaging/Channel.cs b/src/DotNetOpenAuth/Messaging/Channel.cs
index ef6486a..1bddf02 100644
--- a/src/DotNetOpenAuth/Messaging/Channel.cs
+++ b/src/DotNetOpenAuth/Messaging/Channel.cs
@@ -580,7 +580,15 @@ namespace DotNetOpenAuth.Messaging {
fields = request.QueryStringBeforeRewriting.ToDictionary();
}
- return (IDirectedProtocolMessage)this.Receive(fields, request.GetRecipient());
+ MessageReceivingEndpoint recipient;
+ try {
+ recipient = request.GetRecipient();
+ } catch (ArgumentException ex) {
+ Logger.Messaging.WarnFormat("Unrecognized HTTP request: " + ex.ToString());
+ return null;
+ }
+
+ return (IDirectedProtocolMessage)this.Receive(fields, recipient);
}
/// <summary>
@@ -819,6 +827,24 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Prepares to send a request to the Service Provider as the query string in a HEAD request.
+ /// </summary>
+ /// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param>
+ /// <returns>The web request ready to send.</returns>
+ /// <remarks>
+ /// This method is simply a standard HTTP HEAD request with the message parts serialized to the query string.
+ /// This method satisfies OAuth 1.0 section 5.2, item #3.
+ /// </remarks>
+ protected virtual HttpWebRequest InitializeRequestAsHead(IDirectedProtocolMessage requestMessage) {
+ Contract.Requires<ArgumentNullException>(requestMessage != null);
+ Contract.Requires<ArgumentException>(requestMessage.Recipient != null, MessagingStrings.DirectedMessageMissingRecipient);
+
+ HttpWebRequest request = this.InitializeRequestAsGet(requestMessage);
+ request.Method = "HEAD";
+ return request;
+ }
+
+ /// <summary>
/// Prepares to send a request to the Service Provider as the payload of a POST request.
/// </summary>
/// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param>
@@ -838,7 +864,18 @@ namespace DotNetOpenAuth.Messaging {
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(requestMessage.Recipient);
httpRequest.CachePolicy = this.CachePolicy;
httpRequest.Method = "POST";
- this.SendParametersInEntity(httpRequest, fields);
+
+ var requestMessageWithBinaryData = requestMessage as IMessageWithBinaryData;
+ if (requestMessageWithBinaryData != null && requestMessageWithBinaryData.SendAsMultipart) {
+ var multiPartFields = new List<MultipartPostPart>(requestMessageWithBinaryData.BinaryData);
+
+ // When sending multi-part, all data gets send as multi-part -- even the non-binary data.
+ multiPartFields.AddRange(fields.Select(field => MultipartPostPart.CreateFormPart(field.Key, field.Value)));
+ this.SendParametersInEntityAsMultipart(httpRequest, multiPartFields);
+ } else {
+ ErrorUtilities.VerifyProtocol(requestMessageWithBinaryData == null || requestMessageWithBinaryData.BinaryData.Count == 0, MessagingStrings.BinaryDataRequiresMultipart);
+ this.SendParametersInEntity(httpRequest, fields);
+ }
return httpRequest;
}
@@ -914,6 +951,19 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Sends the given parameters in the entity stream of an HTTP request in multi-part format.
+ /// </summary>
+ /// <param name="httpRequest">The HTTP request.</param>
+ /// <param name="fields">The parameters to send.</param>
+ /// <remarks>
+ /// This method calls <see cref="HttpWebRequest.GetRequestStream()"/> and closes
+ /// the request stream, but does not call <see cref="HttpWebRequest.GetResponse"/>.
+ /// </remarks>
+ protected void SendParametersInEntityAsMultipart(HttpWebRequest httpRequest, IEnumerable<MultipartPostPart> fields) {
+ httpRequest.PostMultipartNoGetResponse(this.WebRequestHandler, fields);
+ }
+
+ /// <summary>
/// Verifies the integrity and applicability of an incoming message.
/// </summary>
/// <param name="message">The message just received.</param>
diff --git a/src/DotNetOpenAuth/Messaging/EmptyDictionary.cs b/src/DotNetOpenAuth/Messaging/EmptyDictionary.cs
index caf292a..9db5169 100644
--- a/src/DotNetOpenAuth/Messaging/EmptyDictionary.cs
+++ b/src/DotNetOpenAuth/Messaging/EmptyDictionary.cs
@@ -154,7 +154,7 @@ namespace DotNetOpenAuth.Messaging {
/// <exception cref="T:System.NotSupportedException">
/// The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
/// </exception>
- [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Code Contracts generates the code FxCop is complaining about.")]
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Code Contracts ccrewrite does this.")]
public void Add(KeyValuePair<TKey, TValue> item) {
throw new NotSupportedException();
}
diff --git a/src/DotNetOpenAuth/Messaging/EmptyList.cs b/src/DotNetOpenAuth/Messaging/EmptyList.cs
index ba918a4..68cdabd 100644
--- a/src/DotNetOpenAuth/Messaging/EmptyList.cs
+++ b/src/DotNetOpenAuth/Messaging/EmptyList.cs
@@ -99,7 +99,7 @@ namespace DotNetOpenAuth.Messaging {
/// <exception cref="T:System.NotSupportedException">
/// The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.
/// </exception>
- [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Code Contracts generates the code FxCop is complaining about.")]
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Code Contracts ccrewrite does this.")]
public void RemoveAt(int index) {
throw new ArgumentOutOfRangeException("index");
}
@@ -115,7 +115,7 @@ namespace DotNetOpenAuth.Messaging {
/// <exception cref="T:System.NotSupportedException">
/// The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
/// </exception>
- [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Code Contracts generates the code FxCop is complaining about.")]
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Code Contracts ccrewrite does this.")]
public void Add(T item) {
throw new NotSupportedException();
}
diff --git a/src/DotNetOpenAuth/Messaging/EnumerableCache.cs b/src/DotNetOpenAuth/Messaging/EnumerableCache.cs
index 71825bc..29ec533 100644
--- a/src/DotNetOpenAuth/Messaging/EnumerableCache.cs
+++ b/src/DotNetOpenAuth/Messaging/EnumerableCache.cs
@@ -35,6 +35,8 @@ namespace DotNetOpenAuth.Messaging {
/// to avoid double-caching.</para>
/// </remarks>
public static IEnumerable<T> CacheGeneratedResults<T>(this IEnumerable<T> sequence) {
+ Contract.Requires<ArgumentNullException>(sequence != null);
+
// Don't create a cache for types that don't need it.
if (sequence is IList<T> ||
sequence is ICollection<T> ||
diff --git a/src/DotNetOpenAuth/Messaging/HttpDeliveryMethods.cs b/src/DotNetOpenAuth/Messaging/HttpDeliveryMethods.cs
index 17c8f7a..1443fff 100644
--- a/src/DotNetOpenAuth/Messaging/HttpDeliveryMethods.cs
+++ b/src/DotNetOpenAuth/Messaging/HttpDeliveryMethods.cs
@@ -46,8 +46,13 @@ namespace DotNetOpenAuth.Messaging {
DeleteRequest = 0x10,
/// <summary>
+ /// Added to the URLs in the query part (as defined by [RFC3986] (Berners-Lee, T., “Uniform Resource Identifiers (URI): Generic Syntax,” .) section 3).
+ /// </summary>
+ HeadRequest = 0x20,
+
+ /// <summary>
/// The flags that control HTTP verbs.
/// </summary>
- HttpVerbMask = PostRequest | GetRequest | PutRequest | DeleteRequest,
+ HttpVerbMask = PostRequest | GetRequest | PutRequest | DeleteRequest | HeadRequest,
}
}
diff --git a/src/DotNetOpenAuth/Messaging/IDirectWebRequestHandler.cs b/src/DotNetOpenAuth/Messaging/IDirectWebRequestHandler.cs
index af03ba9..3420de9 100644
--- a/src/DotNetOpenAuth/Messaging/IDirectWebRequestHandler.cs
+++ b/src/DotNetOpenAuth/Messaging/IDirectWebRequestHandler.cs
@@ -187,6 +187,8 @@ namespace DotNetOpenAuth.Messaging {
/// </remarks>
IncomingWebResponse IDirectWebRequestHandler.GetResponse(HttpWebRequest request) {
Contract.Requires<ArgumentNullException>(request != null);
+ Contract.Ensures(Contract.Result<IncomingWebResponse>() != null);
+ Contract.Ensures(Contract.Result<IncomingWebResponse>().ResponseStream != null);
throw new System.NotImplementedException();
}
@@ -209,6 +211,9 @@ namespace DotNetOpenAuth.Messaging {
IncomingWebResponse IDirectWebRequestHandler.GetResponse(HttpWebRequest request, DirectWebRequestOptions options) {
Contract.Requires<ArgumentNullException>(request != null);
Contract.Requires<NotSupportedException>(((IDirectWebRequestHandler)this).CanSupport(options), MessagingStrings.DirectWebRequestOptionsNotSupported);
+ Contract.Ensures(Contract.Result<IncomingWebResponse>() != null);
+ Contract.Ensures(Contract.Result<IncomingWebResponse>().ResponseStream != null);
+
////ErrorUtilities.VerifySupported(((IDirectWebRequestHandler)this).CanSupport(options), string.Format(MessagingStrings.DirectWebRequestOptionsNotSupported, options, this.GetType().Name));
throw new System.NotImplementedException();
}
diff --git a/src/DotNetOpenAuth/Messaging/IMessageWithBinaryData.cs b/src/DotNetOpenAuth/Messaging/IMessageWithBinaryData.cs
new file mode 100644
index 0000000..f411cf5
--- /dev/null
+++ b/src/DotNetOpenAuth/Messaging/IMessageWithBinaryData.cs
@@ -0,0 +1,152 @@
+//-----------------------------------------------------------------------
+// <copyright file="IMessageWithBinaryData.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Messaging {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Linq;
+ using System.Text;
+
+ /// <summary>
+ /// The interface that classes must implement to be serialized/deserialized
+ /// as protocol or extension messages that uses POST multi-part data for binary content.
+ /// </summary>
+ [ContractClass(typeof(IMessageWithBinaryDataContract))]
+ public interface IMessageWithBinaryData : IDirectedProtocolMessage {
+ /// <summary>
+ /// Gets the parts of the message that carry binary data.
+ /// </summary>
+ /// <value>A list of parts. Never null.</value>
+ IList<MultipartPostPart> BinaryData { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether this message should be sent as multi-part POST.
+ /// </summary>
+ bool SendAsMultipart { get; }
+ }
+
+ /// <summary>
+ /// The contract class for the <see cref="IMessageWithBinaryData"/> interface.
+ /// </summary>
+ [ContractClassFor(typeof(IMessageWithBinaryData))]
+ internal sealed class IMessageWithBinaryDataContract : IMessageWithBinaryData {
+ #region IMessageWithBinaryData Members
+
+ /// <summary>
+ /// Gets the parts of the message that carry binary data.
+ /// </summary>
+ /// <value>A list of parts. Never null.</value>
+ IList<MultipartPostPart> IMessageWithBinaryData.BinaryData {
+ get {
+ Contract.Ensures(Contract.Result<IList<MultipartPostPart>>() != null);
+ throw new NotImplementedException();
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this message should be sent as multi-part POST.
+ /// </summary>
+ bool IMessageWithBinaryData.SendAsMultipart {
+ get { throw new NotImplementedException(); }
+ }
+
+ #endregion
+
+ #region IMessage Properties
+
+ /// <summary>
+ /// Gets the version of the protocol or extension this message is prepared to implement.
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// Implementations of this interface should ensure that this property never returns null.
+ /// </remarks>
+ Version IMessage.Version {
+ get {
+ Contract.Ensures(Contract.Result<Version>() != null);
+ return default(Version); // dummy return
+ }
+ }
+
+ /// <summary>
+ /// Gets the extra, non-standard Protocol parameters included in the message.
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// Implementations of this interface should ensure that this property never returns null.
+ /// </remarks>
+ IDictionary<string, string> IMessage.ExtraData {
+ get {
+ Contract.Ensures(Contract.Result<IDictionary<string, string>>() != null);
+ return default(IDictionary<string, string>);
+ }
+ }
+
+ #endregion
+
+ #region IDirectedProtocolMessage Members
+
+ /// <summary>
+ /// Gets the preferred method of transport for the message.
+ /// </summary>
+ /// <remarks>
+ /// For indirect messages this will likely be GET+POST, which both can be simulated in the user agent:
+ /// the GET with a simple 301 Redirect, and the POST with an HTML form in the response with javascript
+ /// to automate submission.
+ /// </remarks>
+ HttpDeliveryMethods IDirectedProtocolMessage.HttpMethods {
+ get { throw new NotImplementedException(); }
+ }
+
+ /// <summary>
+ /// Gets the URL of the intended receiver of this message.
+ /// </summary>
+ Uri IDirectedProtocolMessage.Recipient {
+ get { throw new NotImplementedException(); }
+ }
+
+ #endregion
+
+ #region IProtocolMessage Members
+
+ /// <summary>
+ /// Gets the level of protection this message requires.
+ /// </summary>
+ MessageProtections IProtocolMessage.RequiredProtection {
+ get { throw new NotImplementedException(); }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this is a direct or indirect message.
+ /// </summary>
+ MessageTransport IProtocolMessage.Transport {
+ get { throw new NotImplementedException(); }
+ }
+
+ #endregion
+
+ #region IMessage methods
+
+ /// <summary>
+ /// Checks the message state for conformity to the protocol specification
+ /// and throws an exception if the message is invalid.
+ /// </summary>
+ /// <remarks>
+ /// <para>Some messages have required fields, or combinations of fields that must relate to each other
+ /// in specialized ways. After deserializing a message, this method checks the state of the
+ /// message to see if it conforms to the protocol.</para>
+ /// <para>Note that this property should <i>not</i> check signatures or perform any state checks
+ /// outside this scope of this particular message.</para>
+ /// </remarks>
+ /// <exception cref="ProtocolException">Thrown if the message is invalid.</exception>
+ void IMessage.EnsureValidMessage() {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+}
diff --git a/src/DotNetOpenAuth/Messaging/ITamperProtectionChannelBindingElement.cs b/src/DotNetOpenAuth/Messaging/ITamperProtectionChannelBindingElement.cs
index ba25c12..87ea553 100644
--- a/src/DotNetOpenAuth/Messaging/ITamperProtectionChannelBindingElement.cs
+++ b/src/DotNetOpenAuth/Messaging/ITamperProtectionChannelBindingElement.cs
@@ -6,12 +6,14 @@
namespace DotNetOpenAuth.Messaging {
using System;
+ using System.Diagnostics.Contracts;
using DotNetOpenAuth.OAuth.ChannelElements;
/// <summary>
/// An interface that must be implemented by message transforms/validators in order
/// to be included in the channel stack.
/// </summary>
+ [ContractClass(typeof(ITamperProtectionChannelBindingElementContract))]
public interface ITamperProtectionChannelBindingElement : IChannelBindingElement {
/// <summary>
/// Gets or sets the delegate that will initialize the non-serialized properties necessary on a
@@ -25,4 +27,102 @@ namespace DotNetOpenAuth.Messaging {
/// <returns>The cloned instance.</returns>
ITamperProtectionChannelBindingElement Clone();
}
+
+ /// <summary>
+ /// Contract class for the <see cref="ITamperProtectionChannelBindingElement"/> interface.
+ /// </summary>
+ [ContractClassFor(typeof(ITamperProtectionChannelBindingElement))]
+ internal abstract class ITamperProtectionChannelBindingElementContract : ITamperProtectionChannelBindingElement {
+ #region ITamperProtectionChannelBindingElement Properties
+
+ /// <summary>
+ /// Gets or sets the delegate that will initialize the non-serialized properties necessary on a
+ /// signable message so that its signature can be correctly calculated or verified.
+ /// </summary>
+ Action<ITamperResistantOAuthMessage> ITamperProtectionChannelBindingElement.SignatureCallback {
+ get { throw new NotImplementedException(); }
+ set { throw new NotImplementedException(); }
+ }
+
+ #endregion
+
+ #region IChannelBindingElement Members
+
+ /// <summary>
+ /// Gets or sets the channel that this binding element belongs to.
+ /// </summary>
+ /// <remarks>
+ /// This property is set by the channel when it is first constructed.
+ /// </remarks>
+ Channel IChannelBindingElement.Channel {
+ get { throw new NotImplementedException(); }
+ set { throw new NotImplementedException(); }
+ }
+
+ /// <summary>
+ /// Gets the protection commonly offered (if any) by this binding element.
+ /// </summary>
+ /// <remarks>
+ /// This value is used to assist in sorting binding elements in the channel stack.
+ /// </remarks>
+ MessageProtections IChannelBindingElement.Protection {
+ get { throw new NotImplementedException(); }
+ }
+
+ /// <summary>
+ /// Prepares a message for sending based on the rules of this channel binding element.
+ /// </summary>
+ /// <param name="message">The message to prepare for sending.</param>
+ /// <returns>
+ /// The protections (if any) that this binding element applied to the message.
+ /// Null if this binding element did not even apply to this binding element.
+ /// </returns>
+ /// <remarks>
+ /// Implementations that provide message protection must honor the
+ /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
+ /// </remarks>
+ MessageProtections? IChannelBindingElement.ProcessOutgoingMessage(IProtocolMessage message) {
+ Contract.Requires<ArgumentNullException>(message != null);
+ Contract.Requires<InvalidOperationException>(((IChannelBindingElement)this).Channel != null);
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Performs any transformation on an incoming message that may be necessary and/or
+ /// validates an incoming message based on the rules of this channel binding element.
+ /// </summary>
+ /// <param name="message">The incoming message to process.</param>
+ /// <returns>
+ /// The protections (if any) that this binding element applied to the message.
+ /// Null if this binding element did not even apply to this binding element.
+ /// </returns>
+ /// <exception cref="ProtocolException">
+ /// Thrown when the binding element rules indicate that this message is invalid and should
+ /// NOT be processed.
+ /// </exception>
+ /// <remarks>
+ /// Implementations that provide message protection must honor the
+ /// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
+ /// </remarks>
+ MessageProtections? IChannelBindingElement.ProcessIncomingMessage(IProtocolMessage message) {
+ Contract.Requires<ArgumentNullException>(message != null);
+ Contract.Requires<InvalidOperationException>(((IChannelBindingElement)this).Channel != null);
+ throw new NotImplementedException();
+ }
+
+ #endregion
+
+ #region ITamperProtectionChannelBindingElement Methods
+
+ /// <summary>
+ /// Clones this instance.
+ /// </summary>
+ /// <returns>The cloned instance.</returns>
+ ITamperProtectionChannelBindingElement ITamperProtectionChannelBindingElement.Clone() {
+ Contract.Ensures(Contract.Result<ITamperProtectionChannelBindingElement>() != null);
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
}
diff --git a/src/DotNetOpenAuth/Messaging/MessageReceivingEndpoint.cs b/src/DotNetOpenAuth/Messaging/MessageReceivingEndpoint.cs
index e26a672..e39a047 100644
--- a/src/DotNetOpenAuth/Messaging/MessageReceivingEndpoint.cs
+++ b/src/DotNetOpenAuth/Messaging/MessageReceivingEndpoint.cs
@@ -24,6 +24,7 @@ namespace DotNetOpenAuth.Messaging {
: this(new Uri(locationUri), method) {
Contract.Requires<ArgumentNullException>(locationUri != null);
Contract.Requires<ArgumentOutOfRangeException>(method != HttpDeliveryMethods.None);
+ Contract.Requires<ArgumentOutOfRangeException>((method & HttpDeliveryMethods.HttpVerbMask) != 0, MessagingStrings.GetOrPostFlagsRequired);
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs b/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
index e5b725b..0bbac42 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingStrings.Designer.cs
@@ -70,6 +70,15 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
+ /// Looks up a localized string similar to Unable to send all message data because some of it requires multi-part POST, but IMessageWithBinaryData.SendAsMultipart was false..
+ /// </summary>
+ internal static string BinaryDataRequiresMultipart {
+ get {
+ return ResourceManager.GetString("BinaryDataRequiresMultipart", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to HttpContext.Current is null. There must be an ASP.NET request in process for this operation to succeed..
/// </summary>
internal static string CurrentHttpContextRequired {
diff --git a/src/DotNetOpenAuth/Messaging/MessagingStrings.resx b/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
index 3d4e317..34385d4 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
+++ b/src/DotNetOpenAuth/Messaging/MessagingStrings.resx
@@ -297,4 +297,7 @@
<data name="StreamMustHaveKnownLength" xml:space="preserve">
<value>The stream must have a known length.</value>
</data>
+ <data name="BinaryDataRequiresMultipart" xml:space="preserve">
+ <value>Unable to send all message data because some of it requires multi-part POST, but IMessageWithBinaryData.SendAsMultipart was false.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
index be5927f..c29ec8c 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
@@ -141,7 +141,7 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
- /// Sends an multipart HTTP POST request (useful for posting files).
+ /// Sends a multipart HTTP POST request (useful for posting files).
/// </summary>
/// <param name="request">The HTTP request.</param>
/// <param name="requestHandler">The request handler.</param>
@@ -152,14 +152,60 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentNullException>(requestHandler != null);
Contract.Requires<ArgumentNullException>(parts != null);
+ PostMultipartNoGetResponse(request, requestHandler, parts);
+ return requestHandler.GetResponse(request);
+ }
+
+ /// <summary>
+ /// Assembles a message comprised of the message on a given exception and all inner exceptions.
+ /// </summary>
+ /// <param name="exception">The exception.</param>
+ /// <returns>The assembled message.</returns>
+ public static string ToStringDescriptive(this Exception exception) {
+ // The input being null is probably bad, but since this method is called
+ // from a catch block, we don't really want to throw a new exception and
+ // hide the details of this one.
+ if (exception == null) {
+ Logger.Messaging.Error("MessagingUtilities.GetAllMessages called with null input.");
+ }
+
+ StringBuilder message = new StringBuilder();
+ while (exception != null) {
+ message.Append(exception.Message);
+ exception = exception.InnerException;
+ if (exception != null) {
+ message.Append(" ");
+ }
+ }
+
+ return message.ToString();
+ }
+
+ /// <summary>
+ /// Sends a multipart HTTP POST request (useful for posting files) but doesn't call GetResponse on it.
+ /// </summary>
+ /// <param name="request">The HTTP request.</param>
+ /// <param name="requestHandler">The request handler.</param>
+ /// <param name="parts">The parts to include in the POST entity.</param>
+ internal static void PostMultipartNoGetResponse(this HttpWebRequest request, IDirectWebRequestHandler requestHandler, IEnumerable<MultipartPostPart> parts) {
+ Contract.Requires<ArgumentNullException>(request != null);
+ Contract.Requires<ArgumentNullException>(requestHandler != null);
+ Contract.Requires<ArgumentNullException>(parts != null);
+
Reporting.RecordFeatureUse("MessagingUtilities.PostMultipart");
+ parts = parts.CacheGeneratedResults();
string boundary = Guid.NewGuid().ToString();
+ string initialPartLeadingBoundary = string.Format(CultureInfo.InvariantCulture, "--{0}\r\n", boundary);
string partLeadingBoundary = string.Format(CultureInfo.InvariantCulture, "\r\n--{0}\r\n", boundary);
string finalTrailingBoundary = string.Format(CultureInfo.InvariantCulture, "\r\n--{0}--\r\n", boundary);
request.Method = "POST";
request.ContentType = "multipart/form-data; boundary=" + boundary;
- request.ContentLength = parts.Sum(p => partLeadingBoundary.Length + p.Length) + finalTrailingBoundary.Length;
+ long contentLength = parts.Sum(p => partLeadingBoundary.Length + p.Length) + finalTrailingBoundary.Length;
+ if (parts.Any()) {
+ contentLength -= 2; // the initial part leading boundary has no leading \r\n
+ }
+ request.ContentLength = contentLength;
// Setting the content-encoding to "utf-8" causes Google to reply
// with a 415 UnsupportedMediaType. But adding it doesn't buy us
@@ -169,8 +215,10 @@ namespace DotNetOpenAuth.Messaging {
var requestStream = requestHandler.GetRequestStream(request);
try {
StreamWriter writer = new StreamWriter(requestStream, Channel.PostEntityEncoding);
+ bool firstPart = true;
foreach (var part in parts) {
- writer.Write(partLeadingBoundary);
+ writer.Write(firstPart ? initialPartLeadingBoundary : partLeadingBoundary);
+ firstPart = false;
part.Serialize(writer);
part.Dispose();
}
@@ -185,33 +233,6 @@ namespace DotNetOpenAuth.Messaging {
requestStream.Dispose();
}
}
-
- return requestHandler.GetResponse(request);
- }
-
- /// <summary>
- /// Assembles a message comprised of the message on a given exception and all inner exceptions.
- /// </summary>
- /// <param name="exception">The exception.</param>
- /// <returns>The assembled message.</returns>
- public static string ToStringDescriptive(this Exception exception) {
- // The input being null is probably bad, but since this method is called
- // from a catch block, we don't really want to throw a new exception and
- // hide the details of this one.
- if (exception == null) {
- Logger.Messaging.Error("MessagingUtilities.GetAllMessages called with null input.");
- }
-
- StringBuilder message = new StringBuilder();
- while (exception != null) {
- message.Append(exception.Message);
- exception = exception.InnerException;
- if (exception != null) {
- message.Append(" ");
- }
- }
-
- return message.ToString();
}
/// <summary>
@@ -646,6 +667,7 @@ namespace DotNetOpenAuth.Messaging {
/// </summary>
/// <param name="request">The request to get recipient information from.</param>
/// <returns>The recipient.</returns>
+ /// <exception cref="ArgumentException">Thrown if the HTTP request is something we can't handle.</exception>
internal static MessageReceivingEndpoint GetRecipient(this HttpRequestInfo request) {
return new MessageReceivingEndpoint(request.UrlBeforeRewriting, GetHttpDeliveryMethod(request.HttpMethod));
}
@@ -655,6 +677,7 @@ namespace DotNetOpenAuth.Messaging {
/// </summary>
/// <param name="httpVerb">The HTTP verb.</param>
/// <returns>A <see cref="HttpDeliveryMethods"/> enum value that is within the <see cref="HttpDeliveryMethods.HttpVerbMask"/>.</returns>
+ /// <exception cref="ArgumentException">Thrown if the HTTP request is something we can't handle.</exception>
internal static HttpDeliveryMethods GetHttpDeliveryMethod(string httpVerb) {
if (httpVerb == "GET") {
return HttpDeliveryMethods.GetRequest;
@@ -664,6 +687,8 @@ namespace DotNetOpenAuth.Messaging {
return HttpDeliveryMethods.PutRequest;
} else if (httpVerb == "DELETE") {
return HttpDeliveryMethods.DeleteRequest;
+ } else if (httpVerb == "HEAD") {
+ return HttpDeliveryMethods.HeadRequest;
} else {
throw ErrorUtilities.ThrowArgumentNamed("httpVerb", MessagingStrings.UnsupportedHttpVerb, httpVerb);
}
@@ -675,14 +700,16 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="httpMethod">The HTTP method.</param>
/// <returns>An HTTP verb, such as GET, POST, PUT, or DELETE.</returns>
internal static string GetHttpVerb(HttpDeliveryMethods httpMethod) {
- if ((httpMethod & HttpDeliveryMethods.GetRequest) != 0) {
+ if ((httpMethod & HttpDeliveryMethods.HttpVerbMask) == HttpDeliveryMethods.GetRequest) {
return "GET";
- } else if ((httpMethod & HttpDeliveryMethods.PostRequest) != 0) {
+ } else if ((httpMethod & HttpDeliveryMethods.HttpVerbMask) == HttpDeliveryMethods.PostRequest) {
return "POST";
- } else if ((httpMethod & HttpDeliveryMethods.PutRequest) != 0) {
+ } else if ((httpMethod & HttpDeliveryMethods.HttpVerbMask) == HttpDeliveryMethods.PutRequest) {
return "PUT";
- } else if ((httpMethod & HttpDeliveryMethods.DeleteRequest) != 0) {
+ } else if ((httpMethod & HttpDeliveryMethods.HttpVerbMask) == HttpDeliveryMethods.DeleteRequest) {
return "DELETE";
+ } else if ((httpMethod & HttpDeliveryMethods.HttpVerbMask) == HttpDeliveryMethods.HeadRequest) {
+ return "HEAD";
} else if ((httpMethod & HttpDeliveryMethods.AuthorizationHeaderRequest) != 0) {
return "GET"; // if AuthorizationHeaderRequest is specified without an explicit HTTP verb, assume GET.
} else {
diff --git a/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs b/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs
index 7ef89a4..f9a5988 100644
--- a/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs
+++ b/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs
@@ -116,6 +116,10 @@ namespace DotNetOpenAuth.Messaging {
/// <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) {
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(name));
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(filePath));
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(contentType));
+
string fileName = Path.GetFileName(filePath);
return CreateFormFilePart(name, fileName, contentType, File.OpenRead(filePath));
}
@@ -130,11 +134,11 @@ namespace DotNetOpenAuth.Messaging {
/// <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>(!string.IsNullOrEmpty(fileName));
+ Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(contentType));
Contract.Requires<ArgumentException>(content != null);
- var part = new MultipartPostPart("form-data");
+ var part = new MultipartPostPart("file");
part.ContentAttributes["name"] = name;
part.ContentAttributes["filename"] = fileName;
part.PartHeaders[HttpRequestHeader.ContentType] = contentType;
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessageDictionary.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessageDictionary.cs
index 49e30cb..f6eed24 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessageDictionary.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessageDictionary.cs
@@ -269,7 +269,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
/// Sets a named value in the message.
/// </summary>
/// <param name="item">The name-value pair to add. The name is the serialized form of the key.</param>
- [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Code Contracts generates the code FxCop is complaining about.")]
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Code Contracts ccrewrite does this.")]
public void Add(KeyValuePair<string, string> item) {
this.Add(item.Key, item.Value);
}
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
index 32d2fec..08e2411 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
@@ -286,6 +286,9 @@ namespace DotNetOpenAuth.Messaging.Reflection {
/// <param name="messagePartEncoder">The message part encoder type.</param>
/// <returns>An instance of the desired encoder.</returns>
private static IMessagePartEncoder GetEncoder(Type messagePartEncoder) {
+ Contract.Requires<ArgumentNullException>(messagePartEncoder != null);
+ Contract.Ensures(Contract.Result<IMessagePartEncoder>() != null);
+
IMessagePartEncoder encoder;
if (!encoders.TryGetValue(messagePartEncoder, out encoder)) {
encoder = encoders[messagePartEncoder] = (IMessagePartEncoder)Activator.CreateInstance(messagePartEncoder);
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
index 8c5980f..b0e938f 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
@@ -11,6 +11,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
+ using System.Linq;
using System.Net;
using System.Text;
using System.Web;
@@ -87,7 +88,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// </summary>
/// <param name="message">The message with data to encode.</param>
/// <returns>A dictionary of name-value pairs with their strings encoded.</returns>
- internal static IDictionary<string, string> GetUriEscapedParameters(MessageDictionary message) {
+ internal static IDictionary<string, string> GetUriEscapedParameters(IEnumerable<KeyValuePair<string, string>> message) {
var encodedDictionary = new Dictionary<string, string>();
UriEscapeParameters(message, encodedDictionary);
return encodedDictionary;
@@ -155,8 +156,16 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
}
}
+ MessageReceivingEndpoint recipient;
+ try {
+ recipient = request.GetRecipient();
+ } catch (ArgumentException ex) {
+ Logger.OAuth.WarnFormat("Unrecognized HTTP request: " + ex.ToString());
+ return null;
+ }
+
// Deserialize the message using all the data we've collected.
- var message = (IDirectedProtocolMessage)this.Receive(fields, request.GetRecipient());
+ var message = (IDirectedProtocolMessage)this.Receive(fields, recipient);
// Add receiving HTTP transport information required for signature generation.
var signedMessage = message as ITamperResistantOAuthMessage;
@@ -194,9 +203,13 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
if ((transmissionMethod & HttpDeliveryMethods.AuthorizationHeaderRequest) != 0) {
httpRequest = this.InitializeRequestAsAuthHeader(request);
} else if ((transmissionMethod & HttpDeliveryMethods.PostRequest) != 0) {
+ var requestMessageWithBinaryData = request as IMessageWithBinaryData;
+ ErrorUtilities.VerifyProtocol(requestMessageWithBinaryData == null || !requestMessageWithBinaryData.SendAsMultipart, OAuthStrings.MultipartPostMustBeUsedWithAuthHeader);
httpRequest = this.InitializeRequestAsPost(request);
} else if ((transmissionMethod & HttpDeliveryMethods.GetRequest) != 0) {
httpRequest = InitializeRequestAsGet(request);
+ } else if ((transmissionMethod & HttpDeliveryMethods.HeadRequest) != 0) {
+ httpRequest = InitializeRequestAsHead(request);
} else if ((transmissionMethod & HttpDeliveryMethods.PutRequest) != 0) {
httpRequest = this.InitializeRequestAsPut(request);
} else if ((transmissionMethod & HttpDeliveryMethods.DeleteRequest) != 0) {
@@ -264,7 +277,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// </summary>
/// <param name="source">The dictionary with names and values to encode.</param>
/// <param name="destination">The dictionary to add the encoded pairs to.</param>
- private static void UriEscapeParameters(IDictionary<string, string> source, IDictionary<string, string> destination) {
+ private static void UriEscapeParameters(IEnumerable<KeyValuePair<string, string>> source, IDictionary<string, string> destination) {
Contract.Requires<ArgumentNullException>(source != null);
Contract.Requires<ArgumentNullException>(destination != null);
@@ -341,12 +354,22 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
if (hasEntity) {
// WARNING: We only set up the request stream for the caller if there is
// extra data. If there isn't any extra data, the caller must do this themselves.
- if (requestMessage.ExtraData.Count > 0) {
- SendParametersInEntity(httpRequest, requestMessage.ExtraData);
+ var requestMessageWithBinaryData = requestMessage as IMessageWithBinaryData;
+ if (requestMessageWithBinaryData != null && requestMessageWithBinaryData.SendAsMultipart) {
+ // Include the binary data in the multipart entity, and any standard text extra message data.
+ // The standard declared message parts are included in the authorization header.
+ var multiPartFields = new List<MultipartPostPart>(requestMessageWithBinaryData.BinaryData);
+ multiPartFields.AddRange(requestMessage.ExtraData.Select(field => MultipartPostPart.CreateFormPart(field.Key, field.Value)));
+ this.SendParametersInEntityAsMultipart(httpRequest, multiPartFields);
} else {
- // We'll assume the content length is zero since the caller may not have
- // anything. They're responsible to change it when the add the payload if they have one.
- httpRequest.ContentLength = 0;
+ ErrorUtilities.VerifyProtocol(requestMessageWithBinaryData == null || requestMessageWithBinaryData.BinaryData.Count == 0, MessagingStrings.BinaryDataRequiresMultipart);
+ if (requestMessage.ExtraData.Count > 0) {
+ this.SendParametersInEntity(httpRequest, requestMessage.ExtraData);
+ } else {
+ // We'll assume the content length is zero since the caller may not have
+ // anything. They're responsible to change it when the add the payload if they have one.
+ httpRequest.ContentLength = 0;
+ }
}
}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
index 004e7d5..b45da66 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
@@ -10,6 +10,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
using System.Collections.Specialized;
using System.Diagnostics.Contracts;
using System.Globalization;
+ using System.Linq;
using System.Text;
using System.Web;
using DotNetOpenAuth.Messaging;
@@ -157,7 +158,26 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
signatureBaseStringElements.Add(message.HttpMethod.ToUpperInvariant());
- var encodedDictionary = OAuthChannel.GetUriEscapedParameters(messageDictionary);
+ // For multipart POST messages, only include the message parts that are NOT
+ // in the POST entity (those parts that may appear in an OAuth authorization header).
+ var encodedDictionary = new Dictionary<string, string>();
+ IEnumerable<KeyValuePair<string, string>> partsToInclude = Enumerable.Empty<KeyValuePair<string, string>>();
+ var binaryMessage = message as IMessageWithBinaryData;
+ if (binaryMessage != null && binaryMessage.SendAsMultipart) {
+ HttpDeliveryMethods authHeaderInUseFlags = HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest;
+ ErrorUtilities.VerifyProtocol((binaryMessage.HttpMethods & authHeaderInUseFlags) == authHeaderInUseFlags, OAuthStrings.MultipartPostMustBeUsedWithAuthHeader);
+
+ // Include the declared keys in the signature as those will be signable.
+ // Cache in local variable to avoid recalculating DeclaredKeys in the delegate.
+ ICollection<string> declaredKeys = messageDictionary.DeclaredKeys;
+ partsToInclude = messageDictionary.Where(pair => declaredKeys.Contains(pair.Key));
+ } else {
+ partsToInclude = messageDictionary;
+ }
+
+ foreach (var pair in OAuthChannel.GetUriEscapedParameters(partsToInclude)) {
+ encodedDictionary[pair.Key] = pair.Value;
+ }
// An incoming message will already have included the query and form parameters
// in the message dictionary, but an outgoing message COULD have SOME parameters
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementChain.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementChain.cs
index bdb0219..67c5205 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementChain.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementChain.cs
@@ -20,7 +20,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <summary>
/// The various signing binding elements that may be applicable to a message in preferred use order.
/// </summary>
- private ITamperProtectionChannelBindingElement[] signers;
+ private readonly ITamperProtectionChannelBindingElement[] signers;
/// <summary>
/// Initializes a new instance of the <see cref="SigningBindingElementChain"/> class.
@@ -93,6 +93,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// </returns>
public MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) {
foreach (IChannelBindingElement signer in this.signers) {
+ ErrorUtilities.VerifyInternal(signer.Channel != null, "A binding element's Channel property is unexpectedly null.");
MessageProtections? result = signer.ProcessOutgoingMessage(message);
if (result.HasValue) {
return result;
@@ -113,6 +114,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// </returns>
public MessageProtections? ProcessIncomingMessage(IProtocolMessage message) {
foreach (IChannelBindingElement signer in this.signers) {
+ ErrorUtilities.VerifyInternal(signer.Channel != null, "A binding element's Channel property is unexpectedly null.");
MessageProtections? result = signer.ProcessIncomingMessage(message);
if (result.HasValue) {
return result;
diff --git a/src/DotNetOpenAuth/OAuth/ConsumerBase.cs b/src/DotNetOpenAuth/OAuth/ConsumerBase.cs
index 6c0ce42..48f54d7 100644
--- a/src/DotNetOpenAuth/OAuth/ConsumerBase.cs
+++ b/src/DotNetOpenAuth/OAuth/ConsumerBase.cs
@@ -9,6 +9,7 @@ namespace DotNetOpenAuth.OAuth {
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
+ using System.Linq;
using System.Net;
using DotNetOpenAuth.Configuration;
using DotNetOpenAuth.Messaging;
@@ -111,6 +112,27 @@ namespace DotNetOpenAuth.OAuth {
}
/// <summary>
+ /// Prepares an authorized request that carries an HTTP multi-part POST, allowing for binary data.
+ /// </summary>
+ /// <param name="endpoint">The URL and method on the Service Provider to send the request to.</param>
+ /// <param name="accessToken">The access token that permits access to the protected resource.</param>
+ /// <param name="binaryData">Extra parameters to include in the message. Must not be null, but may be empty.</param>
+ /// <returns>The initialized WebRequest object.</returns>
+ public HttpWebRequest PrepareAuthorizedRequest(MessageReceivingEndpoint endpoint, string accessToken, IEnumerable<MultipartPostPart> binaryData) {
+ Contract.Requires<ArgumentNullException>(endpoint != null);
+ Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(accessToken));
+ Contract.Requires<ArgumentNullException>(binaryData != null);
+
+ AccessProtectedResourceRequest message = this.CreateAuthorizingMessage(endpoint, accessToken);
+ foreach (MultipartPostPart part in binaryData) {
+ message.BinaryData.Add(part);
+ }
+
+ HttpWebRequest wr = this.OAuthChannel.InitializeRequest(message);
+ return wr;
+ }
+
+ /// <summary>
/// Prepares an HTTP request that has OAuth authorization already attached to it.
/// </summary>
/// <param name="message">The OAuth authorization message to attach to the HTTP request.</param>
diff --git a/src/DotNetOpenAuth/OAuth/Messages/AccessProtectedResourceRequest.cs b/src/DotNetOpenAuth/OAuth/Messages/AccessProtectedResourceRequest.cs
index b60fda4..f3231f0 100644
--- a/src/DotNetOpenAuth/OAuth/Messages/AccessProtectedResourceRequest.cs
+++ b/src/DotNetOpenAuth/OAuth/Messages/AccessProtectedResourceRequest.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.OAuth.Messages {
using System;
+ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using DotNetOpenAuth.Messaging;
@@ -13,7 +14,12 @@ namespace DotNetOpenAuth.OAuth.Messages {
/// A message attached to a request for protected resources that provides the necessary
/// credentials to be granted access to those resources.
/// </summary>
- public class AccessProtectedResourceRequest : SignedMessageBase, ITokenContainingMessage {
+ public class AccessProtectedResourceRequest : SignedMessageBase, ITokenContainingMessage, IMessageWithBinaryData {
+ /// <summary>
+ /// A store for the binary data that is carried in the message.
+ /// </summary>
+ private List<MultipartPostPart> binaryData = new List<MultipartPostPart>();
+
/// <summary>
/// Initializes a new instance of the <see cref="AccessProtectedResourceRequest"/> class.
/// </summary>
@@ -43,5 +49,24 @@ namespace DotNetOpenAuth.OAuth.Messages {
/// </remarks>
[MessagePart("oauth_token", IsRequired = true)]
public string AccessToken { get; set; }
+
+ #region IMessageWithBinaryData Members
+
+ /// <summary>
+ /// Gets the parts of the message that carry binary data.
+ /// </summary>
+ /// <value>A list of parts. Never null.</value>
+ public IList<MultipartPostPart> BinaryData {
+ get { return this.binaryData; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this message should be sent as multi-part POST.
+ /// </summary>
+ public bool SendAsMultipart {
+ get { return this.HttpMethod == "POST" && this.BinaryData.Count > 0; }
+ }
+
+ #endregion
}
}
diff --git a/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs b/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs
index bb4d5d9..fb4c9a1 100644
--- a/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs
+++ b/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs
@@ -124,6 +124,15 @@ namespace DotNetOpenAuth.OAuth {
}
/// <summary>
+ /// Looks up a localized string similar to Cannot send OAuth message as multipart POST without an authorization HTTP header because sensitive data would not be signed..
+ /// </summary>
+ internal static string MultipartPostMustBeUsedWithAuthHeader {
+ get {
+ return ResourceManager.GetString("MultipartPostMustBeUsedWithAuthHeader", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Use of the OpenID+OAuth extension requires that the token manager in use implement the {0} interface..
/// </summary>
internal static string OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface {
diff --git a/src/DotNetOpenAuth/OAuth/OAuthStrings.resx b/src/DotNetOpenAuth/OAuth/OAuthStrings.resx
index bbeeda9..34b314b 100644
--- a/src/DotNetOpenAuth/OAuth/OAuthStrings.resx
+++ b/src/DotNetOpenAuth/OAuth/OAuthStrings.resx
@@ -138,6 +138,9 @@
<data name="MinimumConsumerVersionRequirementNotMet" xml:space="preserve">
<value>This OAuth service provider requires OAuth consumers to implement OAuth {0}, but this consumer appears to only support {1}.</value>
</data>
+ <data name="MultipartPostMustBeUsedWithAuthHeader" xml:space="preserve">
+ <value>Cannot send OAuth message as multipart POST without an authorization HTTP header because sensitive data would not be signed.</value>
+ </data>
<data name="OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface" xml:space="preserve">
<value>Use of the OpenID+OAuth extension requires that the token manager in use implement the {0} interface.</value>
</data>
diff --git a/src/DotNetOpenAuth/OAuth/ServiceProviderDescription.cs b/src/DotNetOpenAuth/OAuth/ServiceProviderDescription.cs
index 9014762..6205f55 100644
--- a/src/DotNetOpenAuth/OAuth/ServiceProviderDescription.cs
+++ b/src/DotNetOpenAuth/OAuth/ServiceProviderDescription.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OAuth {
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
using System.Linq;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth.ChannelElements;
@@ -94,6 +95,7 @@ namespace DotNetOpenAuth.OAuth {
/// </summary>
/// <returns>The created signing element.</returns>
internal ITamperProtectionChannelBindingElement CreateTamperProtectionElement() {
+ Contract.Requires(this.TamperProtectionElements != null);
return new SigningBindingElementChain(this.TamperProtectionElements.Select(el => (ITamperProtectionChannelBindingElement)el.Clone()).ToArray());
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs b/src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs
index d7dca9a..580bdfd 100644
--- a/src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs
+++ b/src/DotNetOpenAuth/OpenId/Behaviors/AXFetchAsSregTransform.cs
@@ -23,7 +23,7 @@ namespace DotNetOpenAuth.OpenId.Behaviors {
/// to the originally requested extension and format.
/// </summary>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sreg", Justification = "Abbreviation")]
- public class AXFetchAsSregTransform : IRelyingPartyBehavior, IProviderBehavior {
+ public sealed class AXFetchAsSregTransform : IRelyingPartyBehavior, IProviderBehavior {
/// <summary>
/// Initializes static members of the <see cref="AXFetchAsSregTransform"/> class.
/// </summary>
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
index 4fa70a0..c516e8f 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/ExtensionsBindingElement.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId.ChannelElements {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
@@ -76,6 +77,7 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// Implementations that provide message protection must honor the
/// <see cref="MessagePartAttribute.RequiredProtection"/> properties where applicable.
/// </remarks>
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "It doesn't look too bad to me. :)")]
public MessageProtections? ProcessOutgoingMessage(IProtocolMessage message) {
var extendableMessage = message as IProtocolMessageWithExtensions;
if (extendableMessage != null) {
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
index 67efe8e..76a1c9b 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
@@ -70,7 +70,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.UI {
/// <remarks>
/// The user's preferred languages as a [BCP 47] language priority list, represented as a comma-separated list of BCP 47 basic language ranges in descending priority order. For instance, the value "fr-CA,fr-FR,en-CA" represents the preference for French spoken in Canada, French spoken in France, followed by English spoken in Canada.
/// </remarks>
- [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "By design")]
+ [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "By design.")]
[MessagePart("lang", AllowEmpty = false)]
public CultureInfo[] LanguagePreference { get; set; }
diff --git a/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs b/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs
index b6ed2f7..e96f362 100644
--- a/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs
+++ b/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
@@ -266,6 +267,7 @@ namespace DotNetOpenAuth.OpenId {
/// an alternative plan.
/// </remarks>
/// <exception cref="ProtocolException">Thrown if the certificate chain is invalid or unverifiable.</exception>
+ [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "By design")]
private static void VerifyCertChain(List<X509Certificate2> certs) {
var chain = new X509Chain();
foreach (var cert in certs) {
@@ -418,6 +420,7 @@ namespace DotNetOpenAuth.OpenId {
/// <summary>
/// A description of a web server that hosts host-meta documents.
/// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Justification = "By design")]
public class HostMetaProxy {
/// <summary>
/// Initializes a new instance of the <see cref="HostMetaProxy"/> class.
diff --git a/src/DotNetOpenAuth/OpenId/IIdentifierDiscoveryService.cs b/src/DotNetOpenAuth/OpenId/IIdentifierDiscoveryService.cs
index f637b37..eb2bf98 100644
--- a/src/DotNetOpenAuth/OpenId/IIdentifierDiscoveryService.cs
+++ b/src/DotNetOpenAuth/OpenId/IIdentifierDiscoveryService.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
@@ -27,6 +28,7 @@ namespace DotNetOpenAuth.OpenId {
/// <returns>
/// A sequence of service endpoints yielded by discovery. Must not be null, but may be empty.
/// </returns>
+ [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "By design")]
[Pure]
IEnumerable<IdentifierDiscoveryResult> Discover(Identifier identifier, IDirectWebRequestHandler requestHandler, out bool abortDiscoveryChain);
}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/RequestBase.cs b/src/DotNetOpenAuth/OpenId/Messages/RequestBase.cs
index 6b89e92..8e4cb9d 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/RequestBase.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/RequestBase.cs
@@ -32,14 +32,14 @@ namespace DotNetOpenAuth.OpenId.Messages {
#pragma warning restore 0414
/// <summary>
- /// Backing store for the <see cref="Incoming"/> property.
+ /// Backing store for the <see cref="ExtraData"/> property.
/// </summary>
- private bool incoming;
+ private readonly Dictionary<string, string> extraData = new Dictionary<string, string>();
/// <summary>
- /// Backing store for the <see cref="ExtraData"/> property.
+ /// Backing store for the <see cref="Incoming"/> property.
/// </summary>
- private Dictionary<string, string> extraData = new Dictionary<string, string>();
+ private bool incoming;
/// <summary>
/// Initializes a new instance of the <see cref="RequestBase"/> class.
diff --git a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
index 611101d..10c69a3 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/OpenIdProvider.cs
@@ -25,6 +25,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// <summary>
/// Offers services for a web page that is acting as an OpenID identity server.
/// </summary>
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "By design")]
[ContractVerification(true)]
public sealed class OpenIdProvider : IDisposable {
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
index 6e141ad..b6a1b76 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/PositiveAuthenticationResponse.cs
@@ -38,7 +38,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.VerifyDiscoveryMatchesAssertion(relyingParty);
- Logger.OpenId.InfoFormat("Received identity assertion for {0} via {1}.", this.ClaimedIdentifier, this.Provider.Uri);
+ Logger.OpenId.InfoFormat("Received identity assertion for {0} via {1}.", this.Response.ClaimedIdentifier, this.Provider.Uri);
}
#region IAuthenticationResponse Properties
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/StandardRelyingPartyApplicationStore.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/StandardRelyingPartyApplicationStore.cs
index 8499178..f0a1574 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/StandardRelyingPartyApplicationStore.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/StandardRelyingPartyApplicationStore.cs
@@ -106,7 +106,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="context">The context, or namespace, within which the <paramref name="nonce"/> must be unique.</param>
/// <param name="nonce">A series of random characters.</param>
- /// <param name="timestamp">The timestamp that together with the nonce string make it unique.
+ /// <param name="timestampUtc">The timestamp that together with the nonce string make it unique.
/// The timestamp may also be used by the data store to clear out old nonces.</param>
/// <returns>
/// True if the nonce+timestamp (combination) was not previously in the database.
@@ -119,8 +119,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// is retrieved or set using the
/// <see cref="StandardExpirationBindingElement.MaximumMessageAge"/> property.
/// </remarks>
- public bool StoreNonce(string context, string nonce, DateTime timestamp) {
- return this.nonceStore.StoreNonce(context, nonce, timestamp);
+ public bool StoreNonce(string context, string nonce, DateTime timestampUtc) {
+ return this.nonceStore.StoreNonce(context, nonce, timestampUtc);
}
#endregion
diff --git a/src/DotNetOpenAuth/OpenId/XriDiscoveryProxyService.cs b/src/DotNetOpenAuth/OpenId/XriDiscoveryProxyService.cs
index e338542..b1a3430 100644
--- a/src/DotNetOpenAuth/OpenId/XriDiscoveryProxyService.cs
+++ b/src/DotNetOpenAuth/OpenId/XriDiscoveryProxyService.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OpenId {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
@@ -21,6 +22,7 @@ namespace DotNetOpenAuth.OpenId {
/// <summary>
/// The discovery service for XRI identifiers that uses an XRI proxy resolver for discovery.
/// </summary>
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Xri", Justification = "Acronym")]
public class XriDiscoveryProxyService : IIdentifierDiscoveryService {
/// <summary>
/// The magic URL that will provide us an XRDS document for a given XRI identifier.
diff --git a/src/DotNetOpenAuth/OpenId/XriIdentifier.cs b/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
index 6af41fa..729f603 100644
--- a/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/XriIdentifier.cs
@@ -94,7 +94,9 @@ namespace DotNetOpenAuth.OpenId {
public override bool Equals(object obj) {
XriIdentifier other = obj as XriIdentifier;
if (obj != null && other == null && Identifier.EqualityOnStrings) { // test hook to enable MockIdentifier comparison
- other = Identifier.Parse(obj.ToString()) as XriIdentifier;
+ string objString = obj.ToString();
+ ErrorUtilities.VerifyInternal(!string.IsNullOrEmpty(objString), "Identifier.ToString() returned a null or empty string.");
+ other = Identifier.Parse(objString) as XriIdentifier;
}
if (other == null) {
return false;
diff --git a/src/DotNetOpenAuth/Reporting.cs b/src/DotNetOpenAuth/Reporting.cs
index 4e4bbf5..2235986 100644
--- a/src/DotNetOpenAuth/Reporting.cs
+++ b/src/DotNetOpenAuth/Reporting.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth {
using System;
using System.Collections.Generic;
using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
@@ -88,6 +89,8 @@ namespace DotNetOpenAuth {
/// <summary>
/// Initializes static members of the <see cref="Reporting"/> class.
/// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline", Justification = "We do more than field initialization here.")]
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Reporting MUST NOT cause unhandled exceptions.")]
static Reporting() {
Enabled = DotNetOpenAuthSection.Configuration.Reporting.Enabled;
if (Enabled) {
@@ -446,6 +449,7 @@ namespace DotNetOpenAuth {
/// <summary>
/// Sends the stats report asynchronously, and careful to not throw any unhandled exceptions.
/// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Unhandled exceptions MUST NOT be thrown from here.")]
private static void SendStatsAsync() {
// Do it on a background thread since it could take a while and we
// don't want to slow down this request we're borrowing.
@@ -635,6 +639,7 @@ namespace DotNetOpenAuth {
/// </summary>
public void Dispose() {
this.Dispose(true);
+ GC.SuppressFinalize(this);
}
#endregion
@@ -775,6 +780,7 @@ namespace DotNetOpenAuth {
/// </summary>
public void Dispose() {
this.Dispose(true);
+ GC.SuppressFinalize(this);
}
#endregion
diff --git a/src/DotNetOpenAuth/Yadis/Yadis.cs b/src/DotNetOpenAuth/Yadis/Yadis.cs
index 589a155..f1c8be3 100644
--- a/src/DotNetOpenAuth/Yadis/Yadis.cs
+++ b/src/DotNetOpenAuth/Yadis/Yadis.cs
@@ -138,6 +138,8 @@ namespace DotNetOpenAuth.Yadis {
internal static IncomingWebResponse Request(IDirectWebRequestHandler requestHandler, Uri uri, bool requireSsl, params string[] acceptTypes) {
Contract.Requires<ArgumentNullException>(requestHandler != null);
Contract.Requires<ArgumentNullException>(uri != null);
+ Contract.Ensures(Contract.Result<IncomingWebResponse>() != null);
+ Contract.Ensures(Contract.Result<IncomingWebResponse>().ResponseStream != null);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.CachePolicy = IdentifierDiscoveryCachePolicy;
diff --git a/src/version.txt b/src/version.txt
index 1809198..1545d96 100644
--- a/src/version.txt
+++ b/src/version.txt
@@ -1 +1 @@
-3.4.0
+3.5.0