summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/nunit.framework.dllbin131072 -> 135168 bytes
-rw-r--r--nuget/content/web.config.transform8
-rw-r--r--projecttemplates/MvcRelyingParty/Web.config6
-rw-r--r--projecttemplates/RelyingPartyLogic/NonceDbStore.cs2
-rw-r--r--projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj4
-rw-r--r--projecttemplates/WebFormsRelyingParty/Web.config6
-rw-r--r--samples/DotNetOpenAuth.ApplicationBlock/CustomExtensions/UIRequestAtRelyingPartyFactory.cs47
-rw-r--r--samples/DotNetOpenAuth.ApplicationBlock/DotNetOpenAuth.ApplicationBlock.csproj1
-rw-r--r--samples/DotNetOpenAuth.ApplicationBlock/GoogleConsumer.cs5
-rw-r--r--samples/DotNetOpenAuth.ApplicationBlock/Util.cs2
-rw-r--r--samples/OAuthConsumerWpf/OAuthConsumerWpf.csproj4
-rw-r--r--samples/OAuthServiceProvider/Code/Global.cs9
-rw-r--r--samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj18
-rw-r--r--samples/OpenIdProviderMvc/OpenIdProviderMvc.csproj4
-rw-r--r--samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj4
-rw-r--r--samples/OpenIdRelyingPartyMvc/Web.config7
-rw-r--r--samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx16
-rw-r--r--samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx.cs46
-rw-r--r--samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx.designer.cs42
-rw-r--r--samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj8
-rw-r--r--samples/OpenIdRelyingPartyWebForms/Web.config7
-rw-r--r--samples/OpenIdRelyingPartyWebFormsVB/Web.config7
-rw-r--r--samples/OpenIdWebRingSsoProvider/OpenIdWebRingSsoProvider.csproj4
-rw-r--r--samples/OpenIdWebRingSsoRelyingParty/Web.config7
-rw-r--r--samples/tools.proj1
-rw-r--r--src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj6
-rw-r--r--src/DotNetOpenAuth.Test/Logging.config17
-rw-r--r--src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs20
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs14
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs53
-rw-r--r--src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs6
-rw-r--r--src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs83
-rw-r--r--src/DotNetOpenAuth.Test/Performance/CodeTimers.cs401
-rw-r--r--src/DotNetOpenAuth.Test/Performance/HighPerformance.cs178
-rw-r--r--src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs56
-rw-r--r--src/DotNetOpenAuth.Test/TestBase.cs40
-rw-r--r--src/DotNetOpenAuth.sln1
-rw-r--r--src/DotNetOpenAuth/ComponentModel/ConverterBase.cs1
-rw-r--r--src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd56
-rw-r--r--src/DotNetOpenAuth/Configuration/MessagingElement.cs28
-rw-r--r--src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs20
-rw-r--r--src/DotNetOpenAuth/Configuration/TrustedProviderConfigurationCollection.cs74
-rw-r--r--src/DotNetOpenAuth/Configuration/TrustedProviderEndpointConfigurationElement.cs35
-rw-r--r--src/DotNetOpenAuth/DotNetOpenAuth.csproj13
-rw-r--r--src/DotNetOpenAuth/GlobalSuppressions.cs109
-rw-r--r--src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs1
-rw-r--r--src/DotNetOpenAuth/InfoCard/Token/Token.cs27
-rw-r--r--src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs25
-rw-r--r--src/DotNetOpenAuth/Messaging/Channel.cs34
-rw-r--r--src/DotNetOpenAuth/Messaging/IMessageOriginalPayload.cs40
-rw-r--r--src/DotNetOpenAuth/Messaging/MessageSerializer.cs6
-rw-r--r--src/DotNetOpenAuth/Messaging/MessagingUtilities.cs11
-rw-r--r--src/DotNetOpenAuth/Messaging/MultipartPostPart.cs43
-rw-r--r--src/DotNetOpenAuth/Messaging/NetworkDirectWebResponse.cs2
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs1
-rw-r--r--src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs3
-rw-r--r--src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset1
-rw-r--r--src/DotNetOpenAuth/Mvc/OpenIdHelper.cs268
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/HmacSha1SigningBindingElement.cs9
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/ITamperResistantOAuthMessage.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs9
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs9
-rw-r--r--src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs19
-rw-r--r--src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/Protocol.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/ServiceProvider.cs2
-rw-r--r--src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs1
-rw-r--r--src/DotNetOpenAuth/OpenId/ChannelElements/KeyValueFormEncoding.cs33
-rw-r--r--src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs11
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs14
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs36
-rw-r--r--src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs36
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs62
-rw-r--r--src/DotNetOpenAuth/OpenId/OpenIdStrings.resx22
-rw-r--r--src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs6
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs5
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs15
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs1
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs261
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs62
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs3
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs16
-rw-r--r--src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs2
-rw-r--r--src/DotNetOpenAuth/OpenId/UriIdentifier.cs2
-rw-r--r--src/DotNetOpenAuth/Xrds/XrdsDocument.cs2
-rw-r--r--src/DotNetOpenAuth/XrdsPublisher.cs2
-rw-r--r--src/version.txt2
-rw-r--r--tools/ILMerge/ILMerge License.rtf104
-rw-r--r--tools/ILMerge/ILMerge.docbin0 -> 91136 bytes
-rw-r--r--tools/ILMerge/ILMerge.exebin0 -> 861184 bytes
-rw-r--r--tools/drop.proj1
-rw-r--r--vsi/vsi.proj2
-rw-r--r--vsix/vsix.proj8
96 files changed, 2139 insertions, 568 deletions
diff --git a/lib/nunit.framework.dll b/lib/nunit.framework.dll
index 88f3fa3..875e098 100644
--- a/lib/nunit.framework.dll
+++ b/lib/nunit.framework.dll
Binary files differ
diff --git a/nuget/content/web.config.transform b/nuget/content/web.config.transform
index 07e22d9..1958981 100644
--- a/nuget/content/web.config.transform
+++ b/nuget/content/web.config.transform
@@ -39,9 +39,15 @@
<dotNetOpenAuth>
<!-- This is an optional configuration section where aspects of dotnetopenauth can be customized. -->
<!-- For a complete set of configuration options see http://www.dotnetopenauth.net/developers/code-snippets/configuration-options/ -->
+ <!-- You may also refer to README.Bin.html for instructions on enabling Intellisense for this section. -->
<openid>
<relyingParty>
- <security requireSsl="false" />
+ <security requireSsl="false">
+ <!-- Uncomment the trustedProviders tag if your relying party should only accept positive assertions from a closed set of OpenID Providers. -->
+ <!--<trustedProviders rejectAssertionsFromUntrustedProviders="true">
+ <add endpoint="https://www.google.com/accounts/o8/ud" />
+ </trustedProviders>-->
+ </security>
<behaviors>
<!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible
with OPs that use Attribute Exchange (in various formats). -->
diff --git a/projecttemplates/MvcRelyingParty/Web.config b/projecttemplates/MvcRelyingParty/Web.config
index 7a867bb..fc14598 100644
--- a/projecttemplates/MvcRelyingParty/Web.config
+++ b/projecttemplates/MvcRelyingParty/Web.config
@@ -51,6 +51,12 @@
</messaging>
<openid>
<relyingParty>
+ <security requireSsl="false">
+ <!-- Uncomment the trustedProviders tag if your relying party should only accept positive assertions from a closed set of OpenID Providers. -->
+ <!--<trustedProviders rejectAssertionsFromUntrustedProviders="true">
+ <add endpoint="https://www.google.com/accounts/o8/ud" />
+ </trustedProviders>-->
+ </security>
<behaviors>
<!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible
with OPs that use Attribute Exchange (in various formats). -->
diff --git a/projecttemplates/RelyingPartyLogic/NonceDbStore.cs b/projecttemplates/RelyingPartyLogic/NonceDbStore.cs
index 812a4d5..951bf0f 100644
--- a/projecttemplates/RelyingPartyLogic/NonceDbStore.cs
+++ b/projecttemplates/RelyingPartyLogic/NonceDbStore.cs
@@ -101,7 +101,7 @@ namespace RelyingPartyLogic {
/// </summary>
protected class TransactedDatabaseEntities : DatabaseEntities {
/// <summary>
- /// Initializes a new instance of the <see cref="NonceDbStore.TransactedDatabaseEntities"/> class.
+ /// Initializes a new instance of the <see cref="TransactedDatabaseEntities"/> class.
/// </summary>
/// <param name="isolationLevel">The isolation level.</param>
public TransactedDatabaseEntities(IsolationLevel isolationLevel) {
diff --git a/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj b/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj
index c371d5a..180e6cb 100644
--- a/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj
+++ b/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj
@@ -101,7 +101,7 @@
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
<Reference Include="System.Web.Mobile" />
- <Reference Include="System.Web.ApplicationServices">
+ <Reference Include="System.Web.ApplicationServices" Condition=" '$(TargetFrameworkVersion)' != 'v3.5' ">
<RequiredTargetFramework>v4.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
@@ -181,4 +181,4 @@
</Target>
-->
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " />
-</Project> \ No newline at end of file
+</Project>
diff --git a/projecttemplates/WebFormsRelyingParty/Web.config b/projecttemplates/WebFormsRelyingParty/Web.config
index eabe925..cd26e26 100644
--- a/projecttemplates/WebFormsRelyingParty/Web.config
+++ b/projecttemplates/WebFormsRelyingParty/Web.config
@@ -54,6 +54,12 @@
</messaging>
<openid>
<relyingParty>
+ <security requireSsl="false">
+ <!-- Uncomment the trustedProviders tag if your relying party should only accept positive assertions from a closed set of OpenID Providers. -->
+ <!--<trustedProviders rejectAssertionsFromUntrustedProviders="true">
+ <add endpoint="https://www.google.com/accounts/o8/ud" />
+ </trustedProviders>-->
+ </security>
<behaviors>
<!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible
with OPs that use Attribute Exchange (in various formats). -->
diff --git a/samples/DotNetOpenAuth.ApplicationBlock/CustomExtensions/UIRequestAtRelyingPartyFactory.cs b/samples/DotNetOpenAuth.ApplicationBlock/CustomExtensions/UIRequestAtRelyingPartyFactory.cs
new file mode 100644
index 0000000..e8adfe3
--- /dev/null
+++ b/samples/DotNetOpenAuth.ApplicationBlock/CustomExtensions/UIRequestAtRelyingPartyFactory.cs
@@ -0,0 +1,47 @@
+//-----------------------------------------------------------------------
+// <copyright file="UIRequestAtRelyingPartyFactory.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.ApplicationBlock.CustomExtensions {
+ using System.Collections.Generic;
+ using DotNetOpenAuth.Messaging;
+ using DotNetOpenAuth.OpenId.ChannelElements;
+ using DotNetOpenAuth.OpenId.Extensions.UI;
+
+ /// <summary>
+ /// An extension factory that allows the <see cref="UIRequest"/> extension to be received by the relying party.
+ /// </summary>
+ /// <remarks>
+ /// Typically UIRequest is only received by the Provider. But Google mirrors back this data to the relying party
+ /// if our web user is already logged into Google.
+ /// See the OpenIdRelyingPartyWebForms sample's DetectGoogleSession.aspx page for usage of this factory.
+ /// </remarks>
+ public class UIRequestAtRelyingPartyFactory : IOpenIdExtensionFactory {
+ /// <summary>
+ /// The Type URI for the UI extension.
+ /// </summary>
+ private const string UITypeUri = "http://specs.openid.net/extensions/ui/1.0";
+
+ /// <summary>
+ /// Allows UIRequest extensions to be received by the relying party. Useful when Google mirrors back the request
+ /// to indicate that a user is logged in.
+ /// </summary>
+ /// <param name="typeUri">The type URI of the extension.</param>
+ /// <param name="data">The parameters associated specifically with this extension.</param>
+ /// <param name="baseMessage">The OpenID message carrying this extension.</param>
+ /// <param name="isProviderRole">A value indicating whether this extension is being received at the OpenID Provider.</param>
+ /// <returns>
+ /// An instance of <see cref="IOpenIdMessageExtension"/> if the factory recognizes
+ /// the extension described in the input parameters; <c>null</c> otherwise.
+ /// </returns>
+ public DotNetOpenAuth.OpenId.Messages.IOpenIdMessageExtension Create(string typeUri, IDictionary<string, string> data, IProtocolMessageWithExtensions baseMessage, bool isProviderRole) {
+ if (typeUri == UITypeUri && !isProviderRole) {
+ return new UIRequest();
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/samples/DotNetOpenAuth.ApplicationBlock/DotNetOpenAuth.ApplicationBlock.csproj b/samples/DotNetOpenAuth.ApplicationBlock/DotNetOpenAuth.ApplicationBlock.csproj
index adb1998..5a3e532 100644
--- a/samples/DotNetOpenAuth.ApplicationBlock/DotNetOpenAuth.ApplicationBlock.csproj
+++ b/samples/DotNetOpenAuth.ApplicationBlock/DotNetOpenAuth.ApplicationBlock.csproj
@@ -87,6 +87,7 @@
<Compile Include="CustomExtensions\Acme.cs" />
<Compile Include="CustomExtensions\AcmeRequest.cs" />
<Compile Include="CustomExtensions\AcmeResponse.cs" />
+ <Compile Include="CustomExtensions\UIRequestAtRelyingPartyFactory.cs" />
<Compile Include="GoogleConsumer.cs" />
<Compile Include="InMemoryTokenManager.cs">
<SubType>Code</SubType>
diff --git a/samples/DotNetOpenAuth.ApplicationBlock/GoogleConsumer.cs b/samples/DotNetOpenAuth.ApplicationBlock/GoogleConsumer.cs
index 558d4bc..474a569 100644
--- a/samples/DotNetOpenAuth.ApplicationBlock/GoogleConsumer.cs
+++ b/samples/DotNetOpenAuth.ApplicationBlock/GoogleConsumer.cs
@@ -222,6 +222,11 @@ namespace DotNetOpenAuth.ApplicationBlock {
{ "max-results", maxResults.ToString(CultureInfo.InvariantCulture) },
};
var request = consumer.PrepareAuthorizedRequest(GetContactsEndpoint, accessToken, extraData);
+
+ // Enable gzip compression. Google only compresses the response for recognized user agent headers. - Mike Lim
+ request.AutomaticDecompression = DecompressionMethods.GZip;
+ request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16";
+
var response = consumer.Channel.WebRequestHandler.GetResponse(request);
string body = response.GetResponseReader().ReadToEnd();
XDocument result = XDocument.Parse(body);
diff --git a/samples/DotNetOpenAuth.ApplicationBlock/Util.cs b/samples/DotNetOpenAuth.ApplicationBlock/Util.cs
index 4b4113d..0bec372 100644
--- a/samples/DotNetOpenAuth.ApplicationBlock/Util.cs
+++ b/samples/DotNetOpenAuth.ApplicationBlock/Util.cs
@@ -124,7 +124,7 @@
private readonly Action<HttpWebRequest> action;
/// <summary>
- /// Initializes a new instance of the <see cref="Util.WrappingWebRequestHandler"/> class.
+ /// Initializes a new instance of the <see cref="WrappingWebRequestHandler"/> class.
/// </summary>
/// <param name="wrappedHandler">The HTTP handler to wrap.</param>
/// <param name="action">The action to perform on outgoing HTTP requests.</param>
diff --git a/samples/OAuthConsumerWpf/OAuthConsumerWpf.csproj b/samples/OAuthConsumerWpf/OAuthConsumerWpf.csproj
index 32f1093..8654ec1 100644
--- a/samples/OAuthConsumerWpf/OAuthConsumerWpf.csproj
+++ b/samples/OAuthConsumerWpf/OAuthConsumerWpf.csproj
@@ -107,7 +107,7 @@
<Reference Include="PresentationFramework">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
- <Reference Include="System.Xaml">
+ <Reference Include="System.Xaml" Condition=" '$(TargetFrameworkVersion)' != 'v3.5' ">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
@@ -227,4 +227,4 @@
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " />
-</Project> \ No newline at end of file
+</Project>
diff --git a/samples/OAuthServiceProvider/Code/Global.cs b/samples/OAuthServiceProvider/Code/Global.cs
index ceaeac8..60fed9f 100644
--- a/samples/OAuthServiceProvider/Code/Global.cs
+++ b/samples/OAuthServiceProvider/Code/Global.cs
@@ -117,6 +117,15 @@
private void Application_Error(object sender, EventArgs e) {
Logger.Error("An unhandled exception occurred in ASP.NET processing: " + Server.GetLastError(), Server.GetLastError());
+
+ // In the event of an unhandled exception, reverse any changes that were made to the database to avoid any partial database updates.
+ var dataContext = dataContextSimple;
+ if (dataContext != null) {
+ dataContext.Transaction.Rollback();
+ dataContext.Connection.Close();
+ dataContext.Dispose();
+ dataContextSimple = null;
+ }
}
private void Application_EndRequest(object sender, EventArgs e) {
diff --git a/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj b/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj
index dd077d0..beb332d 100644
--- a/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj
+++ b/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj
@@ -119,7 +119,7 @@
<Reference Include="PresentationFramework">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
- <Reference Include="System.Xaml">
+ <Reference Include="System.Xaml" Condition=" '$(TargetFrameworkVersion)' != 'v3.5' ">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
@@ -215,11 +215,19 @@
<!-- Don't sign the non-unified version of the assembly. -->
<SuppressTargetPathDelaySignedAssembly>true</SuppressTargetPathDelaySignedAssembly>
</PropertyGroup>
+ <!-- These items should never be visible. In the project source tree, they're invisible because of an ItemDefinitionGroup
+ in DotNetOpenAuth.props. But in the shipping samples that file is not included, so we must still set Visible=false explicitly.. -->
<ItemGroup>
- <SignDependsOn Include="BuildUnified" />
- <DelaySignedAssemblies Include="$(ILMergeProjectOutputAssembly)" />
+ <SignDependsOn Include="BuildUnified">
+ <Visible>false</Visible>
+ </SignDependsOn>
+ <DelaySignedAssemblies Include="$(ILMergeProjectOutputAssembly)">
+ <Visible>false</Visible>
+ </DelaySignedAssemblies>
<ILMergeProjectInputAssemblies Include="$(TargetPath);
- $(ProjectRoot)lib\Microsoft.Contracts.dll; "/>
+ $(ProjectRoot)lib\Microsoft.Contracts.dll; ">
+ <Visible>false</Visible>
+ </ILMergeProjectInputAssemblies>
</ItemGroup>
<Target Name="BuildUnified" DependsOnTargets="Build" Inputs="@(ILMergeProjectInputAssemblies)" Outputs="$(ILMergeProjectOutputAssembly)">
<MakeDir Directories="$(ILMergeOutputAssemblyDirectory)" />
@@ -227,4 +235,4 @@
</Target>
<Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " />
-</Project> \ No newline at end of file
+</Project>
diff --git a/samples/OpenIdProviderMvc/OpenIdProviderMvc.csproj b/samples/OpenIdProviderMvc/OpenIdProviderMvc.csproj
index 9dc060e..d609a29 100644
--- a/samples/OpenIdProviderMvc/OpenIdProviderMvc.csproj
+++ b/samples/OpenIdProviderMvc/OpenIdProviderMvc.csproj
@@ -50,7 +50,7 @@
<Reference Include="System.Web.Extensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
- <Reference Include="System.Web.ApplicationServices">
+ <Reference Include="System.Web.ApplicationServices" Condition=" '$(TargetFrameworkVersion)' != 'v3.5' ">
<RequiredTargetFramework>v4.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Web.Abstractions" />
@@ -153,4 +153,4 @@
</VisualStudio>
</ProjectExtensions>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " />
-</Project> \ No newline at end of file
+</Project>
diff --git a/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj b/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj
index 66e0f6a..861cdb7 100644
--- a/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj
+++ b/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj
@@ -68,7 +68,7 @@
<Reference Include="System.EnterpriseServices" />
<Reference Include="System.Web.Mobile" />
<Reference Include="System.Xml.Linq" />
- <Reference Include="System.Web.ApplicationServices">
+ <Reference Include="System.Web.ApplicationServices" Condition=" '$(TargetFrameworkVersion)' != 'v3.5' ">
<RequiredTargetFramework>v4.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
@@ -221,4 +221,4 @@
</VisualStudio>
</ProjectExtensions>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " />
-</Project> \ No newline at end of file
+</Project>
diff --git a/samples/OpenIdRelyingPartyMvc/Web.config b/samples/OpenIdRelyingPartyMvc/Web.config
index 8101fb2..9561a28 100644
--- a/samples/OpenIdRelyingPartyMvc/Web.config
+++ b/samples/OpenIdRelyingPartyMvc/Web.config
@@ -38,7 +38,12 @@
<dotNetOpenAuth>
<openid>
<relyingParty>
- <security requireSsl="false" />
+ <security requireSsl="false">
+ <!-- Uncomment the trustedProviders tag if your relying party should only accept positive assertions from a closed set of OpenID Providers. -->
+ <!--<trustedProviders rejectAssertionsFromUntrustedProviders="true">
+ <add endpoint="https://www.google.com/accounts/o8/ud" />
+ </trustedProviders>-->
+ </security>
<behaviors>
<!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible
with OPs that use Attribute Exchange (in various formats). -->
diff --git a/samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx b/samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx
new file mode 100644
index 0000000..403858f
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx
@@ -0,0 +1,16 @@
+<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DetectGoogleSession.aspx.cs"
+ Inherits="OpenIdRelyingPartyWebForms.DetectGoogleSession" ValidateRequest="false"
+ MasterPageFile="~/Site.Master" %>
+
+<%@ Register Assembly="DotNetOpenAuth" Namespace="DotNetOpenAuth.OpenId.RelyingParty"
+ TagPrefix="rp" %>
+<%@ Register Assembly="DotNetOpenAuth" Namespace="DotNetOpenAuth.OpenId.Extensions.SimpleRegistration"
+ TagPrefix="sreg" %>
+<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="Main">
+ <asp:Label Text="We've detected that you're logged into Google!" runat="server" Visible="false"
+ ID="YouAreLoggedInLabel" />
+ <asp:Label Text="We've detected that you're logged into Google because your Google account trusts this site!" runat="server" Visible="false"
+ ID="YouTrustUsLabel" />
+ <asp:Label Text="We've detected that you're NOT logged into Google!" runat="server" Visible="false"
+ ID="YouAreNotLoggedInLabel" />
+</asp:Content>
diff --git a/samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx.cs b/samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx.cs
new file mode 100644
index 0000000..98fe745
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx.cs
@@ -0,0 +1,46 @@
+namespace OpenIdRelyingPartyWebForms {
+ using System;
+ using DotNetOpenAuth.ApplicationBlock.CustomExtensions;
+ using DotNetOpenAuth.OpenId.Extensions.UI;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+
+ public partial class DetectGoogleSession : System.Web.UI.Page {
+ private const string GoogleOPIdentifier = "https://www.google.com/accounts/o8/id";
+
+ private const string UIModeDetectSession = "x-has-session";
+
+ protected void Page_Load(object sender, EventArgs e) {
+ using (var openid = new OpenIdRelyingParty()) {
+ // In order to receive the UIRequest as a response, we must register a custom extension factory.
+ openid.ExtensionFactories.Add(new UIRequestAtRelyingPartyFactory());
+
+ var response = openid.GetResponse();
+ if (response == null) {
+ // Submit an OpenID request which Google must reply to immediately.
+ // If the user hasn't established a trust relationship with this site yet,
+ // Google will not give us the user identity, but they will tell us whether the user
+ // at least has an active login session with them so we know whether to promote the
+ // "Log in with Google" button.
+ IAuthenticationRequest request = openid.CreateRequest("https://www.google.com/accounts/o8/id");
+ request.AddExtension(new UIRequest { Mode = UIModeDetectSession });
+ request.Mode = AuthenticationRequestMode.Immediate;
+ request.RedirectToProvider();
+ } else {
+ if (response.Status == AuthenticationStatus.Authenticated) {
+ this.YouTrustUsLabel.Visible = true;
+ } else if (response.Status == AuthenticationStatus.SetupRequired) {
+ // Google refused to authenticate the user without user interaction.
+ // This is either because Google doesn't know who the user is yet,
+ // or because the user hasn't indicated to Google to trust this site.
+ // Google uniquely offers the RP a tip as to which of the above situations is true.
+ // Figure out which it is. In a real app, you might use this value to promote a
+ // Google login button on your site if you detect that a Google session exists.
+ var ext = response.GetUntrustedExtension<UIRequest>();
+ this.YouAreLoggedInLabel.Visible = ext != null && ext.Mode == UIModeDetectSession;
+ this.YouAreNotLoggedInLabel.Visible = !this.YouAreLoggedInLabel.Visible;
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx.designer.cs b/samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx.designer.cs
new file mode 100644
index 0000000..576c646
--- /dev/null
+++ b/samples/OpenIdRelyingPartyWebForms/DetectGoogleSession.aspx.designer.cs
@@ -0,0 +1,42 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace OpenIdRelyingPartyWebForms {
+
+
+ public partial class DetectGoogleSession {
+
+ /// <summary>
+ /// YouAreLoggedInLabel control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.Label YouAreLoggedInLabel;
+
+ /// <summary>
+ /// YouTrustUsLabel control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.Label YouTrustUsLabel;
+
+ /// <summary>
+ /// YouAreNotLoggedInLabel control.
+ /// </summary>
+ /// <remarks>
+ /// Auto-generated field.
+ /// To modify move field declaration from designer file to code-behind file.
+ /// </remarks>
+ protected global::System.Web.UI.WebControls.Label YouAreNotLoggedInLabel;
+ }
+}
diff --git a/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj b/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj
index 69c3e91..cbcd758 100644
--- a/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj
+++ b/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj
@@ -74,6 +74,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Default.aspx" />
+ <Content Include="DetectGoogleSession.aspx" />
<Content Include="Global.asax" />
<Content Include="images\openid_login.png" />
<Content Include="login.aspx" />
@@ -110,6 +111,13 @@
</Compile>
<Compile Include="Code\State.cs" />
<Compile Include="Code\TracePageAppender.cs" />
+ <Compile Include="DetectGoogleSession.aspx.cs">
+ <DependentUpon>DetectGoogleSession.aspx</DependentUpon>
+ <SubType>ASPXCodeBehind</SubType>
+ </Compile>
+ <Compile Include="DetectGoogleSession.aspx.designer.cs">
+ <DependentUpon>DetectGoogleSession.aspx</DependentUpon>
+ </Compile>
<Compile Include="loginGoogleApps.aspx.cs">
<DependentUpon>loginGoogleApps.aspx</DependentUpon>
<SubType>ASPXCodeBehind</SubType>
diff --git a/samples/OpenIdRelyingPartyWebForms/Web.config b/samples/OpenIdRelyingPartyWebForms/Web.config
index 5d3a33b..1f1842b 100644
--- a/samples/OpenIdRelyingPartyWebForms/Web.config
+++ b/samples/OpenIdRelyingPartyWebForms/Web.config
@@ -28,7 +28,12 @@
<dotNetOpenAuth>
<openid>
<relyingParty>
- <security requireSsl="false" />
+ <security requireSsl="false">
+ <!-- Uncomment the trustedProviders tag if your relying party should only accept positive assertions from a closed set of OpenID Providers. -->
+ <!--<trustedProviders rejectAssertionsFromUntrustedProviders="true">
+ <add endpoint="https://www.google.com/accounts/o8/ud" />
+ </trustedProviders>-->
+ </security>
<behaviors>
<!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible
with OPs that use Attribute Exchange (in various formats). -->
diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Web.config b/samples/OpenIdRelyingPartyWebFormsVB/Web.config
index 36174a5..51b3d26 100644
--- a/samples/OpenIdRelyingPartyWebFormsVB/Web.config
+++ b/samples/OpenIdRelyingPartyWebFormsVB/Web.config
@@ -28,7 +28,12 @@
<dotNetOpenAuth>
<openid>
<relyingParty>
- <security requireSsl="false" />
+ <security requireSsl="false">
+ <!-- Uncomment the trustedProviders tag if your relying party should only accept positive assertions from a closed set of OpenID Providers. -->
+ <!--<trustedProviders rejectAssertionsFromUntrustedProviders="true">
+ <add endpoint="https://www.google.com/accounts/o8/ud" />
+ </trustedProviders>-->
+ </security>
<behaviors>
<!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible
with OPs that use Attribute Exchange (in various formats). -->
diff --git a/samples/OpenIdWebRingSsoProvider/OpenIdWebRingSsoProvider.csproj b/samples/OpenIdWebRingSsoProvider/OpenIdWebRingSsoProvider.csproj
index 70ef5ac..3120f1e 100644
--- a/samples/OpenIdWebRingSsoProvider/OpenIdWebRingSsoProvider.csproj
+++ b/samples/OpenIdWebRingSsoProvider/OpenIdWebRingSsoProvider.csproj
@@ -55,7 +55,7 @@
<Reference Include="System.EnterpriseServices" />
<Reference Include="System.Web.Mobile" />
<Reference Include="System.Xml.Linq" />
- <Reference Include="System.Web.ApplicationServices">
+ <Reference Include="System.Web.ApplicationServices" Condition=" '$(TargetFrameworkVersion)' != 'v3.5' ">
<RequiredTargetFramework>v4.0</RequiredTargetFramework>
</Reference>
</ItemGroup>
@@ -138,4 +138,4 @@
</VisualStudio>
</ProjectExtensions>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " />
-</Project> \ No newline at end of file
+</Project>
diff --git a/samples/OpenIdWebRingSsoRelyingParty/Web.config b/samples/OpenIdWebRingSsoRelyingParty/Web.config
index 3f50723..98e5c3f 100644
--- a/samples/OpenIdWebRingSsoRelyingParty/Web.config
+++ b/samples/OpenIdWebRingSsoRelyingParty/Web.config
@@ -40,7 +40,12 @@
<dotNetOpenAuth>
<openid>
<relyingParty>
- <security requireSsl="false" />
+ <security requireSsl="false">
+ <!-- Uncomment the trustedProviders tag if your relying party should only accept positive assertions from a closed set of OpenID Providers. -->
+ <!--<trustedProviders rejectAssertionsFromUntrustedProviders="true">
+ <add endpoint="https://www.google.com/accounts/o8/ud" />
+ </trustedProviders>-->
+ </security>
<behaviors>
<!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible
with OPs that use Attribute Exchange (in various formats). -->
diff --git a/samples/tools.proj b/samples/tools.proj
index 9a8b70c..d72e364 100644
--- a/samples/tools.proj
+++ b/samples/tools.proj
@@ -27,6 +27,7 @@
$(OutputPath)$(ProductName).dll;
$(OutputPath)$(SignedSubPath)$(ProductName).dll;
$(ProjectRoot)lib\Microsoft.Contracts.dll;
+ $(OutputPath)System.Web.Mvc.dll;
" />
<!-- add the PDBs -->
diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
index 5e80f2c..2067ede 100644
--- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
+++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj
@@ -74,6 +74,7 @@
<CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
<CodeContractsExtraRewriteOptions />
<CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -111,6 +112,7 @@
<CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
<CodeContractsExtraRewriteOptions />
<CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -150,6 +152,7 @@
<CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
<CodeContractsExtraRewriteOptions />
<CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net" />
@@ -301,6 +304,9 @@
<Compile Include="OpenId\RelyingParty\IdentifierDiscoveryResultTests.cs" />
<Compile Include="OpenId\UriIdentifierTests.cs" />
<Compile Include="OpenId\XriIdentifierTests.cs" />
+ <Compile Include="Performance\CodeTimers.cs" />
+ <Compile Include="Performance\HighPerformance.cs" />
+ <Compile Include="Performance\PerformanceTestUtilities.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Messaging\ResponseTests.cs" />
<Compile Include="OAuth\AppendixScenarios.cs" />
diff --git a/src/DotNetOpenAuth.Test/Logging.config b/src/DotNetOpenAuth.Test/Logging.config
index 87da027..a32badd 100644
--- a/src/DotNetOpenAuth.Test/Logging.config
+++ b/src/DotNetOpenAuth.Test/Logging.config
@@ -17,6 +17,23 @@
<conversionPattern value="[%thread] %-5level - %message%newline" />
</layout>
</appender>
+ <appender name="StdOutAppender" type="log4net.Appender.ConsoleAppender">
+ <immediateFlush value="true" />
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
+ </layout>
+ </appender>
+ <appender name="StdErrAppender" type="log4net.Appender.ConsoleAppender">
+ <immediateFlush value="true" />
+ <target value="Console.Error" />
+ <filter type="log4net.Filter.LevelRangeFilter">
+ <param name="LevelMin" value="ERROR"/>
+ <param name="LevelMax" value="FATAL"/>
+ </filter>
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
+ </layout>
+ </appender>
<!-- Setup the root category, add the appenders and set the default level -->
<root>
<level value="Info" />
diff --git a/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs
index e862ca6..74e23bd 100644
--- a/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs
+++ b/src/DotNetOpenAuth.Test/Mocks/CoordinatingOAuthChannel.cs
@@ -24,29 +24,29 @@ namespace DotNetOpenAuth.Test.Mocks {
/// <summary>
/// Initializes a new instance of the <see cref="CoordinatingOAuthChannel"/> class for Consumers.
/// </summary>
- /// <param name="signingBindingElement">
- /// The signing element for the Consumer to use. Null for the Service Provider.
- /// </param>
+ /// <param name="signingBindingElement">The signing element for the Consumer to use. Null for the Service Provider.</param>
/// <param name="tokenManager">The token manager to use.</param>
- internal CoordinatingOAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, IConsumerTokenManager tokenManager)
+ /// <param name="securitySettings">The security settings.</param>
+ internal CoordinatingOAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, IConsumerTokenManager tokenManager, DotNetOpenAuth.OAuth.ConsumerSecuritySettings securitySettings)
: base(
signingBindingElement,
new NonceMemoryStore(StandardExpirationBindingElement.MaximumMessageAge),
- tokenManager) {
+ tokenManager,
+ securitySettings) {
}
/// <summary>
/// Initializes a new instance of the <see cref="CoordinatingOAuthChannel"/> class for Consumers.
/// </summary>
- /// <param name="signingBindingElement">
- /// The signing element for the Consumer to use. Null for the Service Provider.
- /// </param>
+ /// <param name="signingBindingElement">The signing element for the Consumer to use. Null for the Service Provider.</param>
/// <param name="tokenManager">The token manager to use.</param>
- internal CoordinatingOAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, IServiceProviderTokenManager tokenManager)
+ /// <param name="securitySettings">The security settings.</param>
+ internal CoordinatingOAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, IServiceProviderTokenManager tokenManager, DotNetOpenAuth.OAuth.ServiceProviderSecuritySettings securitySettings)
: base(
signingBindingElement,
new NonceMemoryStore(StandardExpirationBindingElement.MaximumMessageAge),
- tokenManager) {
+ tokenManager,
+ securitySettings) {
}
/// <summary>
diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
index 479375a..34cc3a4 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/OAuthChannelTests.cs
@@ -27,6 +27,8 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
private TestWebRequestHandler webRequestHandler;
private SigningBindingElementBase signingElement;
private INonceStore nonceStore;
+ private DotNetOpenAuth.OAuth.ServiceProviderSecuritySettings serviceProviderSecuritySettings = DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration.OAuth.ServiceProvider.SecuritySettings.CreateSecuritySettings();
+ private DotNetOpenAuth.OAuth.ConsumerSecuritySettings consumerSecuritySettings = DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration.OAuth.Consumer.SecuritySettings.CreateSecuritySettings();
[SetUp]
public override void SetUp() {
@@ -35,33 +37,33 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
this.webRequestHandler = new TestWebRequestHandler();
this.signingElement = new RsaSha1SigningBindingElement(new InMemoryTokenManager());
this.nonceStore = new NonceMemoryStore(StandardExpirationBindingElement.MaximumMessageAge);
- this.channel = new OAuthChannel(this.signingElement, this.nonceStore, new InMemoryTokenManager(), new TestMessageFactory());
+ this.channel = new OAuthChannel(this.signingElement, this.nonceStore, new InMemoryTokenManager(), this.serviceProviderSecuritySettings, new TestMessageFactory());
this.channel.WebRequestHandler = this.webRequestHandler;
}
[TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullSigner() {
- new OAuthChannel(null, this.nonceStore, new InMemoryTokenManager(), new TestMessageFactory());
+ new OAuthChannel(null, this.nonceStore, new InMemoryTokenManager(), this.consumerSecuritySettings, new TestMessageFactory());
}
[TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullStore() {
- new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), null, new InMemoryTokenManager(), new TestMessageFactory());
+ new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), null, new InMemoryTokenManager(), this.consumerSecuritySettings, new TestMessageFactory());
}
[TestCase, ExpectedException(typeof(ArgumentNullException))]
public void CtorNullTokenManager() {
- new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, null, new TestMessageFactory());
+ new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, null, this.consumerSecuritySettings, new TestMessageFactory());
}
[TestCase]
public void CtorSimpleConsumer() {
- new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IConsumerTokenManager)new InMemoryTokenManager());
+ new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IConsumerTokenManager)new InMemoryTokenManager(), this.consumerSecuritySettings);
}
[TestCase]
public void CtorSimpleServiceProvider() {
- new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IServiceProviderTokenManager)new InMemoryTokenManager());
+ new OAuthChannel(new RsaSha1SigningBindingElement(new InMemoryTokenManager()), this.nonceStore, (IServiceProviderTokenManager)new InMemoryTokenManager(), this.serviceProviderSecuritySettings);
}
[TestCase]
diff --git a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs
index 2ef7e9a..83d5feb 100644
--- a/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/ChannelElements/SigningBindingElementBaseTests.cs
@@ -5,6 +5,8 @@
//-----------------------------------------------------------------------
namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OAuth;
@@ -52,6 +54,15 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
"GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_consumer_key%3Dnerdbank.org%26oauth_nonce%3Dfe4045a3f0efdd1e019fa8f8ae3f5c38%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1222665749%26oauth_version%3D1.0%26scope%3Dhttp%253A%252F%252Fwww.google.com%252Fm8%252Ffeeds%252F",
SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message)));
+ // Test for when oauth_version isn't explicitly included in the message by the consumer.
+ message = CreateTestRequestTokenMessageNoOAuthVersion(
+ this.MessageDescriptions,
+ new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthGetRequestToken?scope=http://www.google.com/m8/feeds/", HttpDeliveryMethods.GetRequest));
+ message.ExtraData.Remove("scope"); // remove it from ExtraData since we put it in the URL
+ Assert.AreEqual(
+ "GET&https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthGetRequestToken&oauth_consumer_key%3Dnerdbank.org%26oauth_nonce%3Dfe4045a3f0efdd1e019fa8f8ae3f5c38%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1222665749%26scope%3Dhttp%253A%252F%252Fwww.google.com%252Fm8%252Ffeeds%252F",
+ SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message)));
+
// This is a simulation of receiving the message, where the query string is still in the URL,
// but has been read into ExtraData, so parameters in the query string appear twice.
message = CreateTestRequestTokenMessage(
@@ -62,6 +73,42 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message)));
}
+ [TestCase]
+ public void BaseSignatureStringResourceRequests() {
+ var message = this.CreateResourceRequest(new MessageReceivingEndpoint("http://tom.test.wishpot.com/restapi/List/Search?List.LastName=ciccotosto", HttpDeliveryMethods.GetRequest));
+ message.ConsumerKey = "public";
+ message.AccessToken = "tokenpublic";
+
+ var signedMessage = (ITamperResistantOAuthMessage)message;
+ signedMessage.HttpMethod = "GET";
+ signedMessage.SignatureMethod = "HMAC-SHA1";
+
+ MessageDictionary dictionary = this.MessageDescriptions.GetAccessor(message);
+ dictionary["oauth_timestamp"] = "1302716502";
+ dictionary["oauth_nonce"] = "2U5YsZvL";
+
+ Assert.AreEqual(
+ "GET&http%3A%2F%2Ftom.test.wishpot.com%2Frestapi%2FList%2FSearch&List.LastName%3Dciccotosto%26oauth_consumer_key%3Dpublic%26oauth_nonce%3D2U5YsZvL%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1302716502%26oauth_token%3Dtokenpublic%26oauth_version%3D1.0",
+ SigningBindingElementBase.ConstructSignatureBaseString(message, this.MessageDescriptions.GetAccessor(message)));
+ }
+
+ internal static UnauthorizedTokenRequest CreateTestRequestTokenMessageNoOAuthVersion(MessageDescriptionCollection messageDescriptions, MessageReceivingEndpoint endpoint) {
+ endpoint = endpoint ?? new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthGetRequestToken", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest);
+ var parts = new Dictionary<string, string>();
+ parts["oauth_consumer_key"] = "nerdbank.org";
+ parts["oauth_timestamp"] = "1222665749";
+ parts["oauth_nonce"] = "fe4045a3f0efdd1e019fa8f8ae3f5c38";
+ parts["scope"] = "http://www.google.com/m8/feeds/";
+ parts["oauth_signature_method"] = "HMAC-SHA1";
+ parts["oauth_signature"] = "anything non-empty";
+
+ UnauthorizedTokenRequest message = new UnauthorizedTokenRequest(endpoint, Protocol.V10.Version);
+ MessageDictionary dictionary = messageDescriptions.GetAccessor(message);
+ MessageSerializer.Get(typeof(UnauthorizedTokenRequest)).Deserialize(parts, dictionary);
+
+ return message;
+ }
+
internal static UnauthorizedTokenRequest CreateTestRequestTokenMessage(MessageDescriptionCollection messageDescriptions, MessageReceivingEndpoint endpoint) {
endpoint = endpoint ?? new MessageReceivingEndpoint("https://www.google.com/accounts/OAuthGetRequestToken", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest);
UnauthorizedTokenRequest message = new UnauthorizedTokenRequest(endpoint, Protocol.V10.Version);
@@ -76,5 +123,11 @@ namespace DotNetOpenAuth.Test.OAuth.ChannelElements {
dictionary["scope"] = "http://www.google.com/m8/feeds/";
return message;
}
+
+ internal AccessProtectedResourceRequest CreateResourceRequest(MessageReceivingEndpoint endpoint) {
+ Contract.Requires(endpoint != null);
+ var message = new AccessProtectedResourceRequest(endpoint, Protocol.V10.Version);
+ return message;
+ }
}
}
diff --git a/src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs b/src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs
index 972dd2a..6bcc583 100644
--- a/src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs
+++ b/src/DotNetOpenAuth.Test/OAuth/OAuthCoordinator.cs
@@ -19,6 +19,8 @@ namespace DotNetOpenAuth.Test.OAuth {
internal class OAuthCoordinator : CoordinatorBase<WebConsumer, ServiceProvider> {
private ConsumerDescription consumerDescription;
private ServiceProviderDescription serviceDescription;
+ private DotNetOpenAuth.OAuth.ServiceProviderSecuritySettings serviceProviderSecuritySettings = DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration.OAuth.ServiceProvider.SecuritySettings.CreateSecuritySettings();
+ private DotNetOpenAuth.OAuth.ConsumerSecuritySettings consumerSecuritySettings = DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration.OAuth.Consumer.SecuritySettings.CreateSecuritySettings();
/// <summary>Initializes a new instance of the <see cref="OAuthCoordinator"/> class.</summary>
/// <param name="consumerDescription">The description of the consumer.</param>
@@ -50,8 +52,8 @@ namespace DotNetOpenAuth.Test.OAuth {
serviceTokenManager.AddConsumer(this.consumerDescription);
// Prepare channels that will pass messages directly back and forth.
- CoordinatingOAuthChannel consumerChannel = new CoordinatingOAuthChannel(consumerSigningElement, (IConsumerTokenManager)consumerTokenManager);
- CoordinatingOAuthChannel serviceProviderChannel = new CoordinatingOAuthChannel(spSigningElement, (IServiceProviderTokenManager)serviceTokenManager);
+ CoordinatingOAuthChannel consumerChannel = new CoordinatingOAuthChannel(consumerSigningElement, (IConsumerTokenManager)consumerTokenManager, this.consumerSecuritySettings);
+ CoordinatingOAuthChannel serviceProviderChannel = new CoordinatingOAuthChannel(spSigningElement, (IServiceProviderTokenManager)serviceTokenManager, this.serviceProviderSecuritySettings);
consumerChannel.RemoteChannel = serviceProviderChannel;
serviceProviderChannel.RemoteChannel = consumerChannel;
diff --git a/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs b/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs
index 7984b58..4530982 100644
--- a/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs
+++ b/src/DotNetOpenAuth.Test/OpenId/Provider/PerformanceTests.cs
@@ -18,6 +18,7 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
using DotNetOpenAuth.OpenId.ChannelElements;
using DotNetOpenAuth.OpenId.Messages;
using DotNetOpenAuth.OpenId.Provider;
+ using DotNetOpenAuth.Test.Performance;
using NUnit.Framework;
[TestFixture, Category("Performance")]
@@ -29,73 +30,50 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
[SetUp]
public override void SetUp() {
base.SetUp();
- SuspendLogging();
this.provider = CreateProvider();
}
- [TearDown]
- public override void Cleanup() {
- ResumeLogging();
- base.Cleanup();
- }
-
[TestCase]
public void AssociateDH() {
var associateRequest = this.CreateAssociateRequest(OPUri);
- Stopwatch timer = new Stopwatch();
- timer.Start();
- int iterations;
- for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++) {
- IRequest request = this.provider.GetRequest(associateRequest);
- var response = this.provider.PrepareResponse(request);
- Assert.IsInstanceOf<AssociateSuccessfulResponse>(response.OriginalMessage);
- }
- timer.Stop();
- double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
- TestUtilities.TestLogger.InfoFormat("Created {0} associations in {1}, or {2} per second.", iterations, timer.Elapsed, executionsPerSecond);
- Assert.IsTrue(executionsPerSecond >= 2, "Too slow ({0} >= 2 executions per second required.)", executionsPerSecond);
+ MeasurePerformance(
+ () => {
+ IRequest request = this.provider.GetRequest(associateRequest);
+ var response = this.provider.PrepareResponse(request);
+ Assert.IsInstanceOf<AssociateSuccessfulResponse>(response.OriginalMessage);
+ },
+ maximumAllowedUnitTime: 3.5e6f,
+ iterations: 1);
}
[TestCase]
public void AssociateClearText() {
var associateRequest = this.CreateAssociateRequest(OPUriSsl); // SSL will cause a plaintext association
- Stopwatch timer = new Stopwatch();
- timer.Start();
- int iterations;
- for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++) {
- IRequest request = this.provider.GetRequest(associateRequest);
- var response = this.provider.PrepareResponse(request);
- Assert.IsInstanceOf<AssociateSuccessfulResponse>(response.OriginalMessage);
- }
- timer.Stop();
- double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
- TestUtilities.TestLogger.InfoFormat("Created {0} associations in {1}, or {2} per second.", iterations, timer.Elapsed, executionsPerSecond);
- Assert.IsTrue(executionsPerSecond > 1000, "Too slow ({0} > 1000 executions per second required.)", executionsPerSecond);
+ MeasurePerformance(
+ () => {
+ IRequest request = this.provider.GetRequest(associateRequest);
+ var response = this.provider.PrepareResponse(request);
+ Assert.IsInstanceOf<AssociateSuccessfulResponse>(response.OriginalMessage);
+ },
+ maximumAllowedUnitTime: 1.5e4f,
+ iterations: 1000);
}
[TestCase]
public void CheckIdSharedHmacSha1Association() {
Protocol protocol = Protocol.Default;
string assocType = protocol.Args.SignatureAlgorithm.HMAC_SHA1;
- double executionsPerSecond = this.ParameterizedCheckIdTest(protocol, assocType);
- TestUtilities.TestLogger.InfoFormat("{0} executions per second.", executionsPerSecond);
- Assert.IsTrue(executionsPerSecond > 500, "Too slow ({0} > 500 executions per second required.)", executionsPerSecond);
+ this.ParameterizedCheckIdTest(protocol, assocType);
}
[TestCase]
public void CheckIdSharedHmacSha256Association() {
Protocol protocol = Protocol.Default;
string assocType = protocol.Args.SignatureAlgorithm.HMAC_SHA256;
- double executionsPerSecond = this.ParameterizedCheckIdTest(protocol, assocType);
- TestUtilities.TestLogger.InfoFormat("{0} executions per second.", executionsPerSecond);
- Assert.IsTrue(executionsPerSecond > 400, "Too slow ({0} > 400 executions per second required.)", executionsPerSecond);
+ this.ParameterizedCheckIdTest(protocol, assocType);
}
- private static double GetExecutionsPerSecond(int iterations, Stopwatch timer) {
- return (double)iterations / (timer.ElapsedMilliseconds / 1000);
- }
-
- private double ParameterizedCheckIdTest(Protocol protocol, string assocType) {
+ private void ParameterizedCheckIdTest(Protocol protocol, string assocType) {
Association assoc = HmacShaAssociation.Create(
protocol,
assocType,
@@ -103,19 +81,14 @@ namespace DotNetOpenAuth.Test.OpenId.Provider {
this.provider.SecuritySettings);
this.provider.AssociationStore.StoreAssociation(AssociationRelyingPartyType.Smart, assoc);
var checkidRequest = this.CreateCheckIdRequest(true);
- Stopwatch timer = new Stopwatch();
- timer.Start();
- int iterations;
- for (iterations = 0; timer.ElapsedMilliseconds < TestRunTime.TotalMilliseconds; iterations++) {
- var request = (IAuthenticationRequest)this.provider.GetRequest(checkidRequest);
- request.IsAuthenticated = true;
- var response = this.provider.PrepareResponse(request);
- Assert.IsInstanceOf<PositiveAssertionResponse>(response.OriginalMessage);
- }
- timer.Stop();
- double executionsPerSecond = GetExecutionsPerSecond(iterations, timer);
- TestUtilities.TestLogger.InfoFormat("Responded to {0} checkid messages in {1}; or {2} authentications per second.", iterations, timer.Elapsed, executionsPerSecond);
- return executionsPerSecond;
+ MeasurePerformance(
+ () => {
+ var request = (IAuthenticationRequest)this.provider.GetRequest(checkidRequest);
+ request.IsAuthenticated = true;
+ var response = this.provider.PrepareResponse(request);
+ Assert.IsInstanceOf<PositiveAssertionResponse>(response.OriginalMessage);
+ },
+ maximumAllowedUnitTime: 6.8e4f);
}
private HttpRequestInfo CreateAssociateRequest(Uri opEndpoint) {
diff --git a/src/DotNetOpenAuth.Test/Performance/CodeTimers.cs b/src/DotNetOpenAuth.Test/Performance/CodeTimers.cs
new file mode 100644
index 0000000..85fa83d
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Performance/CodeTimers.cs
@@ -0,0 +1,401 @@
+// <auto-generated/> // well, imported. But this gets StyleCop off our back
+//-----------------------------------------------------------------------
+// <copyright file="CodeTimers.cs" company="Microsoft Corporation">
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// </copyright>
+// <author>Vance Morrison</author>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Performance {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+
+ /// <summary>
+ /// Stats represents a list of samples (floating point values) This class can calculate the standard
+ /// statistics on this list (Mean, Median, StandardDeviation ...)
+ /// </summary>
+ internal class Stats : IEnumerable<float> {
+ private List<float> data;
+ private float minimum;
+ private float maximum;
+ private float median;
+ private float mean;
+ private float standardDeviation;
+ private bool statsComputed;
+
+ public Stats() { data = new List<float>(); }
+
+ public void Add(float dataItem) {
+ statsComputed = false;
+ data.Add(dataItem);
+ }
+ public void RemoveRange(int index, int count) {
+ data.RemoveRange(index, count);
+ statsComputed = false;
+ }
+ internal void Adjust(float delta) {
+ statsComputed = false;
+ for (int i = 0; i < data.Count; i++)
+ data[i] += delta;
+ }
+ internal void AdjustForScale(float scale) {
+ statsComputed = false;
+ for (int i = 0; i < data.Count; i++)
+ data[i] /= scale;
+ }
+ public int Count { get { return data.Count; } }
+ public float this[int idx] { get { return data[idx]; } }
+ public IEnumerator<float> GetEnumerator() { return data.GetEnumerator(); }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return data.GetEnumerator(); }
+
+ public float Minimum {
+ get {
+ if (!statsComputed) {
+ this.ComputeStats();
+ }
+
+ return minimum;
+ }
+ }
+ public float Maximum {
+ get {
+ if (!statsComputed) {
+ this.ComputeStats();
+ }
+
+ return maximum;
+ }
+ }
+ public float Median {
+ get {
+ if (!statsComputed) {
+ this.ComputeStats();
+ }
+
+ return median;
+ }
+ }
+
+ public float Mean {
+ get {
+ if (!statsComputed) {
+ this.ComputeStats();
+ }
+
+ return mean;
+ }
+ }
+
+ public float StandardDeviation {
+ get {
+ if (!statsComputed) {
+ this.ComputeStats();
+ }
+
+ return standardDeviation;
+ }
+ }
+
+ /// <summary>
+ /// Returns a <see cref="System.String"/> that represents this instance.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="System.String"/> that represents this instance.
+ /// </returns>
+ public override string ToString() {
+ if (!statsComputed) {
+ ComputeStats();
+ }
+
+ return "mean=" + mean.ToString("f3") + " median=" + median.ToString("f3") +
+ " min=" + minimum.ToString("f3") + " max=" + maximum.ToString("f3") +
+ " sdtdev=" + standardDeviation.ToString("f3") + " samples=" + Count.ToString();
+ }
+
+ private void ComputeStats() {
+ minimum = float.MaxValue;
+ maximum = float.MinValue;
+ median = 0.0F;
+ mean = 0.0F;
+ standardDeviation = 0.0F;
+
+ double total = 0;
+ foreach (float dataPoint in this) {
+ if (dataPoint < minimum)
+ minimum = dataPoint;
+ if (dataPoint > maximum)
+ maximum = dataPoint;
+ total += dataPoint;
+ }
+
+ if (Count > 0) {
+ data.Sort();
+ if (Count % 2 == 1)
+ median = this[Count / 2];
+ else
+ median = (this[(Count / 2) - 1] + this[Count / 2]) / 2;
+ mean = (float)(total / Count);
+
+ double squares = 0.0;
+ foreach (float dataPoint in this) {
+ double diffFromMean = dataPoint - mean;
+ squares += diffFromMean * diffFromMean;
+ }
+ standardDeviation = (float)Math.Sqrt(squares / Count);
+ }
+
+ statsComputed = true;
+ }
+ };
+
+ /// <summary>
+ /// The CodeTimer class only times one invocation of the code. Often, you want to collect many samples so
+ /// that you can determine how noisy the resulting data is. This is what MultiSampleCodeTimer does.
+ /// </summary>
+ internal class MultiSampleCodeTimer {
+ public MultiSampleCodeTimer() : this(1) { }
+ public MultiSampleCodeTimer(int sampleCount) : this(sampleCount, 1) { }
+ public MultiSampleCodeTimer(int sampleCount, int iterationCount) {
+ SampleCount = sampleCount;
+ timer = new CodeTimer(iterationCount);
+ timer.Prime = false; // We will do the priming (or not).
+ Prime = true;
+ }
+ public MultiSampleCodeTimer(MultiSampleCodeTimer template)
+ : this(template.SampleCount, template.IterationCount) {
+ OnMeasure = template.OnMeasure;
+ }
+
+ /// <summary>
+ /// If true (the default), the benchmark is run once before the actual measurement to
+ /// insure that any 'first time' initialization is complete.
+ /// </summary>
+ public bool Prime;
+ /// <summary>
+ /// The number of times the benchmark is run in a loop for a single measument.
+ /// </summary>
+ public int IterationCount { get { return timer.IterationCount; } set { timer.IterationCount = value; } }
+ /// <summary>
+ /// The number of measurments to make for a single benchmark.
+ /// </summary>
+ public int SampleCount;
+ /// <summary>
+ /// The smallest time (in microseconds) that can be resolved by the timer).
+ /// </summary>
+ public static float ResolutionUsec { get { return 1000000.0F / Stopwatch.Frequency; } }
+
+ public delegate void MeasureCallback(string name, int iterationCount, float scale, Stats sample);
+ /// <summary>
+ /// OnMeasure is signaled every time a Measure() is called.
+ /// </summary>
+ public event MeasureCallback OnMeasure;
+
+ public Stats Measure(string name, Action action) {
+ return Measure(name, 1, action, null);
+ }
+ /// <summary>
+ /// The main measurment routine. Calling this will cause code:OnMeasure event to be
+ /// raised.
+ /// </summary>
+ /// <param name="name">name of the benchmark</param>
+ /// <param name="scale">The number of times the benchmark is cloned in 'action' (typically 1)</param>
+ /// <param name="action">The actual code to measure.</param>
+ /// <returns>A Stats object representing the measurements (in usec)</returns>
+ public Stats Measure(string name, float scale, Action action) {
+ return Measure(name, scale, action, null);
+ }
+ /// <summary>
+ /// The main measurment routine. Calling this will cause code:OnMeasure event to be
+ /// raised.
+ /// </summary>
+ /// <param name="name">name of the benchmark</param>
+ /// <param name="scale">The number of times the benchmark is cloned in 'action' (typically 1)</param>
+ /// <param name="action">The actual code to measure.</param>
+ /// <param name="reset">Code that will be called before 'action' to reset the state of the benchmark.</param>
+ /// <returns>A Stats object representing the measurements (in usec)</returns>
+ public Stats Measure(string name, float scale, Action action, Action reset) {
+ if (reset != null && IterationCount != 1)
+ throw new ApplicationException("Reset can only be used on timers with an iteration count of 1");
+ Stats statsUSec = new Stats();
+ if (Prime) {
+ if (reset != null)
+ reset();
+ action();
+ }
+ for (int i = 0; i < SampleCount; i++) {
+ if (reset != null)
+ reset();
+ statsUSec.Add(timer.Measure(name, scale, action));
+ }
+
+ if (OnMeasure != null)
+ OnMeasure(name, IterationCount, scale, statsUSec);
+ return statsUSec;
+ }
+
+ /// <summary>
+ /// Prints the mean, median, min, max, and stdDev and count of the samples to the Console
+ /// Useful as a target for OnMeasure
+ /// </summary>
+ public static MeasureCallback PrintStats = delegate(string name, int iterationCount, float scale, Stats sample) {
+ Console.WriteLine(name + ": " + sample.ToString());
+ };
+ /// <summary>
+ /// Prints the mean with a error bound (2 standard deviations, which imply a you have
+ /// 95% confidence that a sampleUsec will be with the bounds (for a normal distribution).
+ /// This is a good default target for OnMeasure.
+ /// </summary>
+ public static MeasureCallback Print = delegate(string name, int iterationCount, float scale, Stats sample) {
+ // +- two standard deviations covers 95% of all samples in a normal distribution
+ float errorPercent = (sample.StandardDeviation * 2 * 100) / Math.Abs(sample.Mean);
+ string errorString = ">400%";
+ if (errorPercent < 400)
+ errorString = (errorPercent.ToString("f0") + "%").PadRight(5);
+ string countString = "";
+ if (iterationCount != 1)
+ countString = "count: " + iterationCount.ToString() + " ";
+ Console.WriteLine(name + ": " + countString + sample.Mean.ToString("f3").PadLeft(8) + " +- " + errorString + " msec");
+ };
+
+ #region privates
+ CodeTimer timer;
+ #endregion
+ };
+
+ /// <summary>
+ /// CodeTimer is a simple wrapper that uses System.Diagnostics.StopWatch
+ /// to time the body of some code (given by a delegate), to high precision.
+ /// </summary>
+ public class CodeTimer {
+ public CodeTimer() : this(1) { }
+ public CodeTimer(int iterationCount) {
+ this.iterationCount = iterationCount;
+ Prime = true;
+
+ // Spin the CPU for a while. This should help insure that the CPU gets out of any low power
+ // mode so so that we get more stable results.
+ // TODO: see if this is true, and if there is a better way of doing it.
+ Stopwatch sw = Stopwatch.StartNew();
+ while (sw.ElapsedMilliseconds < 32) {
+ }
+ }
+ /// <summary>
+ /// The number of times the benchmark is run in a loop for a single measument.
+ /// </summary>
+ public int IterationCount {
+ get { return iterationCount; }
+ set {
+ iterationCount = value;
+ overheadValid = false;
+ }
+ }
+ /// <summary>
+ /// By default CodeTimer will run the action once before doing a
+ /// measurement run. This insures one-time actions like JIT
+ /// compilation are not being measured. However if the benchmark is
+ /// not idempotent, this can be a problem. Setting Prime=false
+ /// insures that this Priming does not happen.
+ /// </summary>
+ public bool Prime;
+ public delegate void MeasureCallback(string name, int iterationCount, float sample);
+ /// <summary>
+ /// OnMeasure is signaled every time a Measure() is called.
+ /// </summary>
+ public event MeasureCallback OnMeasure;
+ /// <summary>
+ /// The smallest time (in microseconds) that can be resolved by the timer).
+ /// </summary>
+ public static float ResolutionUsec { get { return 1000000.0F / Stopwatch.Frequency; } }
+ /// <summary>
+ /// Returns the number of microsecond it took to run 'action', 'count' times.
+ /// </summary>
+ public float Measure(string name, Action action) {
+ return Measure(name, 1, action);
+ }
+ /// <summary>
+ /// Returns the number of microseconds it to to run action 'count' times divided by 'scale'.
+ /// Scaling is useful if you want to normalize to a single iteration for example.
+ /// </summary>
+ public float Measure(string name, float scale, Action action) {
+ Stopwatch sw = new Stopwatch();
+
+ // Run the action once to do any JITTing that might happen.
+ if (Prime)
+ action();
+ float overheadUsec = GetOverheadUsec(action);
+
+ sw.Reset();
+ sw.Start();
+ for (int j = 0; j < iterationCount; j++)
+ action();
+ sw.Stop();
+
+ float sampleUsec = (float)((sw.Elapsed.TotalMilliseconds * 1000.0F - overheadUsec) / scale / iterationCount);
+ if (!computingOverhead && OnMeasure != null)
+ OnMeasure(name, iterationCount, sampleUsec);
+ return sampleUsec;
+ }
+ /// <summary>
+ /// Prints the result of a CodeTimer to standard output.
+ /// This is a good default target for OnMeasure.
+ /// </summary>
+ public static MeasureCallback Print = delegate(string name, int iterationCount, float sample) {
+ Console.WriteLine("{0}: count={1} time={2:f3} msec ", name, iterationCount, sample);
+ };
+ #region privates
+
+ /// <summary>
+ /// Time the overheadUsec of the harness that does nothing so we can subtract it out.
+ ///
+ /// Because calling delegates on static methods is more expensive than caling delegates on
+ /// instance methods we need the action to determine the overheadUsec.
+ /// </summary>
+ /// <returns></returns>
+ float GetOverheadUsec(Action action) {
+ if (!overheadValid) {
+ if (computingOverhead)
+ return 0.0F;
+ computingOverhead = true;
+
+ // Compute the overheads of calling differnet types of delegates.
+ Action emptyInstanceAction = new Action(this.emptyMethod);
+ // Prime the actions (JIT them)
+ Measure(null, emptyInstanceAction);
+ // Compute the min over 5 runs (figuring better not to go negative)
+ instanceOverheadUsec = float.MaxValue;
+ for (int i = 0; i < 5; i++) {
+ // We multiply by iteration count because we don't want this scaled by the
+ // count but 'Measure' does it by whether we want it or not.
+ instanceOverheadUsec = Math.Min(Measure(null, emptyInstanceAction) * IterationCount, instanceOverheadUsec);
+ }
+
+ Action emptyStaticAction = new Action(emptyStaticMethod);
+ Measure(null, emptyStaticAction);
+ staticOverheadUsec = float.MaxValue;
+ for (int i = 0; i < 5; i++)
+ staticOverheadUsec = Math.Min(Measure(null, emptyStaticAction) * IterationCount, staticOverheadUsec);
+
+ computingOverhead = false;
+ overheadValid = true;
+ }
+
+ if (action.Target == null)
+ return staticOverheadUsec;
+ else
+ return instanceOverheadUsec;
+ }
+
+ static private void emptyStaticMethod() { }
+ private void emptyMethod() { }
+
+ bool overheadValid;
+ bool computingOverhead;
+ int iterationCount;
+ float staticOverheadUsec;
+ float instanceOverheadUsec;
+
+ #endregion
+ };
+}
+
diff --git a/src/DotNetOpenAuth.Test/Performance/HighPerformance.cs b/src/DotNetOpenAuth.Test/Performance/HighPerformance.cs
new file mode 100644
index 0000000..695aeda
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Performance/HighPerformance.cs
@@ -0,0 +1,178 @@
+//-----------------------------------------------------------------------
+// <copyright file="HighPerformance.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Performance {
+ using System;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+ using System.Threading;
+ using log4net;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Suppresses logging and forces the CPU into a high performance mode.
+ /// </summary>
+ internal class HighPerformance : IDisposable {
+ private readonly log4net.Core.Level originalLoggerThreshold;
+ private readonly PowerManagment.PowerSetting powerSetting;
+ private readonly ProcessPriorityClass originalProcessPriority;
+
+#pragma warning disable 0618
+ /// <summary>
+ /// Initializes a new instance of the <see cref="HighPerformance"/> class.
+ /// </summary>
+ internal HighPerformance() {
+ ////if (!WaitForQuietCpu()) {
+ //// Assert.Inconclusive("Timed out waiting for a quiet CPU in which to perform perf tests.");
+ ////}
+
+ this.originalLoggerThreshold = LogManager.GetLoggerRepository().Threshold;
+ LogManager.GetLoggerRepository().Threshold = LogManager.GetLoggerRepository().LevelMap["OFF"];
+ this.powerSetting = new PowerManagment.PowerSetting(PowerManagment.PowerProfiles.HighPerformance);
+ this.originalProcessPriority = Process.GetCurrentProcess().PriorityClass;
+ Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
+ Thread.CurrentThread.Priority = ThreadPriority.Highest;
+ SpinCpu();
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose() {
+ Thread.CurrentThread.Priority = ThreadPriority.Normal;
+ Process.GetCurrentProcess().PriorityClass = this.originalProcessPriority;
+ this.powerSetting.Dispose(); // restores original power setting.
+ LogManager.GetLoggerRepository().Threshold = this.originalLoggerThreshold;
+ }
+#pragma warning restore 0618
+
+ /// <summary>
+ /// Runs the CPU in a tight loop to get it out of any low power state.
+ /// </summary>
+ private static void SpinCpu() {
+ int dummy;
+ new MultiSampleCodeTimer(10, 1000).Measure(
+ "Loop 1K times",
+ 1,
+ delegate {
+ int k = 0;
+ while (k < 1000) {
+ k++; // still in danger of being optimized.
+ }
+
+ dummy = k; // avoid optimization.
+ });
+ }
+
+ private static bool WaitForQuietCpu(float maxCpuSpike = 25, int minSecondsOfQuiet = 2, int maxSecondsBeforeGiveUp = 30) {
+ using (var pc = new System.Diagnostics.PerformanceCounter()) {
+ pc.CategoryName = "Processor";
+ pc.CounterName = "% Processor Time";
+ pc.InstanceName = "_Total";
+
+ TimeSpan samplingInterval = TimeSpan.FromMilliseconds(1000);
+ TimeSpan minimumQuietTime = TimeSpan.FromSeconds(minSecondsOfQuiet);
+ TimeSpan maximumTimeBeforeBail = TimeSpan.FromSeconds(maxSecondsBeforeGiveUp);
+ DateTime startTryingStamp = DateTime.Now;
+ int hitsRequired = (int)(minimumQuietTime.TotalMilliseconds / samplingInterval.TotalMilliseconds);
+ while (DateTime.Now - startTryingStamp < maximumTimeBeforeBail) {
+ int hits;
+ for (hits = 0; hits < hitsRequired; hits++) {
+ float currentCpuUtilization = pc.NextValue();
+ if (currentCpuUtilization > maxCpuSpike) {
+ ////Console.WriteLine("Miss: CPU at {0}% utilization", currentCpuUtilization);
+ break;
+ }
+
+ ////Console.WriteLine("Hit: CPU at {0}% utilization", currentCpuUtilization);
+ Thread.Sleep(samplingInterval);
+ }
+
+ if (hits == hitsRequired) {
+ return true;
+ }
+
+ Thread.Sleep(samplingInterval);
+ }
+
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// PowerManagement allows you to access the funtionality of the Control Panel -> Power Options
+ /// dialog in windows. (Currently we only use VISTA APIs).
+ /// </summary>
+ private static class PowerManagment {
+ internal static unsafe Guid CurrentPolicy {
+ get {
+ Guid* retPolicy = null;
+ Guid ret = Guid.Empty;
+ try {
+ int callRet = PowerGetActiveScheme(IntPtr.Zero, ref retPolicy);
+ if (callRet == 0) {
+ ret = *retPolicy;
+ Marshal.FreeHGlobal((IntPtr)retPolicy);
+ }
+ } catch (Exception) {
+ }
+ return ret;
+ }
+
+ set {
+ Guid newPolicy = value;
+ int result = PowerSetActiveScheme(IntPtr.Zero, ref newPolicy);
+ if (result != 0) {
+ TestUtilities.TestLogger.ErrorFormat("Unable to set power management policy. Error code: {0}", result);
+ ////throw new Win32Exception(result);
+ }
+ }
+ }
+
+ [DllImport("powrprof.dll")]
+ private static unsafe extern int PowerGetActiveScheme(IntPtr reservedZero, ref Guid* policyGuidRet);
+
+ [DllImport("powrprof.dll")]
+ private static extern int PowerSetActiveScheme(IntPtr reservedZero, ref Guid policyGuid);
+
+ internal static class PowerProfiles {
+ internal static Guid HighPerformance = new Guid(0x8c5e7fda, 0xe8bf, 0x4a96, 0x9a, 0x85, 0xa6, 0xe2, 0x3a, 0x8c, 0x63, 0x5c);
+
+ internal static Guid Balanced = new Guid(0x381b4222, 0xf694, 0x41f0, 0x96, 0x85, 0xff, 0x5b, 0xb2, 0x60, 0xdf, 0x2e);
+
+ internal static Guid PowerSaver = new Guid(0xa1841308, 0x3541, 0x4fab, 0xbc, 0x81, 0xf7, 0x15, 0x56, 0xf2, 0x0b, 0x4a);
+ }
+
+ internal class PowerSetting : IDisposable {
+ /// <summary>
+ /// The power policy in effect when this instance was constructed.
+ /// </summary>
+ private Guid previousPolicy;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PowerSetting"/> class.
+ /// </summary>
+ /// <param name="powerProfile">The power profile.</param>
+ internal PowerSetting(Guid powerProfile) {
+ this.previousPolicy = PowerManagment.CurrentPolicy;
+ if (this.previousPolicy != powerProfile) {
+ PowerManagment.CurrentPolicy = powerProfile;
+ }
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose() {
+ if (this.previousPolicy != PowerManagment.CurrentPolicy) {
+ PowerManagment.CurrentPolicy = this.previousPolicy;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs b/src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs
new file mode 100644
index 0000000..5e28732
--- /dev/null
+++ b/src/DotNetOpenAuth.Test/Performance/PerformanceTestUtilities.cs
@@ -0,0 +1,56 @@
+//-----------------------------------------------------------------------
+// <copyright file="PerformanceTestUtilities.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Test.Performance {
+ using System;
+ using System.Diagnostics;
+ using System.Reflection;
+ using System.Threading;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using NUnit.Framework;
+
+ internal static class PerformanceTestUtilities {
+ internal static Stats Baseline;
+
+ static PerformanceTestUtilities() {
+ Baseline = CollectBaseline();
+ TestUtilities.TestLogger.InfoFormat(
+ "Scaled where EmptyStaticFunction = 1.0 ({0:f1} nsec = 1.0 units)",
+ Baseline.Median * 1000);
+ }
+
+ internal static bool IsOptimized(Assembly assembly) {
+ DebuggableAttribute debugAttribute = (DebuggableAttribute)System.Attribute.GetCustomAttribute(assembly, typeof(System.Diagnostics.DebuggableAttribute));
+ return debugAttribute == null || !debugAttribute.IsJITOptimizerDisabled;
+ }
+
+ private static Stats CollectBaseline() {
+ using (new HighPerformance()) {
+ return new MultiSampleCodeTimer(10, 1000).Measure(
+ "MethodCalls: EmptyStaticFunction()",
+ 10,
+ delegate {
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ Class.EmptyStaticFunction();
+ });
+ }
+ }
+
+ private class Class {
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static void EmptyStaticFunction() {
+ }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth.Test/TestBase.cs b/src/DotNetOpenAuth.Test/TestBase.cs
index 8aeca2d..4a6eaca 100644
--- a/src/DotNetOpenAuth.Test/TestBase.cs
+++ b/src/DotNetOpenAuth.Test/TestBase.cs
@@ -11,6 +11,8 @@ namespace DotNetOpenAuth.Test {
using System.Web;
using DotNetOpenAuth.Messaging.Reflection;
using DotNetOpenAuth.OAuth.Messages;
+ using DotNetOpenAuth.OpenId.RelyingParty;
+ using DotNetOpenAuth.Test.Performance;
using log4net;
using NUnit.Framework;
@@ -65,6 +67,34 @@ namespace DotNetOpenAuth.Test {
log4net.LogManager.Shutdown();
}
+ internal static Stats MeasurePerformance(Action action, float maximumAllowedUnitTime, int samples = 10, int iterations = 100, string name = null) {
+ if (!PerformanceTestUtilities.IsOptimized(typeof(OpenIdRelyingParty).Assembly)) {
+ Assert.Inconclusive("Unoptimized code.");
+ }
+
+ var timer = new MultiSampleCodeTimer(samples, iterations);
+ Stats stats;
+ using (new HighPerformance()) {
+ stats = timer.Measure(name ?? TestContext.CurrentContext.Test.FullName, action);
+ }
+
+ stats.AdjustForScale(PerformanceTestUtilities.Baseline.Median);
+
+ TestUtilities.TestLogger.InfoFormat(
+ "Performance counters: median {0}, mean {1}, min {2}, max {3}, stddev {4} ({5}%).",
+ stats.Median,
+ stats.Mean,
+ stats.Minimum,
+ stats.Maximum,
+ stats.StandardDeviation,
+ stats.StandardDeviation / stats.Median * 100);
+
+ Assert.IsTrue(stats.Mean < maximumAllowedUnitTime, "The mean time of {0} exceeded the maximum allowable of {1}.", stats.Mean, maximumAllowedUnitTime);
+ TestUtilities.TestLogger.InfoFormat("Within {0}% of the maximum allowed time of {1}.", Math.Round((maximumAllowedUnitTime - stats.Mean) / maximumAllowedUnitTime * 100, 1), maximumAllowedUnitTime);
+
+ return stats;
+ }
+
/// <summary>
/// Sets HttpContext.Current to some empty (but non-null!) value.
/// </summary>
@@ -73,15 +103,5 @@ namespace DotNetOpenAuth.Test {
new HttpRequest("mock", "http://mock", "mock"),
new HttpResponse(new StringWriter()));
}
-
-#pragma warning disable 0618
- protected internal static void SuspendLogging() {
- LogManager.GetLoggerRepository().Threshold = LogManager.GetLoggerRepository().LevelMap["OFF"];
- }
-
- protected internal static void ResumeLogging() {
- LogManager.GetLoggerRepository().Threshold = LogManager.GetLoggerRepository().LevelMap["ALL"];
- }
-#pragma warning restore 0618
}
}
diff --git a/src/DotNetOpenAuth.sln b/src/DotNetOpenAuth.sln
index 2cef1b2..cf7f97e 100644
--- a/src/DotNetOpenAuth.sln
+++ b/src/DotNetOpenAuth.sln
@@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
..\doc\README.Bin.html = ..\doc\README.Bin.html
..\doc\README.html = ..\doc\README.html
..\samples\README.html = ..\samples\README.html
+ ..\nuget\content\web.config.transform = ..\nuget\content\web.config.transform
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{CD57219F-24F4-4136-8741-6063D0D7A031}"
diff --git a/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs b/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs
index 980d90f..c41ac47 100644
--- a/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs
+++ b/src/DotNetOpenAuth/ComponentModel/ConverterBase.cs
@@ -143,6 +143,7 @@ using System.Reflection;
/// <exception cref="T:System.NotSupportedException">
/// The conversion cannot be performed.
/// </exception>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Assume(System.Boolean,System.String,System.String)", Justification = "No localization required.")]
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
Contract.Assume(destinationType != null, "Missing contract.");
if (destinationType.IsInstanceOfType(value)) {
diff --git a/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
index 9c0ab77..0b27948 100644
--- a/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
+++ b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd
@@ -218,6 +218,16 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
+ <xs:attribute name="maximumIndirectMessageUrlLength" type="xs:int" default="2048">
+ <xs:annotation>
+ <xs:documentation>
+ The maximum allowable size for a 301 Redirect response before we send
+ a 200 OK response with a scripted form POST with the parameters instead
+ in order to ensure successfully sending a large payload to another server
+ that might have a maximum allowable size restriction on its GET request.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="openid">
@@ -243,6 +253,44 @@
</xs:documentation>
</xs:annotation>
<xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="trustedProviders">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element name="add">
+ <xs:complexType>
+ <xs:attribute name="endpoint" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ The OpenID Provider Endpoint (aka "OP Endpoint") that this relying party trusts.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="remove">
+ <xs:complexType>
+ <xs:attribute name="endpoint" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="clear">
+ <xs:complexType>
+ <!--tag is empty-->
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
+ <xs:attribute name="rejectAssertionsFromUntrustedProviders" type="xs:boolean" default="false">
+ <xs:annotation>
+ <xs:documentation>
+ A value indicating whether any login attempt coming from an OpenID Provider Endpoint that is not on this
+ whitelist of trusted OP Endpoints will be rejected. If the trusted providers list is empty and this value
+ is true, all assertions are rejected.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ </xs:choice>
<xs:attribute name="requireSsl" type="xs:boolean" default="false">
<xs:annotation>
<xs:documentation>
@@ -269,7 +317,7 @@
<xs:attribute name="minimumHashBitLength" type="xs:int">
<xs:annotation>
<xs:documentation>
- Shared associations with OpenID Providers will only be formed or used if they
+ Shared associations with OpenID Providers will only be formed or used if they
are willing to form associations equal to or greater than a given level of protection.
</xs:documentation>
</xs:annotation>
@@ -524,7 +572,7 @@
so security is comparable to OpenID 2.0 relying parties.
</xs:documentation>
</xs:annotation>
- </xs:attribute>
+ </xs:attribute>
<xs:attribute name="unsolicitedAssertionVerification">
<xs:annotation>
<xs:documentation>
@@ -735,7 +783,7 @@
</xs:documentation>
</xs:annotation>
<xs:complexType>
-
+
</xs:complexType>
</xs:element>
</xs:choice>
@@ -856,7 +904,7 @@
<xs:attribute name="includeEventStatistics" type="xs:boolean" default="true">
<xs:annotation>
<xs:documentation>
- Whether a set of counters that track how often certain events (such as an
+ Whether a set of counters that track how often certain events (such as an
successful or failed authentication) is included in the report.
</xs:documentation>
</xs:annotation>
diff --git a/src/DotNetOpenAuth/Configuration/MessagingElement.cs b/src/DotNetOpenAuth/Configuration/MessagingElement.cs
index f130dbc..28b34a3 100644
--- a/src/DotNetOpenAuth/Configuration/MessagingElement.cs
+++ b/src/DotNetOpenAuth/Configuration/MessagingElement.cs
@@ -37,6 +37,20 @@ namespace DotNetOpenAuth.Configuration {
private const string StrictConfigName = "strict";
/// <summary>
+ /// The default value for the <see cref="MaximumIndirectMessageUrlLength"/> property.
+ /// </summary>
+ /// <value>
+ /// 2KB, recommended by OpenID group
+ /// </value>
+ private const int DefaultMaximumIndirectMessageUrlLength = 2 * 1024;
+
+ /// <summary>
+ /// The name of the attribute that controls the maximum length of a URL before it is converted
+ /// to a POST payload.
+ /// </summary>
+ private const string MaximumIndirectMessageUrlLengthConfigName = "maximumIndirectMessageUrlLength";
+
+ /// <summary>
/// Gets the actual maximum message lifetime that a program should allow.
/// </summary>
/// <value>The sum of the <see cref="MaximumMessageLifetime"/> and
@@ -114,5 +128,19 @@ namespace DotNetOpenAuth.Configuration {
get { return (UntrustedWebRequestElement)this[UntrustedWebRequestElementName] ?? new UntrustedWebRequestElement(); }
set { this[UntrustedWebRequestElementName] = value; }
}
+
+ /// <summary>
+ /// Gets or sets the maximum allowable size for a 301 Redirect response before we send
+ /// a 200 OK response with a scripted form POST with the parameters instead
+ /// in order to ensure successfully sending a large payload to another server
+ /// that might have a maximum allowable size restriction on its GET request.
+ /// </summary>
+ /// <value>The default value is 2048.</value>
+ [ConfigurationProperty(MaximumIndirectMessageUrlLengthConfigName, DefaultValue = DefaultMaximumIndirectMessageUrlLength)]
+ [IntegerValidator(MinValue = 500, MaxValue = 4096)]
+ internal int MaximumIndirectMessageUrlLength {
+ get { return (int)this[MaximumIndirectMessageUrlLengthConfigName]; }
+ set { this[MaximumIndirectMessageUrlLengthConfigName] = value; }
+ }
}
}
diff --git a/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs b/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs
index 1bf2ebc..4347e2c 100644
--- a/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs
+++ b/src/DotNetOpenAuth/Configuration/OpenIdRelyingPartySecuritySettingsElement.cs
@@ -81,6 +81,11 @@ namespace DotNetOpenAuth.Configuration {
private const string ProtectDownlevelReplayAttacksConfigName = "protectDownlevelReplayAttacks";
/// <summary>
+ /// The name of the &lt;trustedProviders&gt; sub-element.
+ /// </summary>
+ private const string TrustedProvidersElementName = "trustedProviders";
+
+ /// <summary>
/// Initializes a new instance of the <see cref="OpenIdRelyingPartySecuritySettingsElement"/> class.
/// </summary>
public OpenIdRelyingPartySecuritySettingsElement() {
@@ -235,6 +240,16 @@ namespace DotNetOpenAuth.Configuration {
}
/// <summary>
+ /// Gets or sets the set of trusted OpenID Provider Endpoints.
+ /// </summary>
+ [ConfigurationProperty(TrustedProvidersElementName, IsDefaultCollection = false)]
+ [ConfigurationCollection(typeof(TrustedProviderConfigurationCollection))]
+ public TrustedProviderConfigurationCollection TrustedProviders {
+ get { return (TrustedProviderConfigurationCollection)this[TrustedProvidersElementName] ?? new TrustedProviderConfigurationCollection(); }
+ set { this[TrustedProvidersElementName] = value; }
+ }
+
+ /// <summary>
/// Initializes a programmatically manipulatable bag of these security settings with the settings from the config file.
/// </summary>
/// <returns>The newly created security settings object.</returns>
@@ -256,6 +271,11 @@ namespace DotNetOpenAuth.Configuration {
settings.AllowApproximateIdentifierDiscovery = this.AllowApproximateIdentifierDiscovery;
settings.ProtectDownlevelReplayAttacks = this.ProtectDownlevelReplayAttacks;
+ settings.RejectAssertionsFromUntrustedProviders = this.TrustedProviders.RejectAssertionsFromUntrustedProviders;
+ foreach (TrustedProviderEndpointConfigurationElement opEndpoint in this.TrustedProviders) {
+ settings.TrustedProviderEndpoints.Add(opEndpoint.ProviderEndpoint);
+ }
+
return settings;
}
}
diff --git a/src/DotNetOpenAuth/Configuration/TrustedProviderConfigurationCollection.cs b/src/DotNetOpenAuth/Configuration/TrustedProviderConfigurationCollection.cs
new file mode 100644
index 0000000..f5e62f4
--- /dev/null
+++ b/src/DotNetOpenAuth/Configuration/TrustedProviderConfigurationCollection.cs
@@ -0,0 +1,74 @@
+//-----------------------------------------------------------------------
+// <copyright file="TrustedProviderConfigurationCollection.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Configuration {
+ using System;
+ using System.Collections.Generic;
+ using System.Configuration;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+
+ /// <summary>
+ /// A configuration collection of trusted OP Endpoints.
+ /// </summary>
+ internal class TrustedProviderConfigurationCollection : ConfigurationElementCollection {
+ /// <summary>
+ /// The name of the "rejectAssertionsFromUntrustedProviders" element.
+ /// </summary>
+ private const string RejectAssertionsFromUntrustedProvidersConfigName = "rejectAssertionsFromUntrustedProviders";
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TrustedProviderConfigurationCollection"/> class.
+ /// </summary>
+ internal TrustedProviderConfigurationCollection() {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TrustedProviderConfigurationCollection"/> class.
+ /// </summary>
+ /// <param name="elements">The elements to initialize the collection with.</param>
+ [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "Seems unavoidable")]
+ internal TrustedProviderConfigurationCollection(IEnumerable<TrustedProviderEndpointConfigurationElement> elements) {
+ Contract.Requires<ArgumentNullException>(elements != null);
+
+ foreach (TrustedProviderEndpointConfigurationElement element in elements) {
+ this.BaseAdd(element);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether any login attempt coming from an OpenID Provider Endpoint that is not on this
+ /// whitelist of trusted OP Endpoints will be rejected. If the trusted providers list is empty and this value
+ /// is true, all assertions are rejected.
+ /// </summary>
+ [ConfigurationProperty(RejectAssertionsFromUntrustedProvidersConfigName, DefaultValue = false)]
+ internal bool RejectAssertionsFromUntrustedProviders {
+ get { return (bool)this[RejectAssertionsFromUntrustedProvidersConfigName]; }
+ set { this[RejectAssertionsFromUntrustedProvidersConfigName] = value; }
+ }
+
+ /// <summary>
+ /// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement"/>.
+ /// </summary>
+ /// <returns>
+ /// A new <see cref="T:System.Configuration.ConfigurationElement"/>.
+ /// </returns>
+ protected override ConfigurationElement CreateNewElement() {
+ return new TrustedProviderEndpointConfigurationElement();
+ }
+
+ /// <summary>
+ /// Gets the element key for a specified configuration element when overridden in a derived class.
+ /// </summary>
+ /// <param name="element">The <see cref="T:System.Configuration.ConfigurationElement"/> to return the key for.</param>
+ /// <returns>
+ /// An <see cref="T:System.Object"/> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement"/>.
+ /// </returns>
+ protected override object GetElementKey(ConfigurationElement element) {
+ return ((TrustedProviderEndpointConfigurationElement)element).ProviderEndpoint;
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/Configuration/TrustedProviderEndpointConfigurationElement.cs b/src/DotNetOpenAuth/Configuration/TrustedProviderEndpointConfigurationElement.cs
new file mode 100644
index 0000000..2576eb0
--- /dev/null
+++ b/src/DotNetOpenAuth/Configuration/TrustedProviderEndpointConfigurationElement.cs
@@ -0,0 +1,35 @@
+//-----------------------------------------------------------------------
+// <copyright file="TrustedProviderEndpointConfigurationElement.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Configuration {
+ using System;
+ using System.Configuration;
+
+ /// <summary>
+ /// A configuration element that records a trusted Provider Endpoint.
+ /// </summary>
+ internal class TrustedProviderEndpointConfigurationElement : ConfigurationElement {
+ /// <summary>
+ /// The name of the attribute that stores the <see cref="ProviderEndpoint"/> value.
+ /// </summary>
+ private const string ProviderEndpointConfigName = "endpoint";
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TrustedProviderEndpointConfigurationElement"/> class.
+ /// </summary>
+ public TrustedProviderEndpointConfigurationElement() {
+ }
+
+ /// <summary>
+ /// Gets or sets the OpenID Provider Endpoint (aka "OP Endpoint") that this relying party trusts.
+ /// </summary>
+ [ConfigurationProperty(ProviderEndpointConfigName, IsRequired = true, IsKey = true)]
+ public Uri ProviderEndpoint {
+ get { return (Uri)this[ProviderEndpointConfigName]; }
+ set { this[ProviderEndpointConfigName] = value; }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
index 488e092..52930af 100644
--- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj
+++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj
@@ -84,7 +84,7 @@ http://opensource.org/licenses/ms-pl.html
<CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs>
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
<CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet>Migrated rules for DotNetOpenAuth.ruleset</CodeAnalysisRuleSet>
<CodeContractsExtraRewriteOptions />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@@ -125,7 +125,7 @@ http://opensource.org/licenses/ms-pl.html
<CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs>
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
<CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet>Migrated rules for DotNetOpenAuth.ruleset</CodeAnalysisRuleSet>
<CodeContractsExtraRewriteOptions />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseNoUI|AnyCPU'">
@@ -165,6 +165,7 @@ http://opensource.org/licenses/ms-pl.html
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
<CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
<CodeContractsExtraRewriteOptions />
+ <CodeAnalysisRuleSet>Migrated rules for DotNetOpenAuth.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -181,7 +182,7 @@ http://opensource.org/licenses/ms-pl.html
</CodeContractsCustomRewriterAssembly>
<CodeContractsCustomRewriterClass>
</CodeContractsCustomRewriterClass>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+ <CodeContractsRuntimeCheckingLevel>Preconditions</CodeContractsRuntimeCheckingLevel>
<CodeContractsRunCodeAnalysis>True</CodeContractsRunCodeAnalysis>
<CodeContractsBuildReferenceAssembly>True</CodeContractsBuildReferenceAssembly>
<CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
@@ -295,6 +296,8 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="Configuration\OpenIdRelyingPartyElement.cs" />
<Compile Include="Configuration\OpenIdRelyingPartySecuritySettingsElement.cs" />
<Compile Include="Configuration\ReportingElement.cs" />
+ <Compile Include="Configuration\TrustedProviderConfigurationCollection.cs" />
+ <Compile Include="Configuration\TrustedProviderEndpointConfigurationElement.cs" />
<Compile Include="Configuration\TypeConfigurationCollection.cs" />
<Compile Include="Configuration\TypeConfigurationElement.cs" />
<Compile Include="Configuration\UntrustedWebRequestElement.cs" />
@@ -316,6 +319,7 @@ http://opensource.org/licenses/ms-pl.html
<Compile Include="InfoCard\WellKnownIssuers.cs" />
<Compile Include="Messaging\CachedDirectWebResponse.cs" />
<Compile Include="Messaging\ChannelContract.cs" />
+ <Compile Include="Messaging\IMessageOriginalPayload.cs" />
<Compile Include="Messaging\DirectWebRequestOptions.cs" />
<Compile Include="Messaging\EnumerableCache.cs" />
<Compile Include="Messaging\HostErrorException.cs" />
@@ -795,10 +799,11 @@ http://opensource.org/licenses/ms-pl.html
OutputFile="$(ILMergeOutputAssembly)"
KeyFile="$(PublicKeyFile)"
DelaySign="true"
+ ToolPath="$(ProjectRoot)tools\ILMerge"
TargetPlatformVersion="$(ClrVersion).0"
TargetPlatformDirectory="$(ILMergeTargetPlatformDirectory)" />
</Target>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))\EnlistmentInfo.targets" Condition=" '$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), EnlistmentInfo.targets))' != '' " />
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/DotNetOpenAuth/GlobalSuppressions.cs b/src/DotNetOpenAuth/GlobalSuppressions.cs
index 9b1bcfa..8539422 100644
--- a/src/DotNetOpenAuth/GlobalSuppressions.cs
+++ b/src/DotNetOpenAuth/GlobalSuppressions.cs
@@ -9,54 +9,61 @@
// "In Project Suppression File".
// You do not need to add suppressions to this file manually.
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.HmacSha1SigningBindingElement")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Hmac", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.HmacSha1SigningBindingElement")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rsa", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.RsaSha1SigningBindingElement")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.RsaSha1SigningBindingElement")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "Diffie-Hellman", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "checkInput", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#Initialize(Mono.Math.BigInteger,Mono.Math.BigInteger,Mono.Math.BigInteger,System.Int32,System.Boolean)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Int32,System.Int32,Org.Mentalis.Security.Cryptography.DHKeyGeneration)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Byte[],System.Byte[],System.Int32)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Byte[],System.Byte[],System.Byte[])")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellman.#FromXmlString(System.String)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "PostTrialDivisionTest", Scope = "member", Target = "Mono.Math.Prime.Generator.SequentialSearchPrimeGeneratorBase.#GenerateNewPrime(System.Int32,System.Object)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.Prime.PrimalityTests.#GetSPPRounds(Mono.Math.BigInteger,Mono.Math.Prime.ConfidenceFactor)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.BigInteger+ModulusRing.#BarrettReduction(Mono.Math.BigInteger)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.BigInteger.#op_Multiply(Mono.Math.BigInteger,Mono.Math.BigInteger)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "sign", Scope = "member", Target = "Mono.Math.BigInteger.#.ctor(Mono.Math.BigInteger+Sign,System.UInt32)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "notUsed", Scope = "member", Target = "Mono.Math.BigInteger.#isProbablePrime(System.Int32)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "returnto", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "openid", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "claimedid", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Xri", Scope = "type", Target = "DotNetOpenAuth.OpenId.XriIdentifier")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "yyyy-MM-dd", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "usersetupurl", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "birthdate", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "rehydrated", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Messaging.Bindings")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.ChannelElements")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.SimpleRegistration")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Messages")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "We sign it when producing drops.")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.OAuth")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.UI")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Messaging.Reflection")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "oauthverifier", Scope = "resource", Target = "DotNetOpenAuth.OAuth.OAuthStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "whitelist", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "icam", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "idmanagement", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "no-pii", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "req", Scope = "member", Target = "DotNetOpenAuth.OpenId.Provider.IAuthenticationRequestContract.#DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest.ClaimedIdentifier")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "runat", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.OnOutgoingAuthenticationRequest(DotNetOpenAuth.OpenId.RelyingParty.IAuthenticationRequest)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.OnIncomingPositiveAssertion(DotNetOpenAuth.OpenId.RelyingParty.IAuthenticationResponse)")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.ApplySecuritySettings(DotNetOpenAuth.OpenId.RelyingParty.RelyingPartySecuritySettings)")]
-[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")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Mvc")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Mvc", Scope = "namespace", Target = "DotNetOpenAuth.Mvc")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.HmacSha1SigningBindingElement")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Hmac", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.HmacSha1SigningBindingElement")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rsa", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.RsaSha1SigningBindingElement")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha", Scope = "type", Target = "DotNetOpenAuth.OAuth.ChannelElements.RsaSha1SigningBindingElement")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "Diffie-Hellman", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "checkInput", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#Initialize(Mono.Math.BigInteger,Mono.Math.BigInteger,Mono.Math.BigInteger,System.Int32,System.Boolean)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Int32,System.Int32,Org.Mentalis.Security.Cryptography.DHKeyGeneration)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Byte[],System.Byte[],System.Int32)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellmanManaged.#.ctor(System.Byte[],System.Byte[],System.Byte[])")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Org.Mentalis.Security.Cryptography.DiffieHellman.#FromXmlString(System.String)")]
+[assembly: SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "PostTrialDivisionTest", Scope = "member", Target = "Mono.Math.Prime.Generator.SequentialSearchPrimeGeneratorBase.#GenerateNewPrime(System.Int32,System.Object)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.Prime.PrimalityTests.#GetSPPRounds(Mono.Math.BigInteger,Mono.Math.Prime.ConfidenceFactor)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.BigInteger+ModulusRing.#BarrettReduction(Mono.Math.BigInteger)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes", Scope = "member", Target = "Mono.Math.BigInteger.#op_Multiply(Mono.Math.BigInteger,Mono.Math.BigInteger)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "sign", Scope = "member", Target = "Mono.Math.BigInteger.#.ctor(Mono.Math.BigInteger+Sign,System.UInt32)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "notUsed", Scope = "member", Target = "Mono.Math.BigInteger.#isProbablePrime(System.Int32)")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "returnto", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "openid", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "claimedid", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Xri", Scope = "type", Target = "DotNetOpenAuth.OpenId.XriIdentifier")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "yyyy-MM-dd", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "usersetupurl", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "birthdate", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "rehydrated", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Messaging.Bindings")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.ChannelElements")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.SimpleRegistration")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Messages")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy")]
+[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "We sign it when producing drops.")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.OAuth")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.OpenId.Extensions.UI")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Messaging.Reflection")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "oauthverifier", Scope = "resource", Target = "DotNetOpenAuth.OAuth.OAuthStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "whitelist", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "icam", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "idmanagement", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "no-pii", Scope = "resource", Target = "DotNetOpenAuth.OpenId.Behaviors.BehaviorStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "req", Scope = "member", Target = "DotNetOpenAuth.OpenId.Provider.IAuthenticationRequestContract.#DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest.ClaimedIdentifier")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "runat", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.OnOutgoingAuthenticationRequest(DotNetOpenAuth.OpenId.RelyingParty.IAuthenticationRequest)")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.OnIncomingPositiveAssertion(DotNetOpenAuth.OpenId.RelyingParty.IAuthenticationResponse)")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.RelyingParty.IRelyingPartyBehavior.ApplySecuritySettings(DotNetOpenAuth.OpenId.RelyingParty.RelyingPartySecuritySettings)")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.OnOutgoingResponse(DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest)")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.OnIncomingRequest(DotNetOpenAuth.OpenId.Provider.IRequest)")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes", Scope = "member", Target = "DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform.#DotNetOpenAuth.OpenId.Provider.IProviderBehavior.ApplySecuritySettings(DotNetOpenAuth.OpenId.Provider.ProviderSecuritySettings)")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "DotNetOpenAuth.Mvc")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Mvc", Scope = "namespace", Target = "DotNetOpenAuth.Mvc")]
+[assembly: SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
+[assembly: SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "DotNetOpenAuth.OpenId.DiffieHellmanUtilities.#.cctor()")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Scope = "member", Target = "DotNetOpenAuth.OAuth.Messages.SignedMessageBase.#DotNetOpenAuth.Messaging.IMessageOriginalPayload.OriginalPayload")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "iframe", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "Sig", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1701:ResourceStringCompoundWordsShouldBeCasedCorrectly", MessageId = "DSig", Scope = "resource", Target = "DotNetOpenAuth.OpenId.OpenIdStrings.resources")]
diff --git a/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs b/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs
index 2ac2b7e..3dd892a 100644
--- a/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs
+++ b/src/DotNetOpenAuth/InfoCard/ReceivingTokenEventArgs.cs
@@ -71,6 +71,7 @@ namespace DotNetOpenAuth.InfoCard {
/// Adds an X.509 certificate with a private key that may be used to decrypt the incoming token.
/// </summary>
/// <param name="certificate">The certificate.</param>
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive")]
public void AddDecryptingToken(X509Certificate2 certificate) {
Contract.Requires<ArgumentNullException>(certificate != null);
Contract.Requires<ArgumentException>(certificate.HasPrivateKey);
diff --git a/src/DotNetOpenAuth/InfoCard/Token/Token.cs b/src/DotNetOpenAuth/InfoCard/Token/Token.cs
index 89fa3a3..3b6f573 100644
--- a/src/DotNetOpenAuth/InfoCard/Token/Token.cs
+++ b/src/DotNetOpenAuth/InfoCard/Token/Token.cs
@@ -41,6 +41,7 @@ namespace DotNetOpenAuth.InfoCard {
/// <param name="audience">The audience. May be <c>null</c> to avoid audience checking.</param>
/// <param name="decryptor">The decryptor to use to decrypt the token, if necessary..</param>
/// <exception cref="InformationCardException">Thrown for any problem decoding or decrypting the token.</exception>
+ [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Not a problem for this type."), SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive")]
private Token(string tokenXml, Uri audience, TokenDecryptor decryptor) {
Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(tokenXml));
Contract.Requires<ArgumentException>(decryptor != null || !IsEncrypted(tokenXml));
@@ -64,7 +65,14 @@ namespace DotNetOpenAuth.InfoCard {
}
}
- this.Xml = new XPathDocument(new StringReader(decryptedString)).CreateNavigator();
+ var stringReader = new StringReader(decryptedString);
+ try {
+ this.Xml = new XPathDocument(stringReader).CreateNavigator();
+ } catch {
+ stringReader.Dispose();
+ throw;
+ }
+
Logger.InfoCard.DebugFormat("Incoming SAML token, after any decryption: {0}", this.Xml.InnerXml);
this.AuthorizationContext = TokenUtility.AuthenticateToken(this.Xml.ReadSubtree(), audience);
}
@@ -191,13 +199,26 @@ namespace DotNetOpenAuth.InfoCard {
/// <returns>
/// <c>true</c> if the specified token XML is encrypted; otherwise, <c>false</c>.
/// </returns>
- [Pure]
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive"), Pure]
internal static bool IsEncrypted(string tokenXml) {
Contract.Requires<ArgumentNullException>(tokenXml != null);
- using (XmlReader tokenReader = XmlReader.Create(new StringReader(tokenXml))) {
+ var stringReader = new StringReader(tokenXml);
+ XmlReader tokenReader;
+ try {
+ tokenReader = XmlReader.Create(stringReader);
+ } catch {
+ stringReader.Dispose();
+ throw;
+ }
+
+ try {
Contract.Assume(tokenReader != null); // CC missing for XmlReader.Create
return IsEncrypted(tokenReader);
+ } catch {
+ IDisposable disposableReader = tokenReader;
+ disposableReader.Dispose();
+ throw;
}
}
diff --git a/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs b/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
index c9bc1d3..111d636 100644
--- a/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
+++ b/src/DotNetOpenAuth/Messaging/CachedDirectWebResponse.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.Messaging {
using System;
using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.IO;
using System.Net;
@@ -156,6 +157,7 @@ namespace DotNetOpenAuth.Messaging {
/// <param name="response">The response whose stream is to be cloned.</param>
/// <param name="maximumBytesToRead">The maximum bytes to cache.</param>
/// <returns>The seekable Stream instance that contains a copy of what was returned in the HTTP response.</returns>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Assume(System.Boolean,System.String,System.String)", Justification = "No localization required.")]
private static MemoryStream CacheNetworkStreamAndClose(HttpWebResponse response, int maximumBytesToRead) {
Contract.Requires<ArgumentNullException>(response != null);
Contract.Ensures(Contract.Result<MemoryStream>() != null);
@@ -163,15 +165,20 @@ namespace DotNetOpenAuth.Messaging {
// 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);
-
- networkStream.Dispose();
- response.Close();
-
- return cachedStream;
+ try {
+ 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);
+
+ networkStream.Dispose();
+ response.Close();
+
+ return cachedStream;
+ } catch {
+ cachedStream.Dispose();
+ throw;
+ }
}
}
}
diff --git a/src/DotNetOpenAuth/Messaging/Channel.cs b/src/DotNetOpenAuth/Messaging/Channel.cs
index 84dbe3c..0abdcfa 100644
--- a/src/DotNetOpenAuth/Messaging/Channel.cs
+++ b/src/DotNetOpenAuth/Messaging/Channel.cs
@@ -25,6 +25,7 @@ namespace DotNetOpenAuth.Messaging {
/// <summary>
/// Manages sending direct messages to a remote party and receiving responses.
/// </summary>
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Unavoidable.")]
[ContractVerification(true)]
[ContractClass(typeof(ChannelContract))]
public abstract class Channel : IDisposable {
@@ -47,14 +48,6 @@ namespace DotNetOpenAuth.Messaging {
protected internal static readonly ContentType HttpFormUrlEncodedContentType = new ContentType(HttpFormUrlEncoded) { CharSet = PostEntityEncoding.WebName };
/// <summary>
- /// The maximum allowable size for a 301 Redirect response before we send
- /// a 200 OK response with a scripted form POST with the parameters instead
- /// in order to ensure successfully sending a large payload to another server
- /// that might have a maximum allowable size restriction on its GET request.
- /// </summary>
- private const int IndirectMessageGetToPostThreshold = 2 * 1024; // 2KB, recommended by OpenID group
-
- /// <summary>
/// The HTML that should be returned to the user agent as part of a 301 Redirect.
/// </summary>
/// <value>A string that should be used as the first argument to String.Format, where the {0} should be replaced with the URL to redirect to.</value>
@@ -120,6 +113,11 @@ namespace DotNetOpenAuth.Messaging {
private RequestCachePolicy cachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
/// <summary>
+ /// Backing field for the <see cref="MaximumIndirectMessageUrlLength"/> property.
+ /// </summary>
+ private int maximumIndirectMessageUrlLength = Configuration.DotNetOpenAuthSection.Configuration.Messaging.MaximumIndirectMessageUrlLength;
+
+ /// <summary>
/// Initializes a new instance of the <see cref="Channel"/> class.
/// </summary>
/// <param name="messageTypeProvider">
@@ -157,6 +155,24 @@ namespace DotNetOpenAuth.Messaging {
public IDirectWebRequestHandler WebRequestHandler { get; set; }
/// <summary>
+ /// Gets or sets the maximum allowable size for a 301 Redirect response before we send
+ /// a 200 OK response with a scripted form POST with the parameters instead
+ /// in order to ensure successfully sending a large payload to another server
+ /// that might have a maximum allowable size restriction on its GET request.
+ /// </summary>
+ /// <value>The default value is 2048.</value>
+ public int MaximumIndirectMessageUrlLength {
+ get {
+ return this.maximumIndirectMessageUrlLength;
+ }
+
+ set {
+ Contract.Requires<ArgumentOutOfRangeException>(value >= 500 && value <= 4096);
+ this.maximumIndirectMessageUrlLength = value;
+ }
+ }
+
+ /// <summary>
/// Gets or sets the message descriptions.
/// </summary>
internal MessageDescriptionCollection MessageDescriptions {
@@ -730,7 +746,7 @@ namespace DotNetOpenAuth.Messaging {
// First try creating a 301 redirect, and fallback to a form POST
// if the message is too big.
OutgoingWebResponse response = this.Create301RedirectResponse(message, fields);
- if (response.Headers[HttpResponseHeader.Location].Length > IndirectMessageGetToPostThreshold) {
+ if (response.Headers[HttpResponseHeader.Location].Length > this.MaximumIndirectMessageUrlLength) {
response = this.CreateFormPostResponse(message, fields);
}
diff --git a/src/DotNetOpenAuth/Messaging/IMessageOriginalPayload.cs b/src/DotNetOpenAuth/Messaging/IMessageOriginalPayload.cs
new file mode 100644
index 0000000..d18be20
--- /dev/null
+++ b/src/DotNetOpenAuth/Messaging/IMessageOriginalPayload.cs
@@ -0,0 +1,40 @@
+//-----------------------------------------------------------------------
+// <copyright file="IMessageOriginalPayload.cs" company="Andrew Arnott">
+// Copyright (c) Andrew Arnott. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+namespace DotNetOpenAuth.Messaging {
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.Text;
+
+ /// <summary>
+ /// An interface that appears on messages that need to retain a description of
+ /// what their literal payload was when they were deserialized.
+ /// </summary>
+ [ContractClass(typeof(IMessageOriginalPayloadContract))]
+ public interface IMessageOriginalPayload {
+ /// <summary>
+ /// Gets or sets the original message parts, before any normalization or default values were assigned.
+ /// </summary>
+ [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "By design")]
+ IDictionary<string, string> OriginalPayload { get; set; }
+ }
+
+ /// <summary>
+ /// Code contract for the <see cref="IMessageOriginalPayload"/> interface.
+ /// </summary>
+ [ContractClassFor(typeof(IMessageOriginalPayload))]
+ internal abstract class IMessageOriginalPayloadContract : IMessageOriginalPayload {
+ /// <summary>
+ /// Gets or sets the original message parts, before any normalization or default values were assigned.
+ /// </summary>
+ IDictionary<string, string> IMessageOriginalPayload.OriginalPayload {
+ get { throw new NotImplementedException(); }
+ set { throw new NotImplementedException(); }
+ }
+ }
+}
diff --git a/src/DotNetOpenAuth/Messaging/MessageSerializer.cs b/src/DotNetOpenAuth/Messaging/MessageSerializer.cs
index ccda5d5..e1625b9 100644
--- a/src/DotNetOpenAuth/Messaging/MessageSerializer.cs
+++ b/src/DotNetOpenAuth/Messaging/MessageSerializer.cs
@@ -106,7 +106,13 @@ namespace DotNetOpenAuth.Messaging {
} catch (ArgumentException ex) {
throw ErrorUtilities.Wrap(ex, MessagingStrings.ErrorDeserializingMessage, this.messageType.Name);
}
+
messageDictionary.Message.EnsureValidMessage();
+
+ var originalPayloadMessage = messageDictionary.Message as IMessageOriginalPayload;
+ if (originalPayloadMessage != null) {
+ originalPayloadMessage.OriginalPayload = fields;
+ }
}
#if CONTRACTS_FULL
diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
index 85ba9a9..4b20ab8 100644
--- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
+++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs
@@ -444,9 +444,14 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentException>(copyFrom.CanRead);
MemoryStream copyTo = new MemoryStream(copyFrom.CanSeek ? (int)copyFrom.Length : 4 * 1024);
- copyFrom.CopyTo(copyTo);
- copyTo.Position = 0;
- return copyTo;
+ try {
+ copyFrom.CopyTo(copyTo);
+ copyTo.Position = 0;
+ return copyTo;
+ } catch {
+ copyTo.Dispose();
+ throw;
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs b/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs
index f9a5988..eff40dd 100644
--- a/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs
+++ b/src/DotNetOpenAuth/Messaging/MultipartPostPart.cs
@@ -40,10 +40,10 @@ namespace DotNetOpenAuth.Messaging {
}
/// <summary>
- /// Gets the content disposition.
+ /// Gets or sets the content disposition.
/// </summary>
/// <value>The content disposition.</value>
- public string ContentDisposition { get; private set; }
+ public string ContentDisposition { get; set; }
/// <summary>
/// Gets the key=value attributes that appear on the same line as the Content-Disposition.
@@ -103,9 +103,14 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentException>(value != null);
var part = new MultipartPostPart("form-data");
- part.ContentAttributes["name"] = name;
- part.Content = new MemoryStream(Encoding.UTF8.GetBytes(value));
- return part;
+ try {
+ part.ContentAttributes["name"] = name;
+ part.Content = new MemoryStream(Encoding.UTF8.GetBytes(value));
+ return part;
+ } catch {
+ part.Dispose();
+ throw;
+ }
}
/// <summary>
@@ -121,7 +126,13 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(contentType));
string fileName = Path.GetFileName(filePath);
- return CreateFormFilePart(name, fileName, contentType, File.OpenRead(filePath));
+ var fileStream = File.OpenRead(filePath);
+ try {
+ return CreateFormFilePart(name, fileName, contentType, fileStream);
+ } catch {
+ fileStream.Dispose();
+ throw;
+ }
}
/// <summary>
@@ -139,14 +150,20 @@ namespace DotNetOpenAuth.Messaging {
Contract.Requires<ArgumentException>(content != null);
var part = new MultipartPostPart("file");
- part.ContentAttributes["name"] = name;
- part.ContentAttributes["filename"] = fileName;
- part.PartHeaders[HttpRequestHeader.ContentType] = contentType;
- if (!contentType.StartsWith("text/", StringComparison.Ordinal)) {
- part.PartHeaders["Content-Transfer-Encoding"] = "binary";
+ try {
+ part.ContentAttributes["name"] = name;
+ part.ContentAttributes["filename"] = fileName;
+ part.PartHeaders[HttpRequestHeader.ContentType] = contentType;
+ if (!contentType.StartsWith("text/", StringComparison.Ordinal)) {
+ part.PartHeaders["Content-Transfer-Encoding"] = "binary";
+ }
+
+ part.Content = content;
+ return part;
+ } catch {
+ part.Dispose();
+ throw;
}
- part.Content = content;
- return part;
}
/// <summary>
diff --git a/src/DotNetOpenAuth/Messaging/NetworkDirectWebResponse.cs b/src/DotNetOpenAuth/Messaging/NetworkDirectWebResponse.cs
index 643cf81..800d2ba 100644
--- a/src/DotNetOpenAuth/Messaging/NetworkDirectWebResponse.cs
+++ b/src/DotNetOpenAuth/Messaging/NetworkDirectWebResponse.cs
@@ -109,6 +109,8 @@ namespace DotNetOpenAuth.Messaging {
this.httpWebResponse = null;
}
}
+
+ base.Dispose(disposing);
}
}
}
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs
index 125742c..26d088b 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessageDescriptionCollection.cs
@@ -33,6 +33,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
/// <param name="messageType">A type that implements <see cref="IMessage"/>.</param>
/// <param name="messageVersion">The protocol version of the message.</param>
/// <returns>A <see cref="MessageDescription"/> instance.</returns>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Assume(System.Boolean,System.String,System.String)", Justification = "No localization required.")]
[Pure]
internal MessageDescription Get(Type messageType, Version messageVersion) {
Contract.Requires<ArgumentNullException>(messageType != null);
diff --git a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
index b876ec4..088aa05 100644
--- a/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
+++ b/src/DotNetOpenAuth/Messaging/Reflection/MessagePart.cs
@@ -112,7 +112,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
/// The attribute discovered on <paramref name="member"/> that describes the
/// serialization requirements of the message part.
/// </param>
- [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "Code contracts requires it.")]
+ [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Unavoidable"), SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "Code contracts requires it.")]
internal MessagePart(MemberInfo member, MessagePartAttribute attribute) {
Contract.Requires<ArgumentNullException>(member != null);
Contract.Requires<ArgumentException>(member is FieldInfo || member is PropertyInfo);
@@ -295,6 +295,7 @@ namespace DotNetOpenAuth.Messaging.Reflection {
/// <param name="toString">The function to convert the custom type to a string.</param>
/// <param name="toOriginalString">The mapping function that converts some custom value to its original (non-normalized) string. May be null if the same as the <paramref name="toString"/> function.</param>
/// <param name="toValue">The function to convert a string to the custom type.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentNullException>(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "toString", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "toValue", Justification = "Code contracts")]
private static void Map<T>(Func<T, string> toString, Func<T, string> toOriginalString, Func<string, T> toValue) {
Contract.Requires<ArgumentNullException>(toString != null, "toString");
Contract.Requires<ArgumentNullException>(toValue != null, "toValue");
diff --git a/src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset b/src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset
index db238b6..0ba4e6e 100644
--- a/src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset
+++ b/src/DotNetOpenAuth/Migrated rules for DotNetOpenAuth.ruleset
@@ -5,6 +5,7 @@
<Rule Id="CA1054" Action="None" />
<Rule Id="CA1055" Action="None" />
<Rule Id="CA1056" Action="None" />
+ <Rule Id="CA1062" Action="None" />
<Rule Id="CA2104" Action="None" />
</Rules>
</RuleSet> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs b/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs
index ffde271..adde6b6 100644
--- a/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs
+++ b/src/DotNetOpenAuth/Mvc/OpenIdHelper.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.Mvc {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
@@ -35,10 +36,11 @@ namespace DotNetOpenAuth.Mvc {
Contract.Requires<ArgumentNullException>(html != null);
Contract.Ensures(Contract.Result<string>() != null);
- StringWriter result = new StringWriter();
- result.WriteStylesheetLink(OpenId.RelyingParty.OpenIdSelector.EmbeddedStylesheetResourceName);
- result.WriteStylesheetLink(OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedStylesheetResourceName);
- return result.ToString();
+ using (var result = new StringWriter(CultureInfo.CurrentCulture)) {
+ result.WriteStylesheetLink(OpenId.RelyingParty.OpenIdSelector.EmbeddedStylesheetResourceName);
+ result.WriteStylesheetLink(OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedStylesheetResourceName);
+ return result.ToString();
+ }
}
/// <summary>
@@ -59,43 +61,45 @@ namespace DotNetOpenAuth.Mvc {
/// <returns>
/// HTML that should be sent directly to the browser.
/// </returns>
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive")]
public static string OpenIdSelectorScripts(this HtmlHelper html, OpenIdSelector selectorOptions, OpenIdAjaxOptions additionalOptions) {
Contract.Requires<ArgumentNullException>(html != null);
Contract.Ensures(Contract.Result<string>() != null);
+ bool selectorOptionsOwned = false;
if (selectorOptions == null) {
+ selectorOptionsOwned = true;
selectorOptions = new OpenId.RelyingParty.OpenIdSelector();
}
+ try {
+ if (additionalOptions == null) {
+ additionalOptions = new OpenIdAjaxOptions();
+ }
- if (additionalOptions == null) {
- additionalOptions = new OpenIdAjaxOptions();
- }
-
- StringWriter result = new StringWriter();
-
- if (additionalOptions.ShowDiagnosticIFrame || additionalOptions.ShowDiagnosticTrace) {
- string scriptFormat = @"window.openid_visible_iframe = {0}; // causes the hidden iframe to show up
+ using (StringWriter result = new StringWriter(CultureInfo.CurrentCulture)) {
+ if (additionalOptions.ShowDiagnosticIFrame || additionalOptions.ShowDiagnosticTrace) {
+ string scriptFormat = @"window.openid_visible_iframe = {0}; // causes the hidden iframe to show up
window.openid_trace = {1}; // causes lots of messages";
- result.WriteScriptBlock(string.Format(
- CultureInfo.InvariantCulture,
- scriptFormat,
- additionalOptions.ShowDiagnosticIFrame ? "true" : "false",
- additionalOptions.ShowDiagnosticTrace ? "true" : "false"));
- }
- var scriptResources = new[] {
+ result.WriteScriptBlock(string.Format(
+ CultureInfo.InvariantCulture,
+ scriptFormat,
+ additionalOptions.ShowDiagnosticIFrame ? "true" : "false",
+ additionalOptions.ShowDiagnosticTrace ? "true" : "false"));
+ }
+ var scriptResources = new[] {
OpenIdRelyingPartyControlBase.EmbeddedJavascriptResource,
OpenIdRelyingPartyAjaxControlBase.EmbeddedAjaxJavascriptResource,
OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedScriptResourceName,
};
- result.WriteScriptTags(scriptResources);
+ result.WriteScriptTags(scriptResources);
- if (selectorOptions.DownloadYahooUILibrary) {
- result.WriteScriptTagsUrls(new[] { "https://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/yuiloader/yuiloader-min.js" });
- }
+ if (selectorOptions.DownloadYahooUILibrary) {
+ result.WriteScriptTagsUrls(new[] { "https://ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/yuiloader/yuiloader-min.js" });
+ }
- var blockBuilder = new StringWriter();
- if (selectorOptions.DownloadYahooUILibrary) {
- blockBuilder.WriteLine(@" try {
+ using (var blockBuilder = new StringWriter(CultureInfo.CurrentCulture)) {
+ if (selectorOptions.DownloadYahooUILibrary) {
+ blockBuilder.WriteLine(@" try {
if (YAHOO) {
var loader = new YAHOO.util.YUILoader({
require: ['button', 'menu'],
@@ -106,25 +110,25 @@ window.openid_trace = {1}; // causes lots of messages";
loader.insert();
}
} catch (e) { }");
- }
+ }
- blockBuilder.WriteLine("window.aspnetapppath = '{0}';", VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath));
+ blockBuilder.WriteLine("window.aspnetapppath = '{0}';", VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath));
- // Positive assertions can last no longer than this library is willing to consider them valid,
- // and when they come with OP private associations they last no longer than the OP is willing
- // to consider them valid. We assume the OP will hold them valid for at least five minutes.
- double assertionLifetimeInMilliseconds = Math.Min(TimeSpan.FromMinutes(5).TotalMilliseconds, Math.Min(DotNetOpenAuthSection.Configuration.OpenId.MaxAuthenticationTime.TotalMilliseconds, DotNetOpenAuthSection.Configuration.Messaging.MaximumMessageLifetime.TotalMilliseconds));
- blockBuilder.WriteLine(
- "{0} = {1};",
- OpenIdRelyingPartyAjaxControlBase.MaxPositiveAssertionLifetimeJsName,
- assertionLifetimeInMilliseconds.ToString(CultureInfo.InvariantCulture));
+ // Positive assertions can last no longer than this library is willing to consider them valid,
+ // and when they come with OP private associations they last no longer than the OP is willing
+ // to consider them valid. We assume the OP will hold them valid for at least five minutes.
+ double assertionLifetimeInMilliseconds = Math.Min(TimeSpan.FromMinutes(5).TotalMilliseconds, Math.Min(DotNetOpenAuthSection.Configuration.OpenId.MaxAuthenticationTime.TotalMilliseconds, DotNetOpenAuthSection.Configuration.Messaging.MaximumMessageLifetime.TotalMilliseconds));
+ blockBuilder.WriteLine(
+ "{0} = {1};",
+ OpenIdRelyingPartyAjaxControlBase.MaxPositiveAssertionLifetimeJsName,
+ assertionLifetimeInMilliseconds.ToString(CultureInfo.InvariantCulture));
- if (additionalOptions.PreloadedDiscoveryResults != null) {
- blockBuilder.WriteLine(additionalOptions.PreloadedDiscoveryResults);
- }
+ if (additionalOptions.PreloadedDiscoveryResults != null) {
+ blockBuilder.WriteLine(additionalOptions.PreloadedDiscoveryResults);
+ }
- string discoverUrl = VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath) + html.RouteCollection["OpenIdDiscover"].GetVirtualPath(html.ViewContext.RequestContext, new RouteValueDictionary(new { identifier = "xxx" })).VirtualPath;
- string blockFormat = @" {0} = function (argument, resultFunction, errorCallback) {{
+ string discoverUrl = VirtualPathUtility.AppendTrailingSlash(HttpContext.Current.Request.ApplicationPath) + html.RouteCollection["OpenIdDiscover"].GetVirtualPath(html.ViewContext.RequestContext, new RouteValueDictionary(new { identifier = "xxx" })).VirtualPath;
+ string blockFormat = @" {0} = function (argument, resultFunction, errorCallback) {{
jQuery.ajax({{
async: true,
dataType: 'text',
@@ -133,22 +137,22 @@ window.openid_trace = {1}; // causes lots of messages";
url: '{1}'.replace('xxx', encodeURIComponent(argument))
}});
}};";
- blockBuilder.WriteLine(blockFormat, OpenIdRelyingPartyAjaxControlBase.CallbackJSFunctionAsync, discoverUrl);
+ blockBuilder.WriteLine(blockFormat, OpenIdRelyingPartyAjaxControlBase.CallbackJSFunctionAsync, discoverUrl);
- blockFormat = @" window.postLoginAssertion = function (positiveAssertion) {{
+ blockFormat = @" window.postLoginAssertion = function (positiveAssertion) {{
$('#{0}')[0].setAttribute('value', positiveAssertion);
if ($('#{1}')[0] && !$('#{1}')[0].value) {{ // popups have no ReturnUrl predefined, but full page LogOn does.
$('#{1}')[0].setAttribute('value', window.parent.location.href);
}}
document.forms[{2}].submit();
}};";
- blockBuilder.WriteLine(
- blockFormat,
- additionalOptions.AssertionHiddenFieldId,
- additionalOptions.ReturnUrlHiddenFieldId,
- additionalOptions.FormKey);
+ blockBuilder.WriteLine(
+ blockFormat,
+ additionalOptions.AssertionHiddenFieldId,
+ additionalOptions.ReturnUrlHiddenFieldId,
+ additionalOptions.FormKey);
- blockFormat = @" $(function () {{
+ blockFormat = @" $(function () {{
var box = document.getElementsByName('openid_identifier')[0];
initAjaxOpenId(box, {0}, {1}, {2}, {3}, {4}, {5},
null, // js function to invoke on receiving a positive assertion
@@ -156,32 +160,41 @@ window.openid_trace = {1}; // causes lots of messages";
false, // auto postback
null); // PostBackEventReference (unused in MVC)
}});";
- blockBuilder.WriteLine(
- blockFormat,
- MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenIdTextBox.EmbeddedLogoResourceName)),
- MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedSpinnerResourceName)),
- MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName)),
- MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginFailureResourceName)),
- selectorOptions.Throttle,
- selectorOptions.Timeout.TotalMilliseconds,
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnText),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnToolTip),
- selectorOptions.TextBox.ShowLogOnPostBackButton ? "true" : "false",
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnPostBackToolTip),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.RetryText),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.RetryToolTip),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.BusyToolTip),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.IdentifierRequiredMessage),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnInProgressMessage),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticationSucceededToolTip),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticatedAsToolTip),
- MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticationFailedToolTip));
-
- result.WriteScriptBlock(blockBuilder.ToString());
- result.WriteScriptTags(OpenId.RelyingParty.OpenIdSelector.EmbeddedScriptResourceName);
-
- Reporting.RecordFeatureUse("MVC " + typeof(OpenIdSelector).Name);
- return result.ToString();
+ blockBuilder.WriteLine(
+ blockFormat,
+ MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenIdTextBox.EmbeddedLogoResourceName)),
+ MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedSpinnerResourceName)),
+ MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName)),
+ MessagingUtilities.GetSafeJavascriptValue(Util.GetWebResourceUrl(typeof(OpenIdRelyingPartyControlBase), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginFailureResourceName)),
+ selectorOptions.Throttle,
+ selectorOptions.Timeout.TotalMilliseconds,
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnText),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnToolTip),
+ selectorOptions.TextBox.ShowLogOnPostBackButton ? "true" : "false",
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnPostBackToolTip),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.RetryText),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.RetryToolTip),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.BusyToolTip),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.IdentifierRequiredMessage),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.LogOnInProgressMessage),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticationSucceededToolTip),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticatedAsToolTip),
+ MessagingUtilities.GetSafeJavascriptValue(selectorOptions.TextBox.AuthenticationFailedToolTip));
+
+ result.WriteScriptBlock(blockBuilder.ToString());
+ result.WriteScriptTags(OpenId.RelyingParty.OpenIdSelector.EmbeddedScriptResourceName);
+
+ Reporting.RecordFeatureUse("MVC " + typeof(OpenIdSelector).Name);
+ return result.ToString();
+ }
+ }
+ } catch {
+ if (selectorOptionsOwned) {
+ selectorOptions.Dispose();
+ }
+
+ throw;
+ }
}
/// <summary>
@@ -227,40 +240,42 @@ window.openid_trace = {1}; // causes lots of messages";
/// <returns>
/// HTML that should be sent directly to the browser.
/// </returns>
+ [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Not a problem for this type.")]
public static string OpenIdSelector(this HtmlHelper html, params SelectorButton[] buttons) {
Contract.Requires<ArgumentNullException>(html != null);
Contract.Requires<ArgumentNullException>(buttons != null);
Contract.Ensures(Contract.Result<string>() != null);
- var writer = new StringWriter();
- var h = new HtmlTextWriter(writer);
+ using (var writer = new StringWriter(CultureInfo.CurrentCulture)) {
+ using (var h = new HtmlTextWriter(writer)) {
+ h.AddAttribute(HtmlTextWriterAttribute.Class, "OpenIdProviders");
+ h.RenderBeginTag(HtmlTextWriterTag.Ul);
- h.AddAttribute(HtmlTextWriterAttribute.Class, "OpenIdProviders");
- h.RenderBeginTag(HtmlTextWriterTag.Ul);
+ foreach (SelectorButton button in buttons) {
+ var op = button as SelectorProviderButton;
+ if (op != null) {
+ h.Write(OpenIdSelectorOPButton(html, op.OPIdentifier, op.Image));
+ continue;
+ }
- foreach (SelectorButton button in buttons) {
- var op = button as SelectorProviderButton;
- if (op != null) {
- h.Write(OpenIdSelectorOPButton(html, op.OPIdentifier, op.Image));
- continue;
- }
+ var openid = button as SelectorOpenIdButton;
+ if (openid != null) {
+ h.Write(OpenIdSelectorOpenIdButton(html, openid.Image));
+ continue;
+ }
- var openid = button as SelectorOpenIdButton;
- if (openid != null) {
- h.Write(OpenIdSelectorOpenIdButton(html, openid.Image));
- continue;
- }
+ ErrorUtilities.VerifySupported(false, "The {0} button is not yet supported for MVC.", button.GetType().Name);
+ }
- ErrorUtilities.VerifySupported(false, "The {0} button is not yet supported for MVC.", button.GetType().Name);
- }
+ h.RenderEndTag(); // ul
- h.RenderEndTag(); // ul
+ if (buttons.OfType<SelectorOpenIdButton>().Any()) {
+ h.Write(OpenIdAjaxTextBox(html));
+ }
+ }
- if (buttons.OfType<SelectorOpenIdButton>().Any()) {
- h.Write(OpenIdAjaxTextBox(html));
+ return writer.ToString();
}
-
- return writer.ToString();
}
/// <summary>
@@ -271,6 +286,7 @@ window.openid_trace = {1}; // causes lots of messages";
/// <returns>
/// HTML that should be sent directly to the browser.
/// </returns>
+ [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "html", Justification = "Breaking change, and it's an extension method so it's useful.")]
public static string OpenIdAjaxTextBox(this HtmlHelper html) {
return @"<div style='display: none' id='OpenIDForm'>
<span class='OpenIdAjaxTextBox' style='display: inline-block; position: relative; font-size: 16px'>
@@ -289,48 +305,50 @@ window.openid_trace = {1}; // causes lots of messages";
/// <returns>
/// HTML that should be sent directly to the browser.
/// </returns>
+ [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Not a problem for this type.")]
private static string OpenIdSelectorButton(this HtmlHelper html, string id, string cssClass, string imageUrl) {
Contract.Requires<ArgumentNullException>(html != null);
Contract.Requires<ArgumentNullException>(id != null);
Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(imageUrl));
Contract.Ensures(Contract.Result<string>() != null);
- var writer = new StringWriter();
- var h = new HtmlTextWriter(writer);
-
- h.AddAttribute(HtmlTextWriterAttribute.Id, id);
- if (!string.IsNullOrEmpty(cssClass)) {
- h.AddAttribute(HtmlTextWriterAttribute.Class, cssClass);
- }
- h.RenderBeginTag(HtmlTextWriterTag.Li);
+ using (var writer = new StringWriter(CultureInfo.CurrentCulture)) {
+ using (var h = new HtmlTextWriter(writer)) {
+ h.AddAttribute(HtmlTextWriterAttribute.Id, id);
+ if (!string.IsNullOrEmpty(cssClass)) {
+ h.AddAttribute(HtmlTextWriterAttribute.Class, cssClass);
+ }
+ h.RenderBeginTag(HtmlTextWriterTag.Li);
- h.AddAttribute(HtmlTextWriterAttribute.Href, "#");
- h.RenderBeginTag(HtmlTextWriterTag.A);
+ h.AddAttribute(HtmlTextWriterAttribute.Href, "#");
+ h.RenderBeginTag(HtmlTextWriterTag.A);
- h.RenderBeginTag(HtmlTextWriterTag.Div);
- h.RenderBeginTag(HtmlTextWriterTag.Div);
+ h.RenderBeginTag(HtmlTextWriterTag.Div);
+ h.RenderBeginTag(HtmlTextWriterTag.Div);
- h.AddAttribute(HtmlTextWriterAttribute.Src, imageUrl);
- h.RenderBeginTag(HtmlTextWriterTag.Img);
- h.RenderEndTag();
+ h.AddAttribute(HtmlTextWriterAttribute.Src, imageUrl);
+ h.RenderBeginTag(HtmlTextWriterTag.Img);
+ h.RenderEndTag();
- h.AddAttribute(HtmlTextWriterAttribute.Src, Util.GetWebResourceUrl(typeof(OpenIdSelector), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName));
- h.AddAttribute(HtmlTextWriterAttribute.Class, "loginSuccess");
- h.AddAttribute(HtmlTextWriterAttribute.Title, "Authenticated as {0}");
- h.RenderBeginTag(HtmlTextWriterTag.Img);
- h.RenderEndTag();
+ h.AddAttribute(HtmlTextWriterAttribute.Src, Util.GetWebResourceUrl(typeof(OpenIdSelector), OpenId.RelyingParty.OpenIdAjaxTextBox.EmbeddedLoginSuccessResourceName));
+ h.AddAttribute(HtmlTextWriterAttribute.Class, "loginSuccess");
+ h.AddAttribute(HtmlTextWriterAttribute.Title, "Authenticated as {0}");
+ h.RenderBeginTag(HtmlTextWriterTag.Img);
+ h.RenderEndTag();
- h.RenderEndTag(); // div
+ h.RenderEndTag(); // div
- h.AddAttribute(HtmlTextWriterAttribute.Class, "ui-widget-overlay");
- h.RenderBeginTag(HtmlTextWriterTag.Div);
- h.RenderEndTag(); // div
+ h.AddAttribute(HtmlTextWriterAttribute.Class, "ui-widget-overlay");
+ h.RenderBeginTag(HtmlTextWriterTag.Div);
+ h.RenderEndTag(); // div
- h.RenderEndTag(); // div
- h.RenderEndTag(); // a
- h.RenderEndTag(); // li
+ h.RenderEndTag(); // div
+ h.RenderEndTag(); // a
+ h.RenderEndTag(); // li
+ }
- return writer.ToString();
+ return writer.ToString();
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/HmacSha1SigningBindingElement.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/HmacSha1SigningBindingElement.cs
index 53930bc..5828428 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/HmacSha1SigningBindingElement.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/HmacSha1SigningBindingElement.cs
@@ -32,10 +32,11 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// </remarks>
protected override string GetSignature(ITamperResistantOAuthMessage message) {
string key = GetConsumerAndTokenSecretString(message);
- HashAlgorithm hasher = new HMACSHA1(Encoding.ASCII.GetBytes(key));
- string baseString = ConstructSignatureBaseString(message, this.Channel.MessageDescriptions.GetAccessor(message));
- byte[] digest = hasher.ComputeHash(Encoding.ASCII.GetBytes(baseString));
- return Convert.ToBase64String(digest);
+ using (HashAlgorithm hasher = new HMACSHA1(Encoding.ASCII.GetBytes(key))) {
+ string baseString = ConstructSignatureBaseString(message, this.Channel.MessageDescriptions.GetAccessor(message));
+ byte[] digest = hasher.ComputeHash(Encoding.ASCII.GetBytes(baseString));
+ return Convert.ToBase64String(digest);
+ }
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/ITamperResistantOAuthMessage.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/ITamperResistantOAuthMessage.cs
index ff6d6e9..a95001d 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/ITamperResistantOAuthMessage.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/ITamperResistantOAuthMessage.cs
@@ -13,7 +13,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <summary>
/// An interface that OAuth messages implement to support signing.
/// </summary>
- public interface ITamperResistantOAuthMessage : IDirectedProtocolMessage, ITamperResistantProtocolMessage {
+ public interface ITamperResistantOAuthMessage : IDirectedProtocolMessage, ITamperResistantProtocolMessage, IMessageOriginalPayload {
/// <summary>
/// Gets or sets the method used to sign the message.
/// </summary>
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
index e6cfb78..2b1bea5 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
using System;
using System.Collections.Generic;
using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
@@ -32,6 +33,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <param name="store">The web application store to use for nonces.</param>
/// <param name="tokenManager">The token manager instance to use.</param>
/// <param name="securitySettings">The security settings.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentNullException>(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "securitySettings", Justification = "Code contracts")]
internal OAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store, IConsumerTokenManager tokenManager, ConsumerSecuritySettings securitySettings)
: this(
signingBindingElement,
@@ -52,6 +54,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <param name="store">The web application store to use for nonces.</param>
/// <param name="tokenManager">The token manager instance to use.</param>
/// <param name="securitySettings">The security settings.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentNullException>(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "securitySettings", Justification = "Code contracts")]
internal OAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store, IServiceProviderTokenManager tokenManager, ServiceProviderSecuritySettings securitySettings)
: this(
signingBindingElement,
@@ -75,6 +78,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <param name="messageTypeProvider">An injected message type provider instance.
/// Except for mock testing, this should always be one of
/// <see cref="OAuthConsumerMessageFactory"/> or <see cref="OAuthServiceProviderMessageFactory"/>.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentNullException>(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "securitySettings", Justification = "Code contracts")]
internal OAuthChannel(ITamperProtectionChannelBindingElement signingBindingElement, INonceStore store, ITokenManager tokenManager, SecuritySettings securitySettings, IMessageFactory messageTypeProvider)
: base(messageTypeProvider, InitializeBindingElements(signingBindingElement, store, tokenManager, securitySettings)) {
Contract.Requires<ArgumentNullException>(tokenManager != null);
@@ -292,8 +296,9 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
};
var spTokenManager = tokenManager as IServiceProviderTokenManager;
- if (spTokenManager != null) {
- bindingElements.Insert(0, new TokenHandlingBindingElement(spTokenManager, (ServiceProviderSecuritySettings)securitySettings));
+ var serviceProviderSecuritySettings = securitySettings as ServiceProviderSecuritySettings;
+ if (spTokenManager != null && serviceProviderSecuritySettings != null) {
+ bindingElements.Insert(0, new TokenHandlingBindingElement(spTokenManager, serviceProviderSecuritySettings));
}
return bindingElements.ToArray();
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
index cb81139..31b5149 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/SigningBindingElementBase.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
@@ -148,6 +149,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// <remarks>
/// This method implements OAuth 1.0 section 9.1.
/// </remarks>
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Unavoidable")]
internal static string ConstructSignatureBaseString(ITamperResistantOAuthMessage message, MessageDictionary messageDictionary) {
Contract.Requires<ArgumentNullException>(message != null);
Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(message.HttpMethod));
@@ -175,6 +177,13 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
partsToInclude = messageDictionary;
}
+ // If this message was deserialized, include only those explicitly included message parts (excludes defaulted values)
+ // in the signature.
+ var originalPayloadMessage = (IMessageOriginalPayload)message;
+ if (originalPayloadMessage.OriginalPayload != null) {
+ partsToInclude = partsToInclude.Where(pair => originalPayloadMessage.OriginalPayload.ContainsKey(pair.Key));
+ }
+
foreach (var pair in OAuthChannel.GetUriEscapedParameters(partsToInclude)) {
encodedDictionary[pair.Key] = pair.Value;
}
diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
index 329f8c4..bfebd8b 100644
--- a/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
+++ b/src/DotNetOpenAuth/OAuth/ChannelElements/TokenHandlingBindingElement.cs
@@ -7,6 +7,7 @@
namespace DotNetOpenAuth.OAuth.ChannelElements {
using System;
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
@@ -34,6 +35,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements {
/// </summary>
/// <param name="tokenManager">The token manager.</param>
/// <param name="securitySettings">The security settings.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentNullException>(System.Boolean,System.String,System.String)", Justification = "Code contract"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "securitySettings", Justification = "Code contracts")]
internal TokenHandlingBindingElement(IServiceProviderTokenManager tokenManager, ServiceProviderSecuritySettings securitySettings) {
Contract.Requires<ArgumentNullException>(tokenManager != null);
Contract.Requires<ArgumentNullException>(securitySettings != null, "securitySettings");
diff --git a/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs b/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs
index 57ce470..6084fc0 100644
--- a/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs
+++ b/src/DotNetOpenAuth/OAuth/Messages/SignedMessageBase.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.OAuth.Messages {
using System;
+ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.Messaging.Bindings;
@@ -131,6 +132,24 @@ namespace DotNetOpenAuth.OAuth.Messages {
#endregion
+ #region IMessageOriginalPayload Members
+
+ /// <summary>
+ /// Gets or sets the original message parts, before any normalization or default values were assigned.
+ /// </summary>
+ IDictionary<string, string> IMessageOriginalPayload.OriginalPayload {
+ get { return this.OriginalPayload; }
+ set { this.OriginalPayload = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the original message parts, before any normalization or default values were assigned.
+ /// </summary>
+ [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "By design")]
+ protected IDictionary<string, string> OriginalPayload { get; set; }
+
+ #endregion
+
/// <summary>
/// Gets or sets the signature method used to sign the request.
/// </summary>
diff --git a/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs b/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs
index fb4c9a1..723839d 100644
--- a/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs
+++ b/src/DotNetOpenAuth/OAuth/OAuthStrings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:4.0.30104.0
+// Runtime Version:4.0.30319.225
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/src/DotNetOpenAuth/OAuth/Protocol.cs b/src/DotNetOpenAuth/OAuth/Protocol.cs
index a524ba7..6eecd8e 100644
--- a/src/DotNetOpenAuth/OAuth/Protocol.cs
+++ b/src/DotNetOpenAuth/OAuth/Protocol.cs
@@ -83,7 +83,7 @@ namespace DotNetOpenAuth.OAuth {
internal static readonly List<Protocol> AllVersions = new List<Protocol>() { V10a, V10 };
/// <summary>
- /// The default (or most recent) supported version of the OpenID protocol.
+ /// The default (or most recent) supported version of the OAuth protocol.
/// </summary>
internal static readonly Protocol Default = AllVersions[0];
diff --git a/src/DotNetOpenAuth/OAuth/ServiceProvider.cs b/src/DotNetOpenAuth/OAuth/ServiceProvider.cs
index fda895e..ec9206e 100644
--- a/src/DotNetOpenAuth/OAuth/ServiceProvider.cs
+++ b/src/DotNetOpenAuth/OAuth/ServiceProvider.cs
@@ -341,7 +341,7 @@ namespace DotNetOpenAuth.OAuth {
Contract.Requires<ArgumentException>((consumerKey == null) == (scope == null));
Contract.Requires<InvalidOperationException>(this.TokenManager is ICombinedOpenIdProviderTokenManager);
var openidTokenManager = (ICombinedOpenIdProviderTokenManager)this.TokenManager;
- ErrorUtilities.VerifyArgument(consumerKey == null || consumerKey == openidTokenManager.GetConsumerKey(openIdAuthenticationRequest.Realm), "The consumer key and the realm did not match according to the token manager.");
+ ErrorUtilities.VerifyArgument(consumerKey == null || consumerKey == openidTokenManager.GetConsumerKey(openIdAuthenticationRequest.Realm), OAuthStrings.OpenIdOAuthRealmConsumerKeyDoNotMatch);
this.AttachAuthorizationResponse(openIdAuthenticationRequest, scope);
}
diff --git a/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs b/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs
index 3afd44e..a6560d8 100644
--- a/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs
+++ b/src/DotNetOpenAuth/OAuth/VerificationCodeFormat.cs
@@ -37,6 +37,7 @@ namespace DotNetOpenAuth.OAuth {
/// </remarks>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Alikes", Justification = "Breaking change of existing API")]
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "AlphaNumeric", Justification = "Breaking change of existing API")]
+ [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "LookAlikes", Justification = "Breaking change of existing API")]
AlphaNumericNoLookAlikes,
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/ChannelElements/KeyValueFormEncoding.cs b/src/DotNetOpenAuth/OpenId/ChannelElements/KeyValueFormEncoding.cs
index c363c11..46c2139 100644
--- a/src/DotNetOpenAuth/OpenId/ChannelElements/KeyValueFormEncoding.cs
+++ b/src/DotNetOpenAuth/OpenId/ChannelElements/KeyValueFormEncoding.cs
@@ -99,27 +99,30 @@ namespace DotNetOpenAuth.OpenId.ChannelElements {
/// If ordering of the key=value pairs is important, a deterministic enumerator must
/// be used.
/// </remarks>
+ [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Not a problem for this type.")]
public static byte[] GetBytes(IEnumerable<KeyValuePair<string, string>> keysAndValues) {
Contract.Requires<ArgumentNullException>(keysAndValues != null);
- MemoryStream ms = new MemoryStream();
- using (StreamWriter sw = new StreamWriter(ms, textEncoding)) {
- sw.NewLine = NewLineCharacters;
- foreach (var pair in keysAndValues) {
- if (pair.Key.IndexOfAny(IllegalKeyCharacters) >= 0) {
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, OpenIdStrings.InvalidCharacterInKeyValueFormInput, pair.Key));
- }
- if (pair.Value.IndexOfAny(IllegalValueCharacters) >= 0) {
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, OpenIdStrings.InvalidCharacterInKeyValueFormInput, pair.Value));
- }
+ using (MemoryStream ms = new MemoryStream()) {
+ using (StreamWriter sw = new StreamWriter(ms, textEncoding)) {
+ sw.NewLine = NewLineCharacters;
+ foreach (var pair in keysAndValues) {
+ if (pair.Key.IndexOfAny(IllegalKeyCharacters) >= 0) {
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, OpenIdStrings.InvalidCharacterInKeyValueFormInput, pair.Key));
+ }
+ if (pair.Value.IndexOfAny(IllegalValueCharacters) >= 0) {
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, OpenIdStrings.InvalidCharacterInKeyValueFormInput, pair.Value));
+ }
- sw.Write(pair.Key);
- sw.Write(':');
- sw.Write(pair.Value);
- sw.WriteLine();
+ sw.Write(pair.Key);
+ sw.Write(':');
+ sw.Write(pair.Value);
+ sw.WriteLine();
+ }
}
+
+ return ms.ToArray();
}
- return ms.ToArray();
}
/// <summary>
diff --git a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
index 55c2dc5..df36b5e 100644
--- a/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Extensions/UI/UIRequest.cs
@@ -31,7 +31,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.UI {
/// <see cref="IdentifierDiscoveryResult.IsExtensionSupported&lt;T&gt;()"/> method.</para>
/// </remarks>
[Serializable]
- public sealed class UIRequest : IOpenIdMessageExtension, IMessageWithEvents {
+ public class UIRequest : IOpenIdMessageExtension, IMessageWithEvents {
/// <summary>
/// The factory method that may be used in deserialization of this message.
/// </summary>
diff --git a/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs b/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs
index ba9852e..215ea24 100644
--- a/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs
+++ b/src/DotNetOpenAuth/OpenId/HostMetaDiscoveryService.cs
@@ -212,6 +212,7 @@ namespace DotNetOpenAuth.OpenId {
/// <param name="response">The response.</param>
/// <param name="signingHost">The host name on the certificate that should be used to verify the signature in the XRDS.</param>
/// <exception cref="ProtocolException">Thrown if the XRDS document has an invalid or a missing signature.</exception>
+ [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "XmlDSig", Justification = "xml")]
private static void ValidateXmlDSig(XrdsDocument document, UriIdentifier identifier, IncomingWebResponse response, string signingHost) {
Contract.Requires<ArgumentNullException>(document != null);
Contract.Requires<ArgumentNullException>(identifier != null);
@@ -223,10 +224,10 @@ namespace DotNetOpenAuth.OpenId {
ErrorUtilities.VerifyProtocol(signedInfoNode != null, OpenIdStrings.MissingElement, "SignedInfo");
ErrorUtilities.VerifyProtocol(
signedInfoNode.SelectSingleNode("ds:CanonicalizationMethod[@Algorithm='http://docs.oasis-open.org/xri/xrd/2009/01#canonicalize-raw-octets']", document.XmlNamespaceResolver) != null,
- "Unrecognized or missing canonicalization method.");
+ OpenIdStrings.UnsupportedCanonicalizationMethod);
ErrorUtilities.VerifyProtocol(
signedInfoNode.SelectSingleNode("ds:SignatureMethod[@Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1']", document.XmlNamespaceResolver) != null,
- "Unrecognized or missing signature method.");
+ OpenIdStrings.UnsupportedSignatureMethod);
var certNodes = signatureNode.Select("ds:KeyInfo/ds:X509Data/ds:X509Certificate", document.XmlNamespaceResolver);
ErrorUtilities.VerifyProtocol(certNodes.Count > 0, OpenIdStrings.MissingElement, "X509Certificate");
var certs = certNodes.Cast<XPathNavigator>().Select(n => new X509Certificate2(Convert.FromBase64String(n.Value.Trim()))).ToList();
@@ -249,7 +250,7 @@ namespace DotNetOpenAuth.OpenId {
// Verify that the certificate is issued to the host on whom we are performing discovery.
string hostName = certs[0].GetNameInfo(X509NameType.DnsName, false);
- ErrorUtilities.VerifyProtocol(string.Equals(hostName, signingHost, StringComparison.OrdinalIgnoreCase), "X.509 signing certificate issued to {0}, but a certificate for {1} was expected.", hostName, signingHost);
+ ErrorUtilities.VerifyProtocol(string.Equals(hostName, signingHost, StringComparison.OrdinalIgnoreCase), OpenIdStrings.MisdirectedSigningCertificate, hostName, signingHost);
// Verify the signature itself
byte[] signature = Convert.FromBase64String(response.Headers["Signature"]);
@@ -257,7 +258,7 @@ namespace DotNetOpenAuth.OpenId {
byte[] data = new byte[response.ResponseStream.Length];
response.ResponseStream.Seek(0, SeekOrigin.Begin);
response.ResponseStream.Read(data, 0, data.Length);
- ErrorUtilities.VerifyProtocol(provider.VerifyData(data, "SHA1", signature), "Invalid XmlDSig signature on XRDS document.");
+ ErrorUtilities.VerifyProtocol(provider.VerifyData(data, "SHA1", signature), OpenIdStrings.InvalidDSig);
}
/// <summary>
@@ -271,7 +272,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")]
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "DotNetOpenAuth.Messaging.ErrorUtilities.ThrowProtocol(System.String,System.Object[])", Justification = "The localized portion is a string resource already."), SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "By design")]
private static void VerifyCertChain(List<X509Certificate2> certs) {
var chain = new X509Chain();
foreach (var cert in certs) {
diff --git a/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs
index ccfb1b8..a4fdf49 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/AssociateDiffieHellmanResponse.cs
@@ -53,7 +53,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// </remarks>
protected override Association CreateAssociationAtRelyingParty(AssociateRequest request) {
var diffieHellmanRequest = request as AssociateDiffieHellmanRequest;
- ErrorUtilities.VerifyArgument(diffieHellmanRequest != null, "request");
+ ErrorUtilities.VerifyArgument(diffieHellmanRequest != null, OpenIdStrings.DiffieHellmanAssociationRequired);
HashAlgorithm hasher = DiffieHellmanUtilities.Lookup(Protocol, this.SessionType);
byte[] associationSecret = DiffieHellmanUtilities.SHAHashXorSecret(hasher, diffieHellmanRequest.Algorithm, this.DiffieHellmanServerPublic, this.EncodedMacKey);
@@ -86,14 +86,14 @@ namespace DotNetOpenAuth.OpenId.Messages {
// that will be transmitted to the Relying Party. The RP will perform an inverse operation
// using its part of a DH secret in order to decrypt the shared secret we just invented
// above when we created the association.
- DiffieHellman dh = new DiffieHellmanManaged(
+ using (DiffieHellman dh = new DiffieHellmanManaged(
diffieHellmanRequest.DiffieHellmanModulus ?? AssociateDiffieHellmanRequest.DefaultMod,
diffieHellmanRequest.DiffieHellmanGen ?? AssociateDiffieHellmanRequest.DefaultGen,
- AssociateDiffieHellmanRequest.DefaultX);
- HashAlgorithm hasher = DiffieHellmanUtilities.Lookup(this.Protocol, this.SessionType);
- this.DiffieHellmanServerPublic = DiffieHellmanUtilities.EnsurePositive(dh.CreateKeyExchange());
- this.EncodedMacKey = DiffieHellmanUtilities.SHAHashXorSecret(hasher, dh, diffieHellmanRequest.DiffieHellmanConsumerPublic, association.SecretKey);
-
+ AssociateDiffieHellmanRequest.DefaultX)) {
+ HashAlgorithm hasher = DiffieHellmanUtilities.Lookup(this.Protocol, this.SessionType);
+ this.DiffieHellmanServerPublic = DiffieHellmanUtilities.EnsurePositive(dh.CreateKeyExchange());
+ this.EncodedMacKey = DiffieHellmanUtilities.SHAHashXorSecret(hasher, dh, diffieHellmanRequest.DiffieHellmanConsumerPublic, association.SecretKey);
+ }
return association;
}
}
diff --git a/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs b/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs
index d53b9d0..fce6028 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/IndirectResponseBase.cs
@@ -16,7 +16,12 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// A common base class from which indirect response messages should derive.
/// </summary>
[Serializable]
- internal class IndirectResponseBase : RequestBase {
+ internal class IndirectResponseBase : RequestBase, IProtocolMessageWithExtensions {
+ /// <summary>
+ /// Backing store for the <see cref="Extensions"/> property.
+ /// </summary>
+ private IList<IExtensionMessage> extensions = new List<IExtensionMessage>();
+
/// <summary>
/// Initializes a new instance of the <see cref="IndirectResponseBase"/> class.
/// </summary>
@@ -42,6 +47,35 @@ namespace DotNetOpenAuth.OpenId.Messages {
: base(version, relyingPartyReturnTo, mode, MessageTransport.Indirect) {
}
+ #region IProtocolMessageWithExtensions Members
+
+ /// <summary>
+ /// Gets the list of extensions that are included with this message.
+ /// </summary>
+ /// <value></value>
+ /// <remarks>
+ /// Implementations of this interface should ensure that this property never returns null.
+ /// </remarks>
+ public IList<IExtensionMessage> Extensions {
+ get { return this.extensions; }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Gets the signed extensions on this message.
+ /// </summary>
+ internal IEnumerable<IOpenIdMessageExtension> SignedExtensions {
+ get { return this.extensions.OfType<IOpenIdMessageExtension>().Where(ext => ext.IsSignedByRemoteParty); }
+ }
+
+ /// <summary>
+ /// Gets the unsigned extensions on this message.
+ /// </summary>
+ internal IEnumerable<IOpenIdMessageExtension> UnsignedExtensions {
+ get { return this.extensions.OfType<IOpenIdMessageExtension>().Where(ext => !ext.IsSignedByRemoteParty); }
+ }
+
/// <summary>
/// Gets the originating request message, if applicable.
/// </summary>
diff --git a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
index 776b28b..baeae16 100644
--- a/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/Messages/IndirectSignedResponse.cs
@@ -26,7 +26,7 @@ namespace DotNetOpenAuth.OpenId.Messages {
/// </summary>
[DebuggerDisplay("OpenID {Version} {Mode} (no id assertion)")]
[Serializable]
- internal class IndirectSignedResponse : IndirectResponseBase, ITamperResistantOpenIdMessage, IProtocolMessageWithExtensions {
+ internal class IndirectSignedResponse : IndirectResponseBase, ITamperResistantOpenIdMessage {
/// <summary>
/// The allowed date/time formats for the response_nonce parameter.
/// </summary>
@@ -36,11 +36,6 @@ namespace DotNetOpenAuth.OpenId.Messages {
private static readonly string[] PermissibleDateTimeFormats = { "yyyy-MM-ddTHH:mm:ssZ" };
/// <summary>
- /// Backing store for the <see cref="Extensions"/> property.
- /// </summary>
- private IList<IExtensionMessage> extensions = new List<IExtensionMessage>();
-
- /// <summary>
/// Backing field for the <see cref="IExpiringProtocolMessage.UtcCreationDate"/> property.
/// </summary>
/// <remarks>
@@ -104,21 +99,6 @@ namespace DotNetOpenAuth.OpenId.Messages {
this.ReturnTo = relyingPartyReturnTo;
}
- #region IProtocolMessageWithExtensions Members
-
- /// <summary>
- /// Gets the list of extensions that are included with this message.
- /// </summary>
- /// <value></value>
- /// <remarks>
- /// Implementations of this interface should ensure that this property never returns null.
- /// </remarks>
- public IList<IExtensionMessage> Extensions {
- get { return this.extensions; }
- }
-
- #endregion
-
/// <summary>
/// Gets the level of protection this message requires.
/// </summary>
@@ -241,20 +221,6 @@ namespace DotNetOpenAuth.OpenId.Messages {
internal bool ReturnToParametersSignatureValidated { get; set; }
/// <summary>
- /// Gets the signed extensions on this message.
- /// </summary>
- internal IEnumerable<IOpenIdMessageExtension> SignedExtensions {
- get { return this.extensions.OfType<IOpenIdMessageExtension>().Where(ext => ext.IsSignedByRemoteParty); }
- }
-
- /// <summary>
- /// Gets the unsigned extensions on this message.
- /// </summary>
- internal IEnumerable<IOpenIdMessageExtension> UnsignedExtensions {
- get { return this.extensions.OfType<IOpenIdMessageExtension>().Where(ext => !ext.IsSignedByRemoteParty); }
- }
-
- /// <summary>
/// Gets or sets the nonce that will protect the message from replay attacks.
/// </summary>
/// <value>
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs b/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
index 43283ac..f45af93 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
+++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
-// Runtime Version:4.0.30319.1
+// Runtime Version:4.0.30319.225
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -250,6 +250,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to The associate request instance must be a Diffie-Hellman instance..
+ /// </summary>
+ internal static string DiffieHellmanAssociationRequired {
+ get {
+ return ResourceManager.GetString("DiffieHellmanAssociationRequired", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The following properties must be set before the Diffie-Hellman algorithm can generate a public key: {0}.
/// </summary>
internal static string DiffieHellmanRequiredPropertiesNotSet {
@@ -349,6 +358,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to Invalid XmlDSig signature on XRDS document..
+ /// </summary>
+ internal static string InvalidDSig {
+ get {
+ return ResourceManager.GetString("InvalidDSig", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Cannot decode Key-Value Form because a line was found without a &apos;{0}&apos; character. (line {1}: &apos;{2}&apos;).
/// </summary>
internal static string InvalidKeyValueFormCharacterMissing {
@@ -425,6 +443,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to X.509 signing certificate issued to {0}, but a certificate for {1} was expected..
+ /// </summary>
+ internal static string MisdirectedSigningCertificate {
+ get {
+ return ResourceManager.GetString("MisdirectedSigningCertificate", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Missing {0} element..
/// </summary>
internal static string MissingElement {
@@ -524,11 +551,20 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
- /// Looks up a localized string similar to An positive OpenID assertion was received from OP endpoint {0} that is not on this relying party&apos;s whitelist..
+ /// Looks up a localized string similar to OpenID popup window or iframe did not recognize an OpenID response in the request..
/// </summary>
- internal static string PositiveAssertionFromNonWhitelistedProvider {
+ internal static string PopupRedirectMissingResponse {
get {
- return ResourceManager.GetString("PositiveAssertionFromNonWhitelistedProvider", resourceCulture);
+ return ResourceManager.GetString("PopupRedirectMissingResponse", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to An positive OpenID assertion was received from OP endpoint {0} and was rejected based on this site&apos;s security settings..
+ /// </summary>
+ internal static string PositiveAssertionFromNonQualifiedProvider {
+ get {
+ return ResourceManager.GetString("PositiveAssertionFromNonQualifiedProvider", resourceCulture);
}
}
@@ -722,6 +758,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to Unrecognized or missing canonicalization method..
+ /// </summary>
+ internal static string UnsupportedCanonicalizationMethod {
+ get {
+ return ResourceManager.GetString("UnsupportedCanonicalizationMethod", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to This feature is unavailable due to an unrecognized channel configuration..
/// </summary>
internal static string UnsupportedChannelConfiguration {
@@ -731,6 +776,15 @@ namespace DotNetOpenAuth.OpenId {
}
/// <summary>
+ /// Looks up a localized string similar to Unrecognized or missing signature method..
+ /// </summary>
+ internal static string UnsupportedSignatureMethod {
+ get {
+ return ResourceManager.GetString("UnsupportedSignatureMethod", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to The openid.user_setup_url parameter is required when sending negative assertion messages in response to immediate mode requests..
/// </summary>
internal static string UserSetupUrlRequiredInImmediateNegativeResponse {
diff --git a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
index fab03a9..b700d76 100644
--- a/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
+++ b/src/DotNetOpenAuth/OpenId/OpenIdStrings.resx
@@ -337,8 +337,8 @@ Discovered endpoint info:
<data name="BadExtension" xml:space="preserve">
<value>The {0} extension failed to deserialize and will be skipped. {1}</value>
</data>
- <data name="PositiveAssertionFromNonWhitelistedProvider" xml:space="preserve">
- <value>An positive OpenID assertion was received from OP endpoint {0} that is not on this relying party's whitelist.</value>
+ <data name="PositiveAssertionFromNonQualifiedProvider" xml:space="preserve">
+ <value>An positive OpenID assertion was received from OP endpoint {0} and was rejected based on this site's security settings.</value>
</data>
<data name="HeadTagMustIncludeRunatServer" xml:space="preserve">
<value>The HTML head tag must include runat="server".</value>
@@ -355,4 +355,22 @@ Discovered endpoint info:
<data name="MissingElement" xml:space="preserve">
<value>Missing {0} element.</value>
</data>
+ <data name="DiffieHellmanAssociationRequired" xml:space="preserve">
+ <value>The associate request instance must be a Diffie-Hellman instance.</value>
+ </data>
+ <data name="InvalidDSig" xml:space="preserve">
+ <value>Invalid XmlDSig signature on XRDS document.</value>
+ </data>
+ <data name="MisdirectedSigningCertificate" xml:space="preserve">
+ <value>X.509 signing certificate issued to {0}, but a certificate for {1} was expected.</value>
+ </data>
+ <data name="PopupRedirectMissingResponse" xml:space="preserve">
+ <value>OpenID popup window or iframe did not recognize an OpenID response in the request.</value>
+ </data>
+ <data name="UnsupportedCanonicalizationMethod" xml:space="preserve">
+ <value>Unrecognized or missing canonicalization method.</value>
+ </data>
+ <data name="UnsupportedSignatureMethod" xml:space="preserve">
+ <value>Unrecognized or missing signature method.</value>
+ </data>
</root> \ No newline at end of file
diff --git a/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs b/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
index ad73269..c5e6bba 100644
--- a/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/Provider/AnonymousRequest.cs
@@ -27,7 +27,7 @@ namespace DotNetOpenAuth.OpenId.Provider {
/// </summary>
/// <param name="provider">The provider that received the request.</param>
/// <param name="request">The incoming authentication request message.</param>
- [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "Code contracts require it.")]
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Requires<System.ArgumentException>(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "AuthenticationRequest", Justification = "Type name"), SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily", Justification = "Code contracts require it.")]
internal AnonymousRequest(OpenIdProvider provider, SignedResponseRequest request)
: base(provider, request) {
Contract.Requires<ArgumentNullException>(provider != null);
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
index 967ef60..3a17263 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs
@@ -501,14 +501,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
Contract.Requires<ArgumentNullException>(endpoints != null);
Contract.Requires<ArgumentNullException>(relyingParty != null);
- // Construct the endpoints filters based on criteria given by the host web site.
- EndpointSelector versionFilter = ep => ep.Version >= Protocol.Lookup(relyingParty.SecuritySettings.MinimumRequiredOpenIdVersion).Version;
- EndpointSelector hostingSiteFilter = relyingParty.EndpointFilter ?? (ep => true);
-
bool anyFilteredOut = false;
var filteredEndpoints = new List<IdentifierDiscoveryResult>();
foreach (var endpoint in endpoints) {
- if (versionFilter(endpoint) && hostingSiteFilter(endpoint)) {
+ if (relyingParty.FilterEndpoint(endpoint)) {
filteredEndpoints.Add(endpoint);
} else {
anyFilteredOut = true;
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
index 869a342..9e3824d 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/NegativeAuthenticationResponse.cs
@@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
+ using System.Linq;
using System.Web;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId.Messages;
@@ -279,7 +280,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// have not been tampered with since the Provider sent the message.</para>
/// </remarks>
public T GetUntrustedExtension<T>() where T : IOpenIdMessageExtension {
- return default(T);
+ return this.response.Extensions.OfType<T>().FirstOrDefault();
}
/// <summary>
@@ -303,7 +304,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// have not been tampered with since the Provider sent the message.</para>
/// </remarks>
public IOpenIdMessageExtension GetUntrustedExtension(Type extensionType) {
- return null;
+ return this.response.Extensions.OfType<IOpenIdMessageExtension>().Where(ext => extensionType.IsInstanceOfType(ext)).FirstOrDefault();
}
#endregion
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
index d80bf6a..8be097f 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdAjaxTextBox.cs
@@ -721,11 +721,16 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
var css = new HtmlLink();
- css.Href = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), EmbeddedStylesheetResourceName);
- css.Attributes["rel"] = "stylesheet";
- css.Attributes["type"] = "text/css";
- ErrorUtilities.VerifyHost(this.Page.Header != null, OpenIdStrings.HeadTagMustIncludeRunatServer);
- this.Page.Header.Controls.AddAt(0, css); // insert at top so host page can override
+ try {
+ css.Href = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), EmbeddedStylesheetResourceName);
+ css.Attributes["rel"] = "stylesheet";
+ css.Attributes["type"] = "text/css";
+ ErrorUtilities.VerifyHost(this.Page.Header != null, OpenIdStrings.HeadTagMustIncludeRunatServer);
+ this.Page.Header.Controls.AddAt(0, css); // insert at top so host page can override
+ } catch {
+ css.Dispose();
+ throw;
+ }
this.PrepareClientJavascript();
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs
index dbf6944..6243917 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdButton.cs
@@ -141,6 +141,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Sends server control content to a provided <see cref="T:System.Web.UI.HtmlTextWriter"/> object, which writes the content to be rendered on the client.
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.HtmlTextWriter.WriteEncodedText(System.String)", Justification = "Not localizable")]
protected override void Render(HtmlTextWriter writer) {
if (string.IsNullOrEmpty(this.Identifier)) {
writer.WriteEncodedText(string.Format(CultureInfo.CurrentCulture, "[{0}]", OpenIdStrings.NoIdentifierSet));
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
index 5128599..eccdacf 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs
@@ -316,7 +316,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Gets or sets the text to display if the user attempts to login
/// without providing an Identifier.
/// </summary>
- [Bindable(true)]
+ [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "br", Justification = "HTML"), Bindable(true)]
[Category("Appearance")]
[DefaultValue(RequiredTextDefault)]
[Localizable(true)]
@@ -336,7 +336,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Gets or sets the text to display if the user provides an invalid form for an Identifier.
/// </summary>
- [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Property grid only supports primitive types.")]
+ [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "br", Justification = "HTML"), SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings", Justification = "Property grid only supports primitive types.")]
[Bindable(true)]
[Category("Appearance")]
[DefaultValue(UriFormatTextDefault)]
@@ -687,150 +687,156 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Initializes the child controls.
/// </summary>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.WebControl.set_ToolTip(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.Label.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.HyperLink.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.CheckBox.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.Button.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.BaseValidator.set_ErrorMessage(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "br", Justification = "HTML"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "OpenID", Justification = "It is correct"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "MyOpenID", Justification = "Correct spelling"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "myopenid", Justification = "URL")]
protected void InitializeControls() {
this.panel = new Panel();
Table table = new Table();
- TableRow row1, row2, row3;
- TableCell cell;
- table.Rows.Add(row1 = new TableRow());
- table.Rows.Add(row2 = new TableRow());
- table.Rows.Add(row3 = new TableRow());
-
- // top row, left cell
- cell = new TableCell();
try {
- this.label = new HtmlGenericControl("label");
- this.label.InnerText = LabelTextDefault;
- cell.Controls.Add(this.label);
- row1.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ TableRow row1, row2, row3;
+ TableCell cell;
+ table.Rows.Add(row1 = new TableRow());
+ table.Rows.Add(row2 = new TableRow());
+ table.Rows.Add(row3 = new TableRow());
+
+ // top row, left cell
+ cell = new TableCell();
+ try {
+ this.label = new HtmlGenericControl("label");
+ this.label.InnerText = LabelTextDefault;
+ cell.Controls.Add(this.label);
+ row1.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // top row, middle cell
- cell = new TableCell();
- try {
- cell.Controls.Add(new InPlaceControl(this));
- row1.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ // top row, middle cell
+ cell = new TableCell();
+ try {
+ cell.Controls.Add(new InPlaceControl(this));
+ row1.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // top row, right cell
- cell = new TableCell();
- try {
- this.loginButton = new Button();
- this.loginButton.ID = this.ID + "_loginButton";
- this.loginButton.Text = ButtonTextDefault;
- this.loginButton.ToolTip = ButtonToolTipDefault;
- this.loginButton.Click += this.LoginButton_Click;
- this.loginButton.ValidationGroup = ValidationGroupDefault;
+ // top row, right cell
+ cell = new TableCell();
+ try {
+ this.loginButton = new Button();
+ this.loginButton.ID = this.ID + "_loginButton";
+ this.loginButton.Text = ButtonTextDefault;
+ this.loginButton.ToolTip = ButtonToolTipDefault;
+ this.loginButton.Click += this.LoginButton_Click;
+ this.loginButton.ValidationGroup = ValidationGroupDefault;
#if !Mono
- this.panel.DefaultButton = this.loginButton.ID;
+ this.panel.DefaultButton = this.loginButton.ID;
#endif
- cell.Controls.Add(this.loginButton);
- row1.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ cell.Controls.Add(this.loginButton);
+ row1.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // middle row, left cell
- row2.Cells.Add(new TableCell());
+ // middle row, left cell
+ row2.Cells.Add(new TableCell());
+
+ // middle row, middle cell
+ cell = new TableCell();
+ try {
+ cell.Style[HtmlTextWriterStyle.Color] = "gray";
+ cell.Style[HtmlTextWriterStyle.FontSize] = "smaller";
+ this.requiredValidator = new RequiredFieldValidator();
+ this.requiredValidator.ErrorMessage = RequiredTextDefault + RequiredTextSuffix;
+ this.requiredValidator.Text = RequiredTextDefault + RequiredTextSuffix;
+ this.requiredValidator.Display = ValidatorDisplay.Dynamic;
+ this.requiredValidator.ValidationGroup = ValidationGroupDefault;
+ cell.Controls.Add(this.requiredValidator);
+ this.identifierFormatValidator = new CustomValidator();
+ this.identifierFormatValidator.ErrorMessage = UriFormatTextDefault + RequiredTextSuffix;
+ this.identifierFormatValidator.Text = UriFormatTextDefault + RequiredTextSuffix;
+ this.identifierFormatValidator.ServerValidate += this.IdentifierFormatValidator_ServerValidate;
+ this.identifierFormatValidator.Enabled = UriValidatorEnabledDefault;
+ this.identifierFormatValidator.Display = ValidatorDisplay.Dynamic;
+ this.identifierFormatValidator.ValidationGroup = ValidationGroupDefault;
+ cell.Controls.Add(this.identifierFormatValidator);
+ this.errorLabel = new Label();
+ this.errorLabel.EnableViewState = false;
+ this.errorLabel.ForeColor = System.Drawing.Color.Red;
+ this.errorLabel.Style[HtmlTextWriterStyle.Display] = "block"; // puts it on its own line
+ this.errorLabel.Visible = false;
+ cell.Controls.Add(this.errorLabel);
+ this.examplePrefixLabel = new Label();
+ this.examplePrefixLabel.Text = ExamplePrefixDefault;
+ cell.Controls.Add(this.examplePrefixLabel);
+ cell.Controls.Add(new LiteralControl(" "));
+ this.exampleUrlLabel = new Label();
+ this.exampleUrlLabel.Font.Bold = true;
+ this.exampleUrlLabel.Text = ExampleUrlDefault;
+ cell.Controls.Add(this.exampleUrlLabel);
+ row2.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // middle row, middle cell
- cell = new TableCell();
- try {
- cell.Style[HtmlTextWriterStyle.Color] = "gray";
- cell.Style[HtmlTextWriterStyle.FontSize] = "smaller";
- this.requiredValidator = new RequiredFieldValidator();
- this.requiredValidator.ErrorMessage = RequiredTextDefault + RequiredTextSuffix;
- this.requiredValidator.Text = RequiredTextDefault + RequiredTextSuffix;
- this.requiredValidator.Display = ValidatorDisplay.Dynamic;
- this.requiredValidator.ValidationGroup = ValidationGroupDefault;
- cell.Controls.Add(this.requiredValidator);
- this.identifierFormatValidator = new CustomValidator();
- this.identifierFormatValidator.ErrorMessage = UriFormatTextDefault + RequiredTextSuffix;
- this.identifierFormatValidator.Text = UriFormatTextDefault + RequiredTextSuffix;
- this.identifierFormatValidator.ServerValidate += this.IdentifierFormatValidator_ServerValidate;
- this.identifierFormatValidator.Enabled = UriValidatorEnabledDefault;
- this.identifierFormatValidator.Display = ValidatorDisplay.Dynamic;
- this.identifierFormatValidator.ValidationGroup = ValidationGroupDefault;
- cell.Controls.Add(this.identifierFormatValidator);
- this.errorLabel = new Label();
- this.errorLabel.EnableViewState = false;
- this.errorLabel.ForeColor = System.Drawing.Color.Red;
- this.errorLabel.Style[HtmlTextWriterStyle.Display] = "block"; // puts it on its own line
- this.errorLabel.Visible = false;
- cell.Controls.Add(this.errorLabel);
- this.examplePrefixLabel = new Label();
- this.examplePrefixLabel.Text = ExamplePrefixDefault;
- cell.Controls.Add(this.examplePrefixLabel);
- cell.Controls.Add(new LiteralControl(" "));
- this.exampleUrlLabel = new Label();
- this.exampleUrlLabel.Font.Bold = true;
- this.exampleUrlLabel.Text = ExampleUrlDefault;
- cell.Controls.Add(this.exampleUrlLabel);
- row2.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ // middle row, right cell
+ cell = new TableCell();
+ try {
+ cell.Style[HtmlTextWriterStyle.Color] = "gray";
+ cell.Style[HtmlTextWriterStyle.FontSize] = "smaller";
+ cell.Style[HtmlTextWriterStyle.TextAlign] = "center";
+ this.registerLink = new HyperLink();
+ this.registerLink.Text = RegisterTextDefault;
+ this.registerLink.ToolTip = RegisterToolTipDefault;
+ this.registerLink.NavigateUrl = RegisterUrlDefault;
+ this.registerLink.Visible = RegisterVisibleDefault;
+ cell.Controls.Add(this.registerLink);
+ row2.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // middle row, right cell
- cell = new TableCell();
- try {
- cell.Style[HtmlTextWriterStyle.Color] = "gray";
- cell.Style[HtmlTextWriterStyle.FontSize] = "smaller";
- cell.Style[HtmlTextWriterStyle.TextAlign] = "center";
- this.registerLink = new HyperLink();
- this.registerLink.Text = RegisterTextDefault;
- this.registerLink.ToolTip = RegisterToolTipDefault;
- this.registerLink.NavigateUrl = RegisterUrlDefault;
- this.registerLink.Visible = RegisterVisibleDefault;
- cell.Controls.Add(this.registerLink);
- row2.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ // bottom row, left cell
+ cell = new TableCell();
+ row3.Cells.Add(cell);
- // bottom row, left cell
- cell = new TableCell();
- row3.Cells.Add(cell);
+ // bottom row, middle cell
+ cell = new TableCell();
+ try {
+ this.rememberMeCheckBox = new CheckBox();
+ this.rememberMeCheckBox.Text = RememberMeTextDefault;
+ this.rememberMeCheckBox.Checked = this.UsePersistentCookie != LogOnPersistence.Session;
+ this.rememberMeCheckBox.Visible = RememberMeVisibleDefault;
+ this.rememberMeCheckBox.CheckedChanged += this.RememberMeCheckBox_CheckedChanged;
+ cell.Controls.Add(this.rememberMeCheckBox);
+ row3.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // bottom row, middle cell
- cell = new TableCell();
- try {
- this.rememberMeCheckBox = new CheckBox();
- this.rememberMeCheckBox.Text = RememberMeTextDefault;
- this.rememberMeCheckBox.Checked = this.UsePersistentCookie != LogOnPersistence.Session;
- this.rememberMeCheckBox.Visible = RememberMeVisibleDefault;
- this.rememberMeCheckBox.CheckedChanged += this.RememberMeCheckBox_CheckedChanged;
- cell.Controls.Add(this.rememberMeCheckBox);
- row3.Cells.Add(cell);
- } catch {
- cell.Dispose();
- throw;
- }
+ // bottom row, right cell
+ cell = new TableCell();
+ try {
+ row3.Cells.Add(cell);
+ } catch {
+ cell.Dispose();
+ throw;
+ }
- // bottom row, right cell
- cell = new TableCell();
- try {
- row3.Cells.Add(cell);
+ // this sets all the controls' tab indexes
+ this.TabIndex = TabIndexDefault;
+
+ this.panel.Controls.Add(table);
} catch {
- cell.Dispose();
+ table.Dispose();
throw;
}
- // this sets all the controls' tab indexes
- this.TabIndex = TabIndexDefault;
-
- this.panel.Controls.Add(table);
-
this.idselectorJavascript = new Literal();
this.panel.Controls.Add(this.idselectorJavascript);
}
@@ -849,6 +855,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Renders the child controls.
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the rendered content.</param>
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Web.UI.WebControls.Literal.set_Text(System.String)", Justification = "By design"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "idselector", Justification = "HTML"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "charset", Justification = "html"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "src", Justification = "html"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "openidselector", Justification = "html"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "idselectorinputid", Justification = "html")]
protected override void RenderChildren(HtmlTextWriter writer) {
if (!this.DesignMode) {
this.label.Attributes["for"] = this.ClientID;
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
index a5fdf9b..57c1f05 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs
@@ -39,6 +39,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Provides the programmatic facilities to act as an OpenID relying party.
/// </summary>
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Unavoidable")]
[ContractVerification(true)]
public class OpenIdRelyingParty : IDisposable {
/// <summary>
@@ -108,6 +109,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </summary>
/// <param name="associationStore">The association store. If null, the relying party will always operate in "dumb mode".</param>
/// <param name="nonceStore">The nonce store to use. If null, the relying party will always operate in "dumb mode".</param>
+ [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Unavoidable")]
private OpenIdRelyingParty(IAssociationStore<Uri> associationStore, INonceStore nonceStore) {
// If we are a smart-mode RP (supporting associations), then we MUST also be
// capable of storing nonces to prevent replay attacks.
@@ -542,15 +544,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
NegativeAssertionResponse negativeAssertion;
IndirectSignedResponse positiveExtensionOnly;
if ((positiveAssertion = message as PositiveAssertionResponse) != null) {
- if (this.EndpointFilter != null) {
- // We need to make sure that this assertion is coming from an endpoint
- // that the host deems acceptable.
- var providerEndpoint = new SimpleXrdsProviderEndpoint(positiveAssertion);
- ErrorUtilities.VerifyProtocol(
- this.EndpointFilter(providerEndpoint),
- OpenIdStrings.PositiveAssertionFromNonWhitelistedProvider,
- providerEndpoint.Uri);
- }
+ // We need to make sure that this assertion is coming from an endpoint
+ // that the host deems acceptable.
+ var providerEndpoint = new SimpleXrdsProviderEndpoint(positiveAssertion);
+ ErrorUtilities.VerifyProtocol(
+ this.FilterEndpoint(providerEndpoint),
+ OpenIdStrings.PositiveAssertionFromNonQualifiedProvider,
+ providerEndpoint.Uri);
var response = new PositiveAuthenticationResponse(positiveAssertion, this);
foreach (var behavior in this.Behaviors) {
@@ -660,8 +660,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// </remarks>
internal static OpenIdRelyingParty CreateNonVerifying() {
OpenIdRelyingParty rp = new OpenIdRelyingParty();
- rp.Channel = OpenIdChannel.CreateNonVerifyingChannel();
- return rp;
+ try {
+ rp.Channel = OpenIdChannel.CreateNonVerifyingChannel();
+ return rp;
+ } catch {
+ rp.Dispose();
+ throw;
+ }
}
/// <summary>
@@ -672,13 +677,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <returns>
/// The HTTP response to send to this HTTP request.
/// </returns>
+ [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "OpenID", Justification = "real word"), SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "iframe", Justification = "Code contracts")]
internal OutgoingWebResponse ProcessResponseFromPopup(HttpRequestInfo request, Action<AuthenticationStatus> callback) {
Contract.Requires<ArgumentNullException>(request != null);
Contract.Ensures(Contract.Result<OutgoingWebResponse>() != null);
string extensionsJson = null;
var authResponse = this.NonVerifyingRelyingParty.GetResponse();
- ErrorUtilities.VerifyProtocol(authResponse != null, "OpenID popup window or iframe did not recognize an OpenID response in the request.");
+ ErrorUtilities.VerifyProtocol(authResponse != null, OpenIdStrings.PopupRedirectMissingResponse);
// Give the caller a chance to notify the hosting page and fill up the clientScriptExtensions collection.
if (callback != null) {
@@ -761,6 +767,38 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
}
/// <summary>
+ /// Checks whether a given OP Endpoint is permitted by the host relying party.
+ /// </summary>
+ /// <param name="endpoint">The OP endpoint.</param>
+ /// <returns><c>true</c> if the OP Endpoint is allowed; <c>false</c> otherwise.</returns>
+ protected internal bool FilterEndpoint(IProviderEndpoint endpoint) {
+ if (this.SecuritySettings.RejectAssertionsFromUntrustedProviders) {
+ if (!this.SecuritySettings.TrustedProviderEndpoints.Contains(endpoint.Uri)) {
+ Logger.OpenId.InfoFormat("Filtering out OP endpoint {0} because it is not on the exclusive trusted provider whitelist.", endpoint.Uri.AbsoluteUri);
+ return false;
+ }
+ }
+
+ if (endpoint.Version < Protocol.Lookup(this.SecuritySettings.MinimumRequiredOpenIdVersion).Version) {
+ Logger.OpenId.InfoFormat(
+ "Filtering out OP endpoint {0} because it implements OpenID {1} but this relying party requires OpenID {2} or later.",
+ endpoint.Uri.AbsoluteUri,
+ endpoint.Version,
+ Protocol.Lookup(this.SecuritySettings.MinimumRequiredOpenIdVersion).Version);
+ return false;
+ }
+
+ if (this.EndpointFilter != null) {
+ if (!this.EndpointFilter(endpoint)) {
+ Logger.OpenId.InfoFormat("Filtering out OP endpoint {0} because the host rejected it.", endpoint.Uri.AbsoluteUri);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /// <summary>
/// Releases unmanaged and - optionally - managed resources
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
index 62f6554..7cda8e0 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs
@@ -546,7 +546,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// <summary>
/// Enables a server control to perform final clean up before it is released from memory.
/// </summary>
- [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Base class doesn't implement virtual Dispose(bool), so we must call its Dispose() method.")]
+ [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Unavoidable because base class does not expose a protected virtual Dispose(bool) method."), SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Base class doesn't implement virtual Dispose(bool), so we must call its Dispose() method.")]
public sealed override void Dispose() {
this.Dispose(true);
base.Dispose();
@@ -809,6 +809,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
/// Configures the relying party.
/// </summary>
/// <param name="relyingParty">The relying party.</param>
+ [SuppressMessage("Microsoft.Maintainability", "CA1500:VariableNamesShouldNotMatchFieldNames", MessageId = "relyingParty", Justification = "This makes it possible for overrides to see the value before it is set on a field.")]
protected virtual void ConfigureRelyingParty(OpenIdRelyingParty relyingParty) {
Contract.Requires<ArgumentNullException>(relyingParty != null);
diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs
index a7686c5..fc6d4c7 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingParty/RelyingPartySecuritySettings.cs
@@ -8,6 +8,8 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
using System.Linq;
using DotNetOpenAuth.Messaging;
@@ -28,6 +30,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
this.PrivateSecretMaximumAge = TimeSpan.FromDays(7);
this.ProtectDownlevelReplayAttacks = ProtectDownlevelReplayAttacksDefault;
this.AllowApproximateIdentifierDiscovery = true;
+ this.TrustedProviderEndpoints = new HashSet<Uri>();
}
/// <summary>
@@ -143,6 +146,19 @@ namespace DotNetOpenAuth.OpenId.RelyingParty {
public bool AllowApproximateIdentifierDiscovery { get; set; }
/// <summary>
+ /// Gets the set of trusted OpenID Provider Endpoint URIs.
+ /// </summary>
+ public HashSet<Uri> TrustedProviderEndpoints { get; private set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether any login attempt coming from an OpenID Provider Endpoint that is not on this
+ /// whitelist of trusted OP Endpoints will be rejected. If the trusted providers list is empty and this value
+ /// is true, all assertions are rejected.
+ /// </summary>
+ /// <value>Default is <c>false</c>.</value>
+ public bool RejectAssertionsFromUntrustedProviders { get; set; }
+
+ /// <summary>
/// Gets or sets a value indicating whether special measures are taken to
/// protect users from replay attacks when those users' identities are hosted
/// by OpenID 1.x Providers.
diff --git a/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs b/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs
index 279ca30..7926e8f 100644
--- a/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.cs
+++ b/src/DotNetOpenAuth/OpenId/RelyingPartyDescription.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;
@@ -50,6 +51,7 @@ namespace DotNetOpenAuth.OpenId {
/// </summary>
/// <param name="supportedServiceTypeUris">The supported service type URIs.</param>
/// <returns>The best OpenID protocol version to use when communicating with this Provider.</returns>
+ [SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "OpenID", Justification = "Spelling correct")]
private static Protocol GetProtocolFromServices(string[] supportedServiceTypeUris) {
Protocol protocol = Protocol.FindBestVersion(p => p.RPReturnToTypeURI, supportedServiceTypeUris);
if (protocol == null) {
diff --git a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
index 48ed7f2..145a394 100644
--- a/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
+++ b/src/DotNetOpenAuth/OpenId/UriIdentifier.cs
@@ -480,7 +480,7 @@ namespace DotNetOpenAuth.OpenId {
Contract.Requires<InternalErrorException>(schemeSubstitution);
Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>()));
- int delimiterIndex = normal.IndexOf(Uri.SchemeDelimiter);
+ int delimiterIndex = normal.IndexOf(Uri.SchemeDelimiter, StringComparison.Ordinal);
string normalScheme = delimiterIndex < 0 ? normal : normal.Substring(0, delimiterIndex);
string nonCompressingScheme;
if (string.Equals(normalScheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) ||
diff --git a/src/DotNetOpenAuth/Xrds/XrdsDocument.cs b/src/DotNetOpenAuth/Xrds/XrdsDocument.cs
index e2c2d72..040c994 100644
--- a/src/DotNetOpenAuth/Xrds/XrdsDocument.cs
+++ b/src/DotNetOpenAuth/Xrds/XrdsDocument.cs
@@ -6,6 +6,7 @@
namespace DotNetOpenAuth.Xrds {
using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Xml;
@@ -51,6 +52,7 @@ namespace DotNetOpenAuth.Xrds {
/// Initializes a new instance of the <see cref="XrdsDocument"/> class.
/// </summary>
/// <param name="xml">The text that is the XRDS document.</param>
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Fixing would decrease readability, and not likely avoid any finalizer on a StringReader anyway.")]
public XrdsDocument(string xml)
: this(new XPathDocument(new StringReader(xml)).CreateNavigator()) { }
diff --git a/src/DotNetOpenAuth/XrdsPublisher.cs b/src/DotNetOpenAuth/XrdsPublisher.cs
index 83d82ff..03c32c1 100644
--- a/src/DotNetOpenAuth/XrdsPublisher.cs
+++ b/src/DotNetOpenAuth/XrdsPublisher.cs
@@ -208,7 +208,7 @@ namespace DotNetOpenAuth {
/// Renders the HTTP Header and/or HTML HEAD tags.
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
- [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Uri(Uri, string) accepts second arguments that Uri(Uri, new Uri(string)) does not that we must support.")]
+ [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Diagnostics.Contracts.__ContractsRuntime.Assume(System.Boolean,System.String,System.String)", Justification = "Code contracts"), SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Uri(Uri, string) accepts second arguments that Uri(Uri, new Uri(string)) does not that we must support.")]
protected override void Render(HtmlTextWriter writer) {
Contract.Assume(writer != null, "Missing contract.");
if (this.Enabled && this.Visible && !string.IsNullOrEmpty(this.XrdsUrl)) {
diff --git a/src/version.txt b/src/version.txt
index 2aa5131..7921bd0 100644
--- a/src/version.txt
+++ b/src/version.txt
@@ -1 +1 @@
-3.4.7
+3.4.8
diff --git a/tools/ILMerge/ILMerge License.rtf b/tools/ILMerge/ILMerge License.rtf
new file mode 100644
index 0000000..e800151
--- /dev/null
+++ b/tools/ILMerge/ILMerge License.rtf
@@ -0,0 +1,104 @@
+{\rtf1\ansi\ansicpg1252\uc1\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f37\fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;}
+{\f39\froman\fcharset0\fprq2{\*\panose 02040602050305030304}Book Antiqua;}{\f40\fswiss\fcharset0\fprq2{\*\panose 020b0706030402020204}Franklin Gothic Demi Cond;}{\f41\fswiss\fcharset0\fprq2{\*\panose 020b0503020102020204}Franklin Gothic Book;}
+{\f42\froman\fcharset238\fprq2 Times New Roman CE;}{\f43\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f45\froman\fcharset161\fprq2 Times New Roman Greek;}{\f46\froman\fcharset162\fprq2 Times New Roman Tur;}
+{\f47\froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f48\froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f49\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f50\froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
+{\f412\fswiss\fcharset238\fprq2 Tahoma CE;}{\f413\fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f415\fswiss\fcharset161\fprq2 Tahoma Greek;}{\f416\fswiss\fcharset162\fprq2 Tahoma Tur;}{\f417\fswiss\fcharset177\fprq2 Tahoma (Hebrew);}
+{\f418\fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f419\fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f420\fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}{\f421\fswiss\fcharset222\fprq2 Tahoma (Thai);}{\f432\froman\fcharset238\fprq2 Book Antiqua CE;}
+{\f433\froman\fcharset204\fprq2 Book Antiqua Cyr;}{\f435\froman\fcharset161\fprq2 Book Antiqua Greek;}{\f436\froman\fcharset162\fprq2 Book Antiqua Tur;}{\f439\froman\fcharset186\fprq2 Book Antiqua Baltic;}
+{\f442\fswiss\fcharset238\fprq2 Franklin Gothic Demi Cond CE;}{\f443\fswiss\fcharset204\fprq2 Franklin Gothic Demi Cond Cyr;}{\f445\fswiss\fcharset161\fprq2 Franklin Gothic Demi Cond Greek;}{\f446\fswiss\fcharset162\fprq2 Franklin Gothic Demi Cond Tur;}
+{\f449\fswiss\fcharset186\fprq2 Franklin Gothic Demi Cond Baltic;}{\f452\fswiss\fcharset238\fprq2 Franklin Gothic Book CE;}{\f453\fswiss\fcharset204\fprq2 Franklin Gothic Book Cyr;}{\f455\fswiss\fcharset161\fprq2 Franklin Gothic Book Greek;}
+{\f456\fswiss\fcharset162\fprq2 Franklin Gothic Book Tur;}{\f459\fswiss\fcharset186\fprq2 Franklin Gothic Book Baltic;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;
+\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
+{\stylesheet{\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 Normal;}{\*\cs10 \additive \ssemihidden Default Paragraph Font;}{\*
+\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv
+\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs20\lang1024\langfe1024\cgrid\langnp1024\langfenp1024 \snext11 \ssemihidden Normal Table;}{\s15\ql \fi-274\li274\ri0\sb120\sl460\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin274\itap0 \f40\fs44\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext15 \styrsid9786739 1sectionhead;}{\s16\ql \li0\ri0\sb120\sl200\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \caps\f40\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext16 \styrsid9786739 4laparahead;}{\s17\ql \li0\ri-18\sb120\sl240\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin-18\lin0\itap0 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext17 \styrsid9786739 2lasubhead;}{\s18\ql \fi-187\li187\ri0\sb60\sl180\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin187\itap0 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext18 \styrsid9786739 3cnumbered;}{\s19\ql \fi-340\li624\ri0\sb60\sl160\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin624\itap0 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext19 \styrsid9786739 3inumbered2ndlevel;}{\s20\ql \li0\ri0\sb240\sl240\slmult0
+\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext20 \styrsid9786739 2afrenchsubhead;}{\s21\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0
+\cbpat9 \f37\fs20\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext21 \ssemihidden \styrsid7154712 Document Map;}}{\*\latentstyles\lsdstimax156\lsdlockeddef0}{\*\pgptbl {\pgp\ipgp2\itap0\li0\ri0\sb0\sa0\brdrt\brdrs\brdrw20 }{\pgp\ipgp0
+\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid2099452\rsid4207571\rsid5465292\rsid5510097\rsid5510644\rsid7154712\rsid7241305\rsid7672529\rsid7735936\rsid9179139\rsid9786739\rsid10440675\rsid11303133\rsid13130884\rsid14028235\rsid14100361\rsid14113652
+\rsid15276140\rsid16213514}{\*\generator Microsoft Word 11.0.6359;}{\info{\title ILMerge EULA}{\author Ken Leppert}{\operator mbarnett}{\creatim\yr2005\mo3\dy16\hr15\min43}{\revtim\yr2005\mo3\dy16\hr15\min43}{\printim\yr2004\mo4\dy30\hr13\min9}{\version2}
+{\edmins0}{\nofpages3}{\nofwords1188}{\nofchars6775}{\*\company Microsoft Corporation}{\nofcharsws7948}{\vern24703}}\widowctrl\ftnbj\aenddoc\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180
+\dghorigin1800\dgvorigin1440\dghshow1\dgvshow1\jexpand\viewkind1\viewscale68\viewzk2\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel
+\wrppunct\asianbrkrule\rsidroot9786739\newtblstyruls\nogrowautofit \fet0\sectd \linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang
+{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang
+{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain
+\s15\ql \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0\pararsid7154712 \f40\fs44\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b\f39\fs28\insrsid9786739 MICROSOFT }{
+\b\f39\fs28\insrsid5465292 ILMerge}{\insrsid9786739
+\par }{\b\f39\fs22\insrsid9786739 END-USER LICENSE AGREEMENT FOR MICROSOFT SOFTWARE}{\insrsid9786739
+\par }\pard\plain \s17\qj \li0\ri-17\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin-17\lin0\itap0\pararsid14100361 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b\f39\insrsid9786739 IMPORTANT\emdash
+READ CAREFULLY: }{\f39\insrsid9786739 This End-User License Agreement (\'93EULA\'94) is a legal agreement between you (either an individual or a single entity) and Microsoft Corporation (\'93Microsoft\'94) for th
+e Microsoft software that accompanies this EULA, which includes computer software and may include associated media, printed materials, \'93online\'94 or electronic documentation, and Internet-based services (\'93Software\'94).\~
+ An amendment or addendum to this EULA may accompany the Software.\~ }{\b\f39\insrsid9786739
+YOU AGREE TO BE BOUND BY THE TERMS OF THIS EULA BY INSTALLING, COPYING, OR OTHERWISE USING THE SOFTWARE. IF YOU DO NOT AGREE, DO NOT INSTALL, COPY, OR USE THE SOFTWARE.}{\insrsid9786739
+\par }\pard\plain \qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 1.\~\~\~\~\~\~\~\~ }{
+\b\f39\fs22\insrsid9786739 GRANTS OF LICENSE}{\f39\fs22\insrsid9786739 . Microsoft grants you the rights described in this EULA provided that you comply with all terms and conditions of this EULA.\~ }{\insrsid9786739
+\par }\pard\plain \s19\qj \fi720\li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid9786739 1.1\~\~\~\~\~\~ }{
+\b\i\f39\fs22\cf0\insrsid9786739 License Grant}{\f39\fs22\cf0\insrsid9786739 . Microsoft grants to you a personal, nonexclusive, nontransferable, limited license to }{\f39\fs22\insrsid9786739 install and use a reasonable number of copies of
+the Software on computers residing on your premises }{\f39\fs22\cf0\insrsid9786739 for the purposes of designing, developing, and testing, your software product(s), provided that you are the only individual using the Software.\~ }{\insrsid9786739
+\par }\pard\plain \s18\qj \fi720\li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 1.2\~\~\~\~\~\~ }{
+\b\i\f39\fs22\insrsid9786739 Documentation}{\f39\fs22\insrsid9786739 .}{\b\f39\fs22\insrsid9786739 \~ }{\f39\fs22\insrsid9786739 You may make and use a reasonabl
+e number of copies of any documentation, provided that such copies shall be used only for your personal purposes and are not to be republished or distributed (either in hard copy or electronic form) beyond your premises.}{\insrsid9786739
+\par }\pard \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 {\f39\fs22\insrsid9786739 2.\~\~\~\~\~\~\~\~ }{\b\f39\fs22\insrsid9786739 RESERVATION OF RIGHTS AND OWNERSHIP.\~ }{
+\f39\fs22\insrsid9786739 The Software is licensed as a single product.\~ Its component parts may not be separated. Microsoft reserves all rights not expressly granted to you in this EULA.\~
+ The Software is protected by copyright and other intellectual property laws and treaties}{\f39\fs22\insrsid14028235 , and}{\f39\fs22\insrsid9786739 Microsoft }{\f39\fs22\insrsid14028235 (}{\f39\fs22\insrsid9786739 or its suppliers}{
+\f39\fs22\insrsid14028235 , where applicable)}{\f39\fs22\insrsid9786739 own }{\f39\fs22\insrsid14028235 all right, }{\f39\fs22\insrsid9786739 title, }{\f39\fs22\insrsid14028235 and interest in all }{\f39\fs22\insrsid9786739
+intellectual property rights in the Software.\~ }{\b\f39\fs22\insrsid9786739 The Software is licensed, not sold.}{\insrsid9786739
+\par }\pard\plain \s19\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid9786739 3.\~\~\~\~\~\~\~\~ }{
+\b\f39\fs22\cf0\insrsid9786739 LIMITATIONS ON REVERSE ENGINEERING, DECOMPILATION, AND DISASSEMBLY}{\b\i\f39\fs22\cf0\insrsid9786739 .}{\f39\fs22\cf0\insrsid9786739 \~
+ You may not reverse engineer, decompile, or disassemble the Software, except and only to the extent that such activity is expressly permitted by applicable law notwithstanding this limitation.}{\insrsid9786739
+\par }\pard\plain \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl220\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 4.\~\~\~\~\~\~\~\~
+}{\b\f39\fs22\insrsid9786739 NO RENTAL/COMMERCIAL HOSTING.}{\b\i\f39\fs22\insrsid9786739 }{\f39\fs22\insrsid9786739 You may not rent, lease, lend or provide commercial hosting services with the Software.}{\insrsid9786739
+\par }\pard\plain \s19\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid9786739 5.\~\~\~\~\~\~\~\~ }{
+\b\f39\fs22\cf0\insrsid9786739 NO SOFTWARE TRANSFER.\~ }{\f39\fs22\cf0\insrsid9786739 You may not assign or otherwise transfer the SOFTWARE or any of your rights hereunder to any third party.}{\insrsid9786739
+\par }{\f39\fs22\cf0\insrsid9786739 6.\~\~\~\~\~\~\~\~ }{\b\f39\fs22\cf0\insrsid9786739 CONSENT TO USE OF DATA.\~ }{\f39\fs22\cf0\insrsid9786739 You
+ agree that Microsoft and its affiliates may collect and use technical information gathered as part of the product support services provided to you, if any, related to the Software.\~
+ Microsoft may use this information solely to improve our products or to provide customized services or technologies to you and will not disclose this information in a form that personally identifies you.\~\~ }{\insrsid9786739
+\par }{\f39\fs22\cf0\insrsid5510644 7}{\f39\fs22\cf0\insrsid9786739 .\~\~\~\~\~\~\~\~ }{\b\f39\fs22\cf0\insrsid9786739 ADDITIONAL SOFTWARE/SERVICES.\~ }{\f39\fs22\insrsid9786739 Microsoft is not obligated to provide maintenance, technical supplements}{
+\f39\fs22\insrsid14028235 , updates,}{\f39\fs22\insrsid9786739 or other support to you for the Software licensed under this EULA. }{\f39\fs22\insrsid7241305 }{\f39\fs22\insrsid9786739 In the event that Microsoft does provide such supplements or updates}
+{\b\f39\fs22\insrsid9786739 , }{\f39\fs22\insrsid9786739 this EULA applies to such updates, supplements, or add-on components of the Software that Microsoft may provide to
+you or make available to you after the date you obtain your initial copy of the Software, unless we provide other terms along with the update, supplement, or add-on component}{\f39\fs22\cf0\insrsid9786739 .\~
+ Microsoft reserves the right to discontinue any Internet-based services provided to you or made available to you through the use of the Software.\~ }{\insrsid9786739
+\par }\pard\plain \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl220\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid5510644 8}{
+\f39\fs22\insrsid9786739 .\~\~\~\~\~\~\~\~ }{\b\f39\fs22\insrsid9786739 EXPORT RESTRICTIONS}{\f39\fs22\insrsid9786739 .\~ }{\f39\fs22\cgrid0\insrsid9786739 You acknowledge that the Software is subject to U.S. export jurisdiction.\~
+ You agree to comply with all applicable international and national laws that apply to the Software, including the U.S. Export Administration Regulations, as well as end-user, end-use, and destination restrictions issued by U.S. and other governments.\~\~
+ For additional information see }{\f39\fs22\ul\cgrid0\insrsid9786739 http://www.microsoft.com/exporting/}{\f39\fs22\cgrid0\insrsid9786739 .}{\insrsid9786739
+\par }\pard\plain \s19\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs14\cf1\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\cf0\insrsid14113652 9}{
+\f39\fs22\cf0\insrsid9786739 .\~\~\~\~\~\~ }{\b\f39\fs22\cf0\insrsid9786739 TERMINATION.}{\f39\fs22\cf0\insrsid9786739 \~ Without prejudice to any other rights, Microsoft may terminate this EULA if you fail to comply with }{\f39\fs22\cf0\insrsid7241305
+any }{\f39\fs22\cf0\insrsid9786739 term}{\f39\fs22\cf0\insrsid7241305 or}{\f39\fs22\cf0\insrsid9786739 condition of this EULA. }{\f39\fs22\cf0\insrsid7241305 }{\f39\fs22\cf0\insrsid9786739
+In such event, you must destroy all copies of the Software and all of its component parts.}{\insrsid9786739
+\par }\pard\plain \s18\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl220\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f41\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\fs22\insrsid9786739 1}{
+\f39\fs22\insrsid14113652 0}{\f39\fs22\insrsid9786739 .\~\~\~\~\~\~ }{\b\f39\fs22\ul\insrsid9786739 DISCLAIMER OF WARRANTIES}{\b\f39\fs22\insrsid9786739 .\~
+ TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, MICROSOFT AND ITS SUPPLIERS PROVIDE THE SOFTWARE}{\f39\fs22\insrsid9786739 }{\b\f39\fs22\insrsid9786739 AND SUPPORT SERVICES (IF ANY) }{\b\i\f39\fs22\insrsid9786739 AS IS AND WITH ALL FAULTS}{
+\b\f39\fs22\insrsid9786739 , AND HEREBY DISCLAIM ALL OTHER WARRANTIES AND CONDITIONS, WHETHER EXPRESS, IMPLIED
+ OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES, DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF RELIABILITY OR AVAILABILITY, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF WORKMANLI
+K
+E EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE, ALL WITH REGARD TO THE SOFTWARE, AND THE PROVISION OF OR FAILURE TO PROVIDE SUPPORT OR OTHER SERVICES, INFORMATION, SOFTWARE, AND RELATED CONTENT THROUGH THE SOFTWARE OR OTHERWISE ARISING OUT OF THE
+ USE OF THE SOFTWARE.\~ ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT, QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT WITH REGARD TO THE SOFTWARE.}{\insrsid9786739
+\par }{\f39\fs22\insrsid9786739 1}{\f39\fs22\insrsid14113652 1}{\f39\fs22\insrsid9786739 .}{\b\f39\fs22\insrsid9786739 \~\~\~\~\~\~ }{\b\f39\fs22\ul\insrsid9786739 EXCLUSION OF INCIDENTAL, CONSEQUENTIAL AND CERTAIN OTHER DAMAGES}{\b\f39\fs22\insrsid9786739 .\~
+ }{\b\caps\f39\fs22\insrsid9786739
+To the maximum extent permitted by applicable law, in no event shall Microsoft or its suppliers be liable for any special, incidental, punitive, indirect, or consequential damages whatsoever (including, but not limited to, damages for loss of profit
+s, LOSS OF DATA, or confidential or other information}{\b\f39\fs22\insrsid9786739 , }{\b\caps\f39\fs22\insrsid9786739
+for business interruption, for personal injury, for loss of privacy, for failure to meet any duty including of good faith or of reasonable care, for negligence, and}{\b\f39\fs22\insrsid9786739 }{\b\caps\f39\fs22\insrsid9786739
+for any other pecuniary or other los
+s whatsoever) arising out of or in any way related to the use of or inability to use the SOFTWARE, the provision of or failure to provide Support OR OTHER Services, informatIon, software, and related CONTENT through the software or otherwise arising out o
+f
+ the use of the software, or otherwise under or in connection with any provision of this EULA, even in the event of the fault, tort (including negligence), misrepresentation, strict liability, breach of contract or breach of warranty of Microsoft or any s
+upplier, and even if Microsoft or any supplier has been advised of the possibility of such damages. }{\insrsid9786739
+\par }{\f39\fs22\insrsid9786739 1}{\f39\fs22\insrsid14113652 2}{\f39\fs22\insrsid9786739 .}{\b\f39\fs22\insrsid9786739 \~\~\~\~\~\~ }{\b\f39\fs22\ul\insrsid9786739 LIMITATION OF LIABILITY AND REMEDIES}{\b\f39\fs22\insrsid9786739
+. NOTWITHSTANDING ANY DAMAGES THAT YOU MIGHT INCUR FOR ANY REASON WHATSOEVER (INCLUDING, WITHOUT LIMITATION, A
+LL DAMAGES REFERENCED HEREIN AND ALL DIRECT OR GENERAL DAMAGES IN CONTRACT OR ANYTHING ELSE), THE ENTIRE LIABILITY OF MICROSOFT AND ANY OF ITS SUPPLIERS UNDER ANY PROVISION OF THIS EULA AND YOUR EXCLUSIVE REMEDY HEREUNDER SHALL BE LIMITED TO THE GREATER O
+F THE ACTUAL DAMAGES YOU INCUR IN REASONABLE RELIANCE ON THE SOFTWARE UP TO THE AMOUNT ACTUALLY PAID BY YOU FOR THE SOFTWARE}{\f39\fs22\insrsid9786739 }{\b\f39\fs22\insrsid9786739 OR US$5.00.\~
+ THE FOREGOING LIMITATIONS, EXCLUSIONS AND DISCLAIMERS SHALL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, EVEN IF ANY REMEDY FAILS ITS ESSENTIAL PURPOSE.}{\insrsid9786739
+\par }{\f39\fs22\insrsid9786739 1}{\f39\fs22\insrsid14113652 3}{\f39\fs22\insrsid9786739 .\~\~\~\~\~\~ }{\b\f39\fs22\insrsid9786739 APPLICABLE LAW.\~ }{\f39\fs22\insrsid7735936 T}{\f39\fs22\insrsid9786739 his EULA }{\f39\fs22\insrsid7735936
+shall be construed under and }{\f39\fs22\insrsid9786739 governed by the laws of the State of Washington}{\f39\fs22\insrsid7735936 , without regard to conflicts of law principles}{\f39\fs22\insrsid9786739 .\~ }{\insrsid9786739
+\par }\pard\plain \s20\qj \li0\ri0\sb100\sa100\sbauto1\saauto1\sl240\slmult0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \f40\fs22\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f39\insrsid9786739 1}{\f39\insrsid14113652
+4}{\f39\insrsid9786739 .\~\~\~\~ }{\b\f39\insrsid9786739 ENTIRE AGREEMENT; SEVERABILITY.\~ }{\f39\insrsid9786739 This
+EULA (including any addendum or amendment to this EULA which is included with the Software) are the entire agreement between you and Microsoft relating to the Software and the support services (if any) and they supersede all prior or contemporaneous oral
+or written communications,\~proposals and representations with respect to the Software or any other subject matter covered by this EULA.\~
+ If any provision of this EULA is held to be void, invalid, unenforceable or illegal, the other provisions shall continue in full force and effect}{\insrsid9786739
+\par }\pard\plain \qj \li0\ri0\sb100\sa100\sbauto1\saauto1\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid14100361 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\insrsid10440675
+\par }} \ No newline at end of file
diff --git a/tools/ILMerge/ILMerge.doc b/tools/ILMerge/ILMerge.doc
new file mode 100644
index 0000000..f3ac501
--- /dev/null
+++ b/tools/ILMerge/ILMerge.doc
Binary files differ
diff --git a/tools/ILMerge/ILMerge.exe b/tools/ILMerge/ILMerge.exe
new file mode 100644
index 0000000..3d44384
--- /dev/null
+++ b/tools/ILMerge/ILMerge.exe
Binary files differ
diff --git a/tools/drop.proj b/tools/drop.proj
index 0a617a6..21baae0 100644
--- a/tools/drop.proj
+++ b/tools/drop.proj
@@ -66,6 +66,7 @@
$(ProjectRoot)**\*.sln.cache;
$(ProjectRoot)**\*.suo;
$(ProjectRoot)**\*.user;
+ $(ProjectRoot)**\*.vs10x;
$(ProjectRoot)**\*.gitignore;
$(ProjectRoot)**\*.ldf;
$(ProjectRoot)**\*.log*;
diff --git a/vsi/vsi.proj b/vsi/vsi.proj
index eca131e..683ea51 100644
--- a/vsi/vsi.proj
+++ b/vsi/vsi.proj
@@ -18,7 +18,7 @@
</MSBuild>
<PropertyGroup>
- <ProjectTemplatesVsi>$(DropDirectoryNoSlash).vsi</ProjectTemplatesVsi>
+ <ProjectTemplatesVsi>$(DropsRoot)$(ProductName) SDK-$(BuildVersion)-vs2008.vsi</ProjectTemplatesVsi>
</PropertyGroup>
<ItemGroup>
<RedistributableFiles Include="$(ProjectTemplatesVsi)">
diff --git a/vsix/vsix.proj b/vsix/vsix.proj
index 9fa8919..d966bce 100644
--- a/vsix/vsix.proj
+++ b/vsix/vsix.proj
@@ -58,7 +58,7 @@
<ItemGroup>
<VSGalleryVsixRawSources Include="$(ExtensionVsixLayoutDirectory)*"
Exclude="$(ExtensionVsixLayoutDirectory)*.vsixmanifest">
- <VSGalleryVsix>$(DropsRoot)$(ProductName) %(ProjectTemplateZipTargets.FileName)-$(BuildVersion).vsix</VSGalleryVsix>
+ <VSGalleryVsix>$(DropsRoot)$(ProductName) %(ProjectTemplateZipTargets.FileName)-$(BuildVersion)-vs2010.vsix</VSGalleryVsix>
<TopLevelTemplate>%(ProjectTemplateZipTargets.FileName)</TopLevelTemplate>
</VSGalleryVsixRawSources>
<VSGalleryVsixSources Include="@(VSGalleryVsixRawSources)">
@@ -68,13 +68,13 @@
<VSGalleryVsixZipSources Include="$(ExtensionVsixLayoutDirectory)**\*.zip" />
<VSGalleryVsixSources Include="@(VSGalleryVsixZipSources)">
<TopLevelTemplate>%(FileName)</TopLevelTemplate>
- <VSGalleryVsix>$(DropsRoot)$(ProductName) %(FileName)-$(BuildVersion).vsix</VSGalleryVsix>
+ <VSGalleryVsix>$(DropsRoot)$(ProductName) %(FileName)-$(BuildVersion)-vs2010.vsix</VSGalleryVsix>
<!-- The A in the path below used to be %(FileName), but to fit inside MAX_PATH when VS expands, we shorten it. -->
<TargetPath>$(IntermediatePath)%(FileName).vsix\%(RecursiveDir)A%(Extension)</TargetPath>
</VSGalleryVsixSources>
<VSGalleryVsixSources Include="@(ProjectTemplateZipTargets->'$(ProjectRoot)projecttemplates\%(FileName).vsixmanifest')">
- <VSGalleryVsix>$(DropsRoot)$(ProductName) %(ProjectTemplateZipTargets.FileName)-$(BuildVersion).vsix</VSGalleryVsix>
+ <VSGalleryVsix>$(DropsRoot)$(ProductName) %(ProjectTemplateZipTargets.FileName)-$(BuildVersion)-vs2010.vsix</VSGalleryVsix>
<TopLevelTemplate>%(ProjectTemplateZipTargets.FileName)</TopLevelTemplate>
<TargetPath>$(IntermediatePath)%(ProjectTemplateZipTargets.FileName).vsix\extension.vsixmanifest</TargetPath>
<Transform>true</Transform>
@@ -104,7 +104,7 @@
<Target Name="Build" DependsOnTargets="Layout;VSGalleryVsixLayout" Returns="@(GeneratedVsix)">
<PropertyGroup>
- <ExtensionVsix>$(DropsRoot)$(ProductName) SDK-$(BuildVersion).vsix</ExtensionVsix>
+ <ExtensionVsix>$(DropsRoot)$(ProductName) SDK-$(BuildVersion)-vs2010.vsix</ExtensionVsix>
</PropertyGroup>
<ItemGroup>
<GeneratedVsix Include="$(ExtensionVsix)">