diff options
53 files changed, 1790 insertions, 87 deletions
diff --git a/ILMergeInternalizeExceptions.txt b/ILMergeInternalizeExceptions.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/ILMergeInternalizeExceptions.txt diff --git a/LICENSE.txt b/LICENSE.txt index a3f32e1..906ff2c 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -4,7 +4,7 @@ Every file is bound by the following copyright and license unless explicitly indicated otherwise in and/or for any individual file. -Copyright (c) 2008, Andrew Arnott +Copyright (c) 2008-2009, Andrew Arnott All rights reserved. Microsoft Public License (Ms-PL) @@ -3,16 +3,26 @@ <PropertyGroup> <AutomatedBuild>true</AutomatedBuild> <SolutionPath>$(ProjectRoot)\src\$(ProductName).sln</SolutionPath> + <ILMergeOutputAssemblyDirectory>$(OutputPath)\unified\</ILMergeOutputAssemblyDirectory> + <ILMergeOutputAssembly>$(ILMergeOutputAssemblyDirectory)\$(ProductName).dll</ILMergeOutputAssembly> </PropertyGroup> <Import Project="$(ProjectRoot)\tools\$(ProductName).Versioning.targets"/> <Import Project="$(ProjectRoot)\tools\Documentation.targets"/> <Import Project="$(ProjectRoot)\tools\Publish.targets"/> <UsingTask AssemblyFile="$(ProjectRoot)\lib\MSBuild.Community.Tasks.dll" TaskName="Zip"/> + <UsingTask AssemblyFile="$(ProjectRoot)\lib\MSBuild.Community.Tasks.dll" TaskName="ILMerge"/> <ItemGroup> <SampleProjects Include="$(ProjectRoot)\samples\**\*.csproj" /> <SampleSites Include="OAuthConsumer;OAuthServiceProvider;InfoCardRelyingParty" /> + <ILMergeInputAssemblies Include="$(OutputPath)\$(ProductName).dll; + $(ProjectRoot)\lib\Microsoft.Contracts.dll; "/> + <DelaySignedAssemblies Include="$(ILMergeOutputAssembly); + $(OutputPath)\$(ProductName).dll; + $(OutputPath)\$(ProductName).Contracts.dll; + $(OutputPath)\$(ProductName).Test.dll; + $(ProjectRoot)\samples\OpenIdOfflineProvider\bin\$(Configuration)\OpenIdOfflineProvider.exe" /> </ItemGroup> <Target Name="Clean" DependsOnTargets="CleanDocumentation;UnpublishSamples;UnpublishDocumentation"> @@ -22,7 +32,7 @@ $(ProjectRoot)\bin; $(ProjectRoot)\**\obj; $(ProjectRoot)\doc\api; - $(ProjectRoot)\drops; + $(DropsRoot); $(ProjectRoot)\src\PrecompiledWeb; " /> <DirtyDirectories Include="@(SampleDirectories->'%(FullPath)\bin')" /> @@ -37,50 +47,68 @@ <RemoveDir Directories="@(DirtyDirectories)" /> </Target> - <Target Name="BuildProduct"> + <Target Name="SkipVerification" Condition="'$(IsElevated)' == 'true'"> + <SignatureVerification SkipVerification="true" AssemblyName="$(ProductName)" PublicKeyToken="$(PublicKeyToken)" /> + <SignatureVerification SkipVerification="true" AssemblyName="$(ProductName)_Accessor" PublicKeyToken="$(PublicKeyToken)" /> + <SignatureVerification SkipVerification="true" AssemblyName="$(ProductName).Test" PublicKeyToken="$(PublicKeyToken)" /> + </Target> + + <Target Name="BuildProduct" DependsOnTargets="SkipVerification"> <MSBuild Projects="$(ProjectRoot)\src\$(ProductName)\$(ProductName).csproj" /> </Target> - <Target Name="BuildTests"> + <Target Name="BuildTests" DependsOnTargets="SkipVerification"> <MSBuild Projects="$(ProjectRoot)\src\$(ProductName).Test\$(ProductName).Test.csproj" /> </Target> - <Target Name="BuildSamples"> + <Target Name="BuildSamples" DependsOnTargets="SkipVerification"> <MSBuild Projects="@(SampleProjects)" /> - <MSBuild Projects="$(SolutionPath)" Targets="@(SampleSites)" Properties="Sign=$(Sign)" /> + <MSBuild Projects="$(SolutionPath)" Targets="@(SampleSites)" /> </Target> - <Target Name="Build"> - <!-- We explicitly pass the Sign property in because if properties are set - inside this very .proj file instead of being passed on the command-line, their - values won't propagate automatically. --> - <MSBuild Projects="$(SolutionPath)" Properties="Sign=$(Sign)" /> + <Target Name="Build" DependsOnTargets="SkipVerification"> + <MSBuild Projects="$(SolutionPath)" /> </Target> - <Target Name="Rebuild"> - <!-- We explicitly pass the Sign property in because if properties are set - inside this very .proj file instead of being passed on the command-line, their - values won't propagate automatically. --> - <MSBuild Projects="$(SolutionPath)" Targets="Rebuild" Properties="Sign=$(Sign)" /> + <Target Name="Rebuild" DependsOnTargets="SkipVerification"> + <MSBuild Projects="$(SolutionPath)" Targets="Rebuild" /> </Target> - <Target Name="_EnsureCleanTools" DependsOnTargets="_SetToolsProperties" Condition="'$(NoClean)' != 'true'"> - <!-- clean up any previous drop with the same name so we don't aggregate files. --> - <RemoveDir Directories="$(ToolsDirectory)" /> + <Target Name="BuildUnifiedProduct" + DependsOnTargets="BuildProduct" + Inputs="@(ILMergeInputAssemblies)" + Outputs="$(ILMergeOutputAssembly)"> + <MakeDir Directories="$(ILMergeOutputAssemblyDirectory)" /> + <ILMerge ExcludeFile="$(ProjectRoot)\ILMergeInternalizeExceptions.txt" + InputAssemblies="@(ILMergeInputAssemblies)" + OutputFile="$(ILMergeOutputAssembly)" + KeyFile="$(PublicKeyFile)" + DelaySign="true" + /> + </Target> + + <Target Name="ReSignDelaySignedAssemblies"> + <Message Text="Signing delay-signed assemblies." /> + <ReSignDelaySignedAssemblies + KeyContainer="$(KeyPairContainer)" + Assemblies="@(DelaySignedAssemblies)" + Condition="Exists(%(Identity))" /> </Target> - <Target Name="_SetToolsProperties"> + <Target Name="ToolsLayout" DependsOnTargets="GetBuildVersion;_SetDropProperties;BuildUnifiedProduct"> <PropertyGroup> - <ToolsDirectory>$(ProjectRoot)\drops\$(ProductName)-Tools-$(BuildVersion)</ToolsDirectory> + <ToolsDirectory>$(DropsRoot)\$(ProductName)-Tools-$(BuildVersion)</ToolsDirectory> </PropertyGroup> - </Target> - <Target Name="ToolsLayout" DependsOnTargets="GetBuildVersion;_SetDropProperties;_SetToolsProperties;_EnsureCleanTools"> <ItemGroup> <ToolProjects Include="$(ProjectRoot)\Samples\OpenIdOfflineProvider\OpenIdOfflineProvider.csproj" /> <OfflineProvider Include=" $(ProjectRoot)\Samples\OpenIdOfflineProvider\bin\$(Configuration)\**\*.dll; - $(ProjectRoot)\Samples\OpenIdOfflineProvider\bin\$(Configuration)\OpenIdOfflineProvider.exe" /> + $(ILMergeOutputAssembly).*; + $(ProjectRoot)\Samples\OpenIdOfflineProvider\bin\$(Configuration)\OpenIdOfflineProvider.exe" + Exclude=" + $(ProjectRoot)\Samples\OpenIdOfflineProvider\bin\$(Configuration)\$(ProductName).*; + "/> <OfflineProviderTargets Include=" @(OfflineProvider->'$(ToolsDirectory)\%(RecursiveDir)%(FileName)%(Extension)')"/> @@ -88,8 +116,10 @@ <AllToolTargets Include="@(OfflineProviderTargets)" /> </ItemGroup> - <MSBuild Projects="@(ToolProjects)" Properties="Sign=$(Sign)" /> + <MSBuild Projects="@(ToolProjects)" /> + <!-- clean up any previous drop with the same name so we don't aggregate files. --> + <RemoveDir Directories="$(ToolsDirectory)" Condition="'$(NoClean)' != 'true'" /> <MakeDir Directories="@(ToolsDirectory)" /> <Copy SourceFiles="@(AllToolSources)" DestinationFiles="@(AllToolTargets)" SkipUnchangedFiles="true" /> </Target> @@ -119,28 +149,13 @@ <Target Name="_SetDropProperties"> <!-- This target is necessary because PropertyGroups within the same Target as where CallTarget is fired do NOT affect those called targets. --> - <PropertyGroup> - <Sign Condition="'$(Sign)' == ''">true</Sign> - </PropertyGroup> - <!-- The rest of these are here so that other DependsOn targets have access to these properties. --> <PropertyGroup> - <DropDirectory>$(ProjectRoot)\drops\$(ProductName)-$(BuildVersion)</DropDirectory> + <DropDirectory>$(DropsRoot)\$(ProductName)-$(BuildVersion)</DropDirectory> </PropertyGroup> </Target> - <Target Name="_EnsureCleanDrop" Condition="'$(NoClean)' != 'true'"> - <!-- This target only does a clean sufficient to guarantee that our DotNetOpenAuth.dll is rebuilt, but - we don't usually want to clean our documentation because that takes forever to build froms scratch. --> - <MSBuild Projects="$(SolutionPath)" Targets="Clean" /> - - <!-- clean up any previous drop with the same name so we don't aggregate files. --> - <RemoveDir Directories="$(DropDirectory)" /> - </Target> - - <Target Name="DropLayout" DependsOnTargets="GetBuildVersion;_SetDropProperties;_EnsureCleanDrop;BuildProduct;BuildSamples;Documentation"> - <Warning Condition=" '$(Configuration)' != 'release' " Text="Building $(Configuration) instead of Release!" /> - <Warning Condition=" '$(Sign)' != 'true' " Text="Building unsigned!" /> + <Target Name="DropLayout" DependsOnTargets="GetBuildVersion;_SetDropProperties;BuildUnifiedProduct;ReSignDelaySignedAssemblies;BuildSamples;Documentation"> <PropertyGroup> <DropBinDirectory>$(DropDirectory)\Bin</DropBinDirectory> <DropLibDirectory>$(DropDirectory)\Lib</DropLibDirectory> @@ -164,7 +179,8 @@ " Exclude="$(ProjectRoot)\Doc\README.*.html;" /> <DropBinSourceFiles Include=" - $(OutputPath)\$(ProductName).???; + $(ILMergeOutputAssemblyDirectory)\$(ProductName).???; + $(OutputPath)\$(ProductName).xml; $(OutputPath)\$(ProductName).Contracts.???; $(ProjectRoot)\Doc\README.Bin.html; $(ProjectRoot)\src\$(ProductName)\Configuration\$(ProductName).xsd; @@ -222,6 +238,8 @@ " /> </ItemGroup> + <!-- clean up any previous drop with the same name so we don't aggregate files. --> + <RemoveDir Directories="$(DropDirectory)" Condition="'$(NoClean)' != 'true'" /> <MakeDir Directories="@(DropDirectories)" /> <Copy SourceFiles="@(AllDropSources)" DestinationFiles="@(AllDropTargets)" SkipUnchangedFiles="true" /> <!-- fix up the samples so that they will compile right out of the drop --> @@ -237,7 +255,7 @@ <DropZip>$(DropDirectory).zip</DropZip> </PropertyGroup> <Delete Files="$(DropZip)" /> - <Zip Files="@(AllDropTargets)" ZipFileName="$(DropZip)" WorkingDirectory="$(ProjectRoot)\drops" /> + <Zip Files="@(AllDropTargets)" ZipFileName="$(DropZip)" WorkingDirectory="$(DropsRoot)" /> </Target> <!-- Although Nightly includes publishing samples and docs, those targets are conditioned for @@ -245,5 +263,4 @@ <Target Name="Nightly" DependsOnTargets="Drop;Tools;PublishSamples;PublishDocumentation"> </Target> - </Project> diff --git a/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj b/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj index 1bb2367..2f303bb 100644 --- a/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj +++ b/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj @@ -57,10 +57,11 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> - <PropertyGroup Condition=" '$(Sign)' == 'true' "> + <PropertyGroup> <SignAssembly>true</SignAssembly> - <AssemblyOriginatorKeyFile>..\..\src\official-build-key.pfx</AssemblyOriginatorKeyFile> <DefineConstants>$(DefineConstants);StrongNameSigned</DefineConstants> + <DelaySign>true</DelaySign> + <AssemblyOriginatorKeyFile>..\..\src\official-build-key.pub</AssemblyOriginatorKeyFile> </PropertyGroup> <ItemGroup> <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL"> diff --git a/samples/OpenIdProviderWebForms/Code/InMemoryConsumerDescription.cs b/samples/OpenIdProviderWebForms/Code/InMemoryConsumerDescription.cs new file mode 100644 index 0000000..de4505d --- /dev/null +++ b/samples/OpenIdProviderWebForms/Code/InMemoryConsumerDescription.cs @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------- +// <copyright file="InMemoryConsumerDescription.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace OpenIdProviderWebForms.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public class InMemoryConsumerDescription : IConsumerDescription { + #region IConsumerDescription Members + + public string Key { get; set; } + + public string Secret { get; set; } + + public System.Security.Cryptography.X509Certificates.X509Certificate2 Certificate { get; set; } + + public Uri Callback { get; set; } + + public DotNetOpenAuth.OAuth.VerificationCodeFormat VerificationCodeFormat { get; set; } + + public int VerificationCodeLength { get; set; } + + #endregion + } +} diff --git a/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderAccessToken.cs b/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderAccessToken.cs new file mode 100644 index 0000000..7e26b45 --- /dev/null +++ b/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderAccessToken.cs @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------- +// <copyright file="InMemoryServiceProviderAccessToken.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace OpenIdProviderWebForms.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public class InMemoryServiceProviderAccessToken : IServiceProviderAccessToken { + #region IServiceProviderAccessToken Members + + public string Token { get; set; } + + public DateTime? ExpirationDate { get; set; } + + public string Username { get; set; } + + public string[] Roles { get; set; } + + #endregion + + public string Secret { get; set; } + + public string Scope { get; set; } + } +} diff --git a/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderRequestToken.cs b/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderRequestToken.cs new file mode 100644 index 0000000..9c02427 --- /dev/null +++ b/samples/OpenIdProviderWebForms/Code/InMemoryServiceProviderRequestToken.cs @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------- +// <copyright file="InMemoryServiceProviderRequestToken.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace OpenIdProviderWebForms.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public class InMemoryServiceProviderRequestToken : IServiceProviderRequestToken { + /// <summary> + /// Initializes a new instance of the <see cref="InMemoryServiceProviderRequestToken"/> class. + /// </summary> + public InMemoryServiceProviderRequestToken() { + this.CreatedOn = DateTime.Now; + } + + #region IServiceProviderRequestToken Members + + public string Token { get; set; } + + public string ConsumerKey { get; set; } + + public DateTime CreatedOn { get; set; } + + public Uri Callback { get; set; } + + public string VerificationCode { get; set; } + + public Version ConsumerVersion { get; set; } + + #endregion + + public string Secret { get; set; } + + public string Scope { get; set; } + } +} diff --git a/samples/OpenIdProviderWebForms/Code/InMemoryTokenManager.cs b/samples/OpenIdProviderWebForms/Code/InMemoryTokenManager.cs new file mode 100644 index 0000000..2433f57 --- /dev/null +++ b/samples/OpenIdProviderWebForms/Code/InMemoryTokenManager.cs @@ -0,0 +1,113 @@ +//----------------------------------------------------------------------- +// <copyright file="InMemoryTokenManager.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace OpenIdProviderWebForms.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + using DotNetOpenAuth.OpenId.Extensions.OAuth; + + /// <summary> + /// A simple in-memory token manager. JUST FOR PURPOSES OF KEEPING THE SAMPLE SIMPLE. + /// </summary> + /// <remarks> + /// This is merely a sample app. A real web app SHOULD NEVER store a memory-only + /// token manager in application. It should be an IServiceProviderTokenManager + /// implementation that is bound to a database. + /// </remarks> + public class InMemoryTokenManager : IServiceProviderTokenManager, IOpenIdOAuthTokenManager, ICombinedOpenIdProviderTokenManager { + private Dictionary<string, InMemoryServiceProviderRequestToken> requestTokens = new Dictionary<string, InMemoryServiceProviderRequestToken>(); + private Dictionary<string, InMemoryServiceProviderAccessToken> accessTokens = new Dictionary<string, InMemoryServiceProviderAccessToken>(); + + /// <summary> + /// Initializes a new instance of the <see cref="InMemoryTokenManager"/> class. + /// </summary> + internal InMemoryTokenManager() { + } + + #region IServiceProviderTokenManager Members + + public IConsumerDescription GetConsumer(string consumerKey) { + return new InMemoryConsumerDescription { + Key = consumerKey, + Secret = "some crazy secret", + }; + } + + public IServiceProviderRequestToken GetRequestToken(string token) { + return this.requestTokens[token]; + } + + public IServiceProviderAccessToken GetAccessToken(string token) { + throw new NotImplementedException(); + } + + #endregion + + #region ITokenManager Members + + public string GetTokenSecret(string token) { + if (this.requestTokens.ContainsKey(token)) { + return this.requestTokens[token].Secret; + } else { + return this.accessTokens[token].Secret; + } + } + + public void StoreNewRequestToken(DotNetOpenAuth.OAuth.Messages.UnauthorizedTokenRequest request, DotNetOpenAuth.OAuth.Messages.ITokenSecretContainingMessage response) { + throw new NotImplementedException(); + } + + public bool IsRequestTokenAuthorized(string requestToken) { + // In OpenID+OAuth scenarios, request tokens are always authorized. + return true; + } + + public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret) { + this.requestTokens.Remove(requestToken); + this.accessTokens[accessToken] = new InMemoryServiceProviderAccessToken { + Token = accessToken, + Secret = accessTokenSecret, + }; + } + + public TokenType GetTokenType(string token) { + if (this.requestTokens.ContainsKey(token)) { + return TokenType.RequestToken; + } else if (this.accessTokens.ContainsKey(token)) { + return TokenType.AccessToken; + } else { + return TokenType.InvalidToken; + } + } + + #endregion + + #region IOpenIdOAuthTokenManager Members + + public void StoreOpenIdAuthorizedRequestToken(string consumerKey, AuthorizationApprovedResponse authorization) { + this.requestTokens[authorization.RequestToken] = new InMemoryServiceProviderRequestToken { + Token = authorization.RequestToken, + Scope = authorization.Scope, + ConsumerVersion = authorization.Version, + }; + } + + #endregion + + #region ICombinedOpenIdProviderTokenManager Members + + public string GetConsumerKey(DotNetOpenAuth.OpenId.Realm realm) { + // We just use the realm as the consumer key, like Google does. + return realm; + } + + #endregion + } +} diff --git a/samples/OpenIdProviderWebForms/Code/OAuthHybrid.cs b/samples/OpenIdProviderWebForms/Code/OAuthHybrid.cs new file mode 100644 index 0000000..cc4beff --- /dev/null +++ b/samples/OpenIdProviderWebForms/Code/OAuthHybrid.cs @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthHybrid.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace OpenIdProviderWebForms.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + + internal class OAuthHybrid { + /// <summary> + /// Initializes static members of the <see cref="OAuthHybrid"/> class. + /// </summary> + static OAuthHybrid() { + ServiceProvider = new ServiceProvider(GetServiceDescription(), TokenManager); + } + + internal static IServiceProviderTokenManager TokenManager { + get { + // This is merely a sample app. A real web app SHOULD NEVER store a memory-only + // token manager in application. It should be an IServiceProviderTokenManager + // implementation that is bound to a database. + var tokenManager = (IServiceProviderTokenManager)HttpContext.Current.Application["TokenManager"]; + if (tokenManager == null) { + HttpContext.Current.Application["TokenManager"] = tokenManager = new InMemoryTokenManager(); + } + + return tokenManager; + } + } + + internal static ServiceProvider ServiceProvider { get; private set; } + + internal static ServiceProviderDescription GetServiceDescription() { + return new ServiceProviderDescription { + TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() }, + }; + } + } +} diff --git a/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj b/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj index ceea842..ffb0f2f 100644 --- a/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj +++ b/samples/OpenIdProviderWebForms/OpenIdProviderWebForms.csproj @@ -83,12 +83,20 @@ <Content Include="user_xrds.aspx" /> </ItemGroup> <ItemGroup> + <Compile Include="access_token.ashx.cs"> + <DependentUpon>access_token.ashx</DependentUpon> + </Compile> + <Compile Include="Code\InMemoryConsumerDescription.cs" /> + <Compile Include="Code\InMemoryServiceProviderAccessToken.cs" /> <Compile Include="Code\CustomStore.cs" /> <Compile Include="Code\CustomStoreDataSet.Designer.cs"> <DependentUpon>CustomStoreDataSet.xsd</DependentUpon> <AutoGen>True</AutoGen> <DesignTime>True</DesignTime> </Compile> + <Compile Include="Code\InMemoryServiceProviderRequestToken.cs" /> + <Compile Include="Code\InMemoryTokenManager.cs" /> + <Compile Include="Code\OAuthHybrid.cs" /> <Compile Include="Code\ReadOnlyXmlMembershipProvider.cs" /> <Compile Include="Code\TracePageAppender.cs" /> <Compile Include="Code\Util.cs" /> @@ -157,6 +165,7 @@ <Content Include="TracePage.aspx" /> </ItemGroup> <ItemGroup> + <Content Include="access_token.ashx" /> <None Include="Code\CustomStoreDataSet.xsc"> <DependentUpon>CustomStoreDataSet.xsd</DependentUpon> </None> @@ -190,7 +199,7 @@ <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}"> <WebProjectProperties> <UseIIS>False</UseIIS> - <AutoAssignPort>True</AutoAssignPort> + <AutoAssignPort>False</AutoAssignPort> <DevelopmentServerPort>4860</DevelopmentServerPort> <DevelopmentServerVPath>/</DevelopmentServerVPath> <IISUrl> diff --git a/samples/OpenIdProviderWebForms/access_token.ashx b/samples/OpenIdProviderWebForms/access_token.ashx new file mode 100644 index 0000000..dcb088e --- /dev/null +++ b/samples/OpenIdProviderWebForms/access_token.ashx @@ -0,0 +1 @@ +<%@ WebHandler Language="C#" CodeBehind="access_token.ashx.cs" Class="OpenIdProviderWebForms.access_token" %> diff --git a/samples/OpenIdProviderWebForms/access_token.ashx.cs b/samples/OpenIdProviderWebForms/access_token.ashx.cs new file mode 100644 index 0000000..b895da9 --- /dev/null +++ b/samples/OpenIdProviderWebForms/access_token.ashx.cs @@ -0,0 +1,23 @@ +namespace OpenIdProviderWebForms { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using System.Web.Services; + using DotNetOpenAuth.OAuth; + using OpenIdProviderWebForms.Code; + + [WebService(Namespace = "http://tempuri.org/")] + [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] + public class access_token : IHttpHandler { + public bool IsReusable { + get { return true; } + } + + public void ProcessRequest(HttpContext context) { + var request = OAuthHybrid.ServiceProvider.ReadAccessTokenRequest(); + var response = OAuthHybrid.ServiceProvider.PrepareAccessTokenMessage(request); + OAuthHybrid.ServiceProvider.Channel.Send(response); + } + } +} diff --git a/samples/OpenIdProviderWebForms/decide.aspx b/samples/OpenIdProviderWebForms/decide.aspx index 4a6e2d8..3788315 100644 --- a/samples/OpenIdProviderWebForms/decide.aspx +++ b/samples/OpenIdProviderWebForms/decide.aspx @@ -17,6 +17,10 @@ <td><asp:Label runat="server" ID='realmLabel' /> </td> </tr> </table> + <asp:Panel runat="server" ID="OAuthPanel"> + <p>In addition the relying party has asked for permission to access your private data. </p> + <asp:CheckBox runat="server" Text="Allow the relying party to access my private data" ID="oauthPermission" /> + </asp:Panel> <p>Allow this to proceed? </p> <uc1:ProfileFields ID="profileFields" runat="server" Visible="false" /> <asp:Button ID="yes_button" OnClick="Yes_Click" Text=" yes " runat="Server" /> diff --git a/samples/OpenIdProviderWebForms/decide.aspx.cs b/samples/OpenIdProviderWebForms/decide.aspx.cs index 3a14cf7..6146bd2 100644 --- a/samples/OpenIdProviderWebForms/decide.aspx.cs +++ b/samples/OpenIdProviderWebForms/decide.aspx.cs @@ -6,6 +6,7 @@ namespace OpenIdProviderWebForms { using DotNetOpenAuth.OpenId.Extensions.ProviderAuthenticationPolicy; using DotNetOpenAuth.OpenId.Extensions.SimpleRegistration; using DotNetOpenAuth.OpenId.Provider; + using OpenIdProviderWebForms.Code; /// <summary> /// Page for giving the user the option to continue or cancel out of authentication with a consumer. @@ -21,6 +22,11 @@ namespace OpenIdProviderWebForms { this.realmLabel.Text = ProviderEndpoint.PendingRequest.Realm.ToString(); + var oauthRequest = OAuthHybrid.ServiceProvider.ReadAuthorizationRequest(ProviderEndpoint.PendingRequest); + if (oauthRequest != null) { + this.OAuthPanel.Visible = true; + } + if (ProviderEndpoint.PendingAuthenticationRequest != null) { if (ProviderEndpoint.PendingAuthenticationRequest.IsDirectedIdentity) { ProviderEndpoint.PendingAuthenticationRequest.LocalIdentifier = Code.Util.BuildIdentityUrl(); @@ -51,6 +57,24 @@ namespace OpenIdProviderWebForms { } protected void Yes_Click(object sender, EventArgs e) { + if (!Page.IsValid) { + return; + } + + if (this.OAuthPanel.Visible) { + string consumerKey = null; + string grantedScope = null; + if (this.oauthPermission.Checked) { + // This SIMPLE sample merely uses the realm as the consumerKey, + // but in a real app this will probably involve a database lookup to translate + // the realm to a known consumerKey. + consumerKey = ProviderEndpoint.PendingRequest.Realm; + grantedScope = string.Empty; // we don't scope individual access rights on this sample + } + + OAuthHybrid.ServiceProvider.AttachAuthorizationResponse(ProviderEndpoint.PendingRequest, consumerKey, grantedScope); + } + var sregRequest = ProviderEndpoint.PendingRequest.GetExtension<ClaimsRequest>(); ClaimsResponse sregResponse = null; if (sregRequest != null) { diff --git a/samples/OpenIdProviderWebForms/decide.aspx.designer.cs b/samples/OpenIdProviderWebForms/decide.aspx.designer.cs index 05386cd..3aa6271 100644 --- a/samples/OpenIdProviderWebForms/decide.aspx.designer.cs +++ b/samples/OpenIdProviderWebForms/decide.aspx.designer.cs @@ -50,6 +50,24 @@ namespace OpenIdProviderWebForms { protected global::System.Web.UI.WebControls.Label realmLabel; /// <summary> + /// OAuthPanel 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.Panel OAuthPanel; + + /// <summary> + /// oauthPermission 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.CheckBox oauthPermission; + + /// <summary> /// profileFields control. /// </summary> /// <remarks> diff --git a/samples/OpenIdRelyingPartyWebForms/Global.asax.cs b/samples/OpenIdRelyingPartyWebForms/Global.asax.cs index ac74853..6583289 100644 --- a/samples/OpenIdRelyingPartyWebForms/Global.asax.cs +++ b/samples/OpenIdRelyingPartyWebForms/Global.asax.cs @@ -42,6 +42,20 @@ } } + internal static InMemoryTokenManager OwnSampleOPHybridTokenManager { + get { + var tokenManager = (InMemoryTokenManager)HttpContext.Current.Application["OwnSampleOPHybridTokenManager"]; + if (tokenManager == null) { + string consumerKey = new Uri(HttpContext.Current.Request.Url, HttpContext.Current.Request.ApplicationPath).AbsoluteUri; + string consumerSecret = "some crazy secret"; + tokenManager = new InMemoryTokenManager(consumerKey, consumerSecret); + HttpContext.Current.Application["OwnSampleOPHybridTokenManager"] = tokenManager; + } + + return tokenManager; + } + } + public static string ToString(NameValueCollection collection) { using (StringWriter sw = new StringWriter()) { foreach (string key in collection.Keys) { diff --git a/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj b/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj index d3bf92c..6f5df5c 100644 --- a/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj +++ b/samples/OpenIdRelyingPartyWebForms/OpenIdRelyingPartyWebForms.csproj @@ -101,6 +101,13 @@ <Compile Include="Code\InMemoryTokenManager.cs" /> <Compile Include="Code\State.cs" /> <Compile Include="Code\TracePageAppender.cs" /> + <Compile Include="loginPlusOAuthSampleOP.aspx.cs"> + <DependentUpon>loginPlusOAuthSampleOP.aspx</DependentUpon> + <SubType>ASPXCodeBehind</SubType> + </Compile> + <Compile Include="loginPlusOAuthSampleOP.aspx.designer.cs"> + <DependentUpon>loginPlusOAuthSampleOP.aspx</DependentUpon> + </Compile> <Compile Include="Global.asax.cs"> <DependentUpon>Global.asax</DependentUpon> </Compile> @@ -169,6 +176,7 @@ <Content Include="xrds.aspx" /> </ItemGroup> <ItemGroup> + <Content Include="loginPlusOAuthSampleOP.aspx" /> <Content Include="images\attention.png" /> <Content Include="images\dotnetopenid_tiny.gif" /> <Content Include="images\openid_login.gif" /> diff --git a/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx new file mode 100644 index 0000000..adbb71a --- /dev/null +++ b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx @@ -0,0 +1,33 @@ +<%@ Page Language="C#" AutoEventWireup="True" CodeBehind="loginPlusOAuthSampleOP.aspx.cs" + Inherits="OpenIdRelyingPartyWebForms.loginPlusOAuthSampleOP" ValidateRequest="false" + MasterPageFile="~/Site.Master" %> + +<%@ Register Assembly="DotNetOpenAuth" Namespace="DotNetOpenAuth.OpenId.RelyingParty" + TagPrefix="rp" %> +<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="Main"> + <h2>Login Page </h2> + <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex='0'> + <asp:View ID="View1" runat="server"> + <asp:Label runat="server" Text="OpenIdProviderWebForms sample's OP Identifier or Claimed Identifier: " /> + <rp:OpenIdTextBox runat="server" ID="identifierBox" Text="http://localhost:4860/" + OnCanceled="identifierBox_Failed" OnFailed="identifierBox_Failed" OnLoggedIn="identifierBox_LoggedIn" /> + <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="required" + ControlToValidate="identifierBox" /> + <br /> + <asp:Button ID="beginButton" runat="server" Text="Login + OAuth request" OnClick="beginButton_Click" /> + </asp:View> + <asp:View ID="AuthorizationGiven" runat="server"> + Authentication succeeded, and OAuth access was granted. + <p>The actual login step is aborted since this sample focuses on the process only + up to this point.</p> + </asp:View> + <asp:View ID="AuthorizationDenied" runat="server"> + Authentication succeeded, but OAuth access was denied. + <p>The actual login step is aborted since this sample focuses on the process only + up to this point.</p> + </asp:View> + <asp:View ID="AuthenticationFailed" runat="server"> + Authentication failed or was canceled. + </asp:View> + </asp:MultiView> +</asp:Content> diff --git a/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.cs b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.cs new file mode 100644 index 0000000..5a86f31 --- /dev/null +++ b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.cs @@ -0,0 +1,53 @@ +namespace OpenIdRelyingPartyWebForms { + using System; + using System.Web.Security; + using DotNetOpenAuth.ApplicationBlock; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + using DotNetOpenAuth.OpenId; + using DotNetOpenAuth.OpenId.Extensions.AttributeExchange; + using DotNetOpenAuth.OpenId.RelyingParty; + + public partial class loginPlusOAuthSampleOP : System.Web.UI.Page { + protected void Page_Load(object sender, EventArgs e) { + } + + protected void beginButton_Click(object sender, EventArgs e) { + if (!Page.IsValid) { + return; + } + + this.identifierBox.LogOn(); + } + + protected void identifierBox_LoggedIn(object sender, OpenIdEventArgs e) { + State.FetchResponse = e.Response.GetExtension<FetchResponse>(); + + ServiceProviderDescription serviceDescription = new ServiceProviderDescription { + AccessTokenEndpoint = new MessageReceivingEndpoint(new Uri(e.Response.Provider.Uri, "/access_token.ashx"), HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.PostRequest), + TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() }, + }; + WebConsumer consumer = new WebConsumer(serviceDescription, Global.OwnSampleOPHybridTokenManager); + + AuthorizedTokenResponse accessToken = consumer.ProcessUserAuthorization(e.Response); + if (accessToken != null) { + this.MultiView1.SetActiveView(this.AuthorizationGiven); + + // At this point, the access token would be somehow associated with the user + // account at the RP. + ////Database.Associate(e.Response.ClaimedIdentifier, accessToken.AccessToken); + } else { + this.MultiView1.SetActiveView(this.AuthorizationDenied); + } + + // Avoid the redirect + e.Cancel = true; + } + + protected void identifierBox_Failed(object sender, OpenIdEventArgs e) { + this.MultiView1.SetActiveView(this.AuthenticationFailed); + } + } +} diff --git a/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.designer.cs b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.designer.cs new file mode 100644 index 0000000..9bf29b9 --- /dev/null +++ b/samples/OpenIdRelyingPartyWebForms/loginPlusOAuthSampleOP.aspx.designer.cs @@ -0,0 +1,88 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:2.0.50727.4918 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace OpenIdRelyingPartyWebForms { + + + public partial class loginPlusOAuthSampleOP { + + /// <summary> + /// MultiView1 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.MultiView MultiView1; + + /// <summary> + /// View1 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.View View1; + + /// <summary> + /// identifierBox control. + /// </summary> + /// <remarks> + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// </remarks> + protected global::DotNetOpenAuth.OpenId.RelyingParty.OpenIdTextBox identifierBox; + + /// <summary> + /// RequiredFieldValidator1 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.RequiredFieldValidator RequiredFieldValidator1; + + /// <summary> + /// beginButton 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.Button beginButton; + + /// <summary> + /// AuthorizationGiven 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.View AuthorizationGiven; + + /// <summary> + /// AuthorizationDenied 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.View AuthorizationDenied; + + /// <summary> + /// AuthenticationFailed 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.View AuthenticationFailed; + } +} diff --git a/samples/OpenIdRelyingPartyWebForms/xrds.aspx b/samples/OpenIdRelyingPartyWebForms/xrds.aspx index 9e201d0..99a535c 100644 --- a/samples/OpenIdRelyingPartyWebForms/xrds.aspx +++ b/samples/OpenIdRelyingPartyWebForms/xrds.aspx @@ -17,7 +17,9 @@ is default.aspx. <URI priority="1"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/login.aspx"))%></URI> <URI priority="2"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/loginProgrammatic.aspx"))%></URI> <URI priority="3"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/ajaxlogin.aspx"))%></URI> - <URI priority="3"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/NoIdentityOpenId.aspx"))%></URI> + <URI priority="4"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/NoIdentityOpenId.aspx"))%></URI> + <URI priority="5"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/loginPlusOAuth.aspx"))%></URI> + <URI priority="6"><%=new Uri(Request.Url, Response.ApplyAppPathModifier("~/loginPlusOAuthSampleOP.aspx"))%></URI> </Service> </XRD> </xrds:XRDS> diff --git a/src/DotNetOpenAuth.BuildTasks/ChangeAssemblyReference.cs b/src/DotNetOpenAuth.BuildTasks/ChangeAssemblyReference.cs new file mode 100644 index 0000000..3ad5eb0 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/ChangeAssemblyReference.cs @@ -0,0 +1,47 @@ +using System; +using System.Linq; +using System.IO; +using System.Xml; + +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Microsoft.Build.BuildEngine; + +namespace DotNetOpenAuth.BuildTasks { + /// <summary> + /// Replaces Reference items HintPaths in a set of projects. + /// </summary> + public class ChangeAssemblyReference : Task { + /// <summary> + /// The projects to alter. + /// </summary> + [Required] + public ITaskItem[] Projects { get; set; } + /// <summary> + /// The project reference to remove. + /// </summary> + [Required] + public string OldReference { get; set; } + /// <summary> + /// The assembly reference to add. + /// </summary> + [Required] + public string NewReference { get; set; } + + const string msbuildNamespace = "http://schemas.microsoft.com/developer/msbuild/2003"; + public override bool Execute() { + foreach (var project in Projects) { + Project doc = new Project(); + doc.Load(project.ItemSpec); + + var reference = doc.GetEvaluatedItemsByName("Reference").OfType<BuildItem>(). + Where(item => string.Equals(item.GetMetadata("HintPath"), OldReference, StringComparison.OrdinalIgnoreCase)).Single(); + reference.SetMetadata("HintPath", NewReference); + + doc.Save(project.ItemSpec); + } + + return true; + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs b/src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs new file mode 100644 index 0000000..72415d9 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs @@ -0,0 +1,50 @@ +using System; +using System.Linq; +using System.IO; +using System.Xml; + +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Microsoft.Build.BuildEngine; + +namespace DotNetOpenAuth.BuildTasks { + /// <summary> + /// Replaces ProjectReference items in a set of projects with Reference items. + /// </summary> + public class ChangeProjectReferenceToAssemblyReference : Task { + /// <summary> + /// The projects to alter. + /// </summary> + [Required] + public ITaskItem[] Projects { get; set; } + /// <summary> + /// The project reference to remove. + /// </summary> + [Required] + public string ProjectReference { get; set; } + /// <summary> + /// The assembly reference to add. + /// </summary> + [Required] + public string Reference { get; set; } + + const string msbuildNamespace = "http://schemas.microsoft.com/developer/msbuild/2003"; + public override bool Execute() { + foreach (var project in Projects) { + Project doc = new Project(); + doc.Load(project.ItemSpec); + + var projectReference = doc.EvaluatedItems.OfType<BuildItem>().Where( + item => item.Name == "ProjectReference" && item.Include == ProjectReference).Single(); + doc.RemoveItem(projectReference); + + var newReference = doc.AddNewItem("Reference", Path.GetFileNameWithoutExtension(Reference)); + newReference.SetMetadata("HintPath", Reference); + + doc.Save(project.ItemSpec); + } + + return true; + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/CheckAdminRights.cs b/src/DotNetOpenAuth.BuildTasks/CheckAdminRights.cs new file mode 100644 index 0000000..9cfd35d --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/CheckAdminRights.cs @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------- +// <copyright file="CheckAdminRights.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using System.Security.Principal; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + + public class CheckAdminRights : Task { + /// <summary> + /// Gets or sets a value indicating whether this process has elevated permissions. + /// </summary> + [Output] + public bool IsElevated { get; set; } + + /// <summary> + /// Executes this instance. + /// </summary> + public override bool Execute() { + WindowsIdentity id = WindowsIdentity.GetCurrent(); + WindowsPrincipal p = new WindowsPrincipal(id); + this.IsElevated = p.IsInRole(WindowsBuiltInRole.Administrator); + + return true; + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/CompareFiles.cs b/src/DotNetOpenAuth.BuildTasks/CompareFiles.cs new file mode 100644 index 0000000..691df20 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/CompareFiles.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Build.Utilities; +using Microsoft.Build.Framework; +using System.IO; + +namespace DotNetOpenAuth.BuildTasks { + public class CompareFiles : Task { + /// <summary> + /// One set of items to compare. + /// </summary> + [Required] + public ITaskItem[] OriginalItems { get; set; } + + /// <summary> + /// The other set of items to compare. + /// </summary> + [Required] + public ITaskItem[] NewItems { get; set; } + + /// <summary> + /// Gets whether the items lists contain items that are identical going down the list. + /// </summary> + [Output] + public bool AreSame { get; private set; } + + /// <summary> + /// Same as <see cref="AreSame"/>, but opposite. + /// </summary> + [Output] + public bool AreChanged { get { return !AreSame; } } + + public override bool Execute() { + AreSame = AreFilesIdentical(); + return true; + } + + private bool AreFilesIdentical() { + if (OriginalItems.Length != NewItems.Length) { + return false; + } + + for (int i = 0; i < OriginalItems.Length; i++) { + if (!IsContentOfFilesTheSame(OriginalItems[i].ItemSpec, NewItems[i].ItemSpec)) { + return false; + } + } + + return true; + } + + private bool IsContentOfFilesTheSame(string file1, string file2) { + // If exactly one file is missing, that's different. + if (File.Exists(file1) ^ File.Exists(file2)) return false; + // If both are missing, that's the same. + if (!File.Exists(file1)) return true; + // If both are present, we need to do a content comparison. + using (FileStream fileStream1 = File.OpenRead(file1)) { + using (FileStream fileStream2 = File.OpenRead(file2)) { + if (fileStream1.Length != fileStream2.Length) return false; + byte[] buffer1 = new byte[4096]; + byte[] buffer2 = new byte[buffer1.Length]; + int bytesRead; + do { + bytesRead = fileStream1.Read(buffer1, 0, buffer1.Length); + if (fileStream2.Read(buffer2, 0, buffer2.Length) != bytesRead) { + // We should never get here since we compared file lengths, but + // this is a sanity check. + return false; + } + for (int i = 0; i < bytesRead; i++) { + if (buffer1[i] != buffer2[i]) { + return false; + } + } + } while (bytesRead == buffer1.Length); + } + } + + return true; + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/CreateWebApplication.cs b/src/DotNetOpenAuth.BuildTasks/CreateWebApplication.cs new file mode 100644 index 0000000..4980898 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/CreateWebApplication.cs @@ -0,0 +1,95 @@ +//----------------------------------------------------------------------- +// <copyright file="CreateWebApplication.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using System; + using System.Linq; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + using Microsoft.Web.Administration; + + /// <summary> + /// Creates or updates web applications within an existing web site in IIS. + /// </summary> + public class CreateWebApplication : Task { + /// <summary> + /// Gets or sets the name of the application pool that should host the web application. + /// </summary> + /// <value>The name of an existing application pool.</value> + public string ApplicationPoolName { get; set; } + + /// <summary> + /// Gets or sets the name of the web site under which to create the web application. + /// </summary> + /// <value>The name of the existing web site.</value> + [Required] + public string WebSiteName { get; set; } + + /// <summary> + /// Gets or sets the virtual paths within the web site that will access these applications. + /// </summary> + /// <value>The virtual path, which must start with '/'.</value> + [Required] + public ITaskItem[] VirtualPaths { get; set; } + + /// <summary> + /// Gets or sets the full file system paths to the web applications. + /// </summary> + /// <value>The physical path.</value> + [Required] + public ITaskItem[] PhysicalPaths { get; set; } + + /// <summary> + /// Executes this instance. + /// </summary> + /// <returns>A value indicating whether the task completed successfully.</returns> + public override bool Execute() { + var serverManager = new ServerManager(); + + if (this.PhysicalPaths.Length != this.VirtualPaths.Length) { + Log.LogError(TaskStrings.MismatchingArrayLengths, "PhysicalPath", "VirtualPath"); + return false; + } + + if (this.VirtualPaths.Length == 0) { + // Nothing to do. + return true; + } + + // Find the root web site that this web application will be created under. + var site = serverManager.Sites.FirstOrDefault(s => string.Equals(s.Name, this.WebSiteName, StringComparison.OrdinalIgnoreCase)); + if (site == null) { + Log.LogError(TaskStrings.NoMatchingWebSiteFound, this.WebSiteName); + return false; + } + + Log.LogMessage(MessageImportance.Normal, "Creating web applications under web site: {0}", site.Name); + + for (int i = 0; i < this.PhysicalPaths.Length; i++) { + string physicalPath = this.PhysicalPaths[i].ItemSpec; + string virtualPath = this.VirtualPaths[i].ItemSpec; + + Log.LogMessage(MessageImportance.Normal, "\t{0} -> {1}", virtualPath, physicalPath); + + var app = site.Applications.FirstOrDefault(a => string.Equals(a.Path, virtualPath, StringComparison.OrdinalIgnoreCase)); + if (app == null) { + app = site.Applications.Add(virtualPath, physicalPath); + } else { + // Ensure physical path is set correctly. + var appRoot = app.VirtualDirectories.First(vd => vd.Path == "/"); + appRoot.PhysicalPath = physicalPath; + } + + if (!string.IsNullOrEmpty(this.ApplicationPoolName)) { + app.ApplicationPoolName = this.ApplicationPoolName; + } + } + + serverManager.CommitChanges(); + return true; + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/CustomMsBuildTasks.sln b/src/DotNetOpenAuth.BuildTasks/CustomMsBuildTasks.sln new file mode 100644 index 0000000..6eae4e0 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/CustomMsBuildTasks.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.BuildTasks", "DotNetOpenAuth.BuildTasks.csproj", "{AC231A51-EF60-437C-A33F-AF8ADEB8EB74}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AC231A51-EF60-437C-A33F-AF8ADEB8EB74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC231A51-EF60-437C-A33F-AF8ADEB8EB74}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC231A51-EF60-437C-A33F-AF8ADEB8EB74}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC231A51-EF60-437C-A33F-AF8ADEB8EB74}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/DotNetOpenAuth.BuildTasks/DeleteWebApplication.cs b/src/DotNetOpenAuth.BuildTasks/DeleteWebApplication.cs new file mode 100644 index 0000000..930a8c4 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/DeleteWebApplication.cs @@ -0,0 +1,66 @@ +//----------------------------------------------------------------------- +// <copyright file="DeleteWebApplication.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using System; + using System.Linq; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + using Microsoft.Web.Administration; + + /// <summary> + /// Deletes a web application from IIS. + /// </summary> + public class DeleteWebApplication : Task { + /// <summary> + /// Gets or sets the name of the web site under which to create the web application. + /// </summary> + /// <value>The name of the existing web site.</value> + [Required] + public string WebSiteName { get; set; } + + /// <summary> + /// Gets or sets the virtual paths within the web site that will access these applications. + /// </summary> + /// <value>The virtual path, which must start with '/'.</value> + [Required] + public ITaskItem[] VirtualPaths { get; set; } + + /// <summary> + /// Executes this instance. + /// </summary> + /// <returns>A value indicating whether the task completed successfully.</returns> + public override bool Execute() { + var serverManager = new ServerManager(); + + // Find the root web site that this web application will be created under. + var site = serverManager.Sites.FirstOrDefault(s => string.Equals(s.Name, this.WebSiteName, StringComparison.OrdinalIgnoreCase)); + if (site == null) { + Log.LogMessage(MessageImportance.Low, TaskStrings.NoMatchingWebSiteFound, this.WebSiteName); + return true; + } + + if (this.VirtualPaths.Length == 0) { + // Nothing to do. + return true; + } + + foreach (ITaskItem path in this.VirtualPaths) { + var app = site.Applications.FirstOrDefault(a => string.Equals(a.Path, path.ItemSpec, StringComparison.OrdinalIgnoreCase)); + if (app != null) { + site.Applications.Remove(app); + Log.LogMessage(MessageImportance.Normal, TaskStrings.DeletedWebApplication, app.Path); + } else { + Log.LogMessage(MessageImportance.Low, TaskStrings.WebApplicationNotFoundSoNotDeleted, path.ItemSpec); + } + } + + serverManager.CommitChanges(); + + return true; + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj new file mode 100644 index 0000000..4eb920e --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.30729</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{AC231A51-EF60-437C-A33F-AF8ADEB8EB74}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>DotNetOpenAuth.BuildTasks</RootNamespace> + <AssemblyName>DotNetOpenAuth.BuildTasks</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\lib\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>..\..\lib\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Microsoft.Build.Engine" /> + <Reference Include="Microsoft.Build.Framework" /> + <Reference Include="Microsoft.Build.Utilities.v3.5"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="Microsoft.Web.Administration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>$(SystemRoot)\System32\inetsrv\Microsoft.Web.Administration.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="ChangeProjectReferenceToAssemblyReference.cs" /> + <Compile Include="CompareFiles.cs" /> + <Compile Include="ChangeAssemblyReference.cs" /> + <Compile Include="CreateWebApplication.cs" /> + <Compile Include="DeleteWebApplication.cs" /> + <Compile Include="FilterItems.cs" /> + <Compile Include="GetBuildVersion.cs" /> + <Compile Include="CheckAdminRights.cs" /> + <Compile Include="ReSignDelaySignedAssemblies.cs" /> + <Compile Include="SetEnvironmentVariable.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="SignatureVerification.cs" /> + <Compile Include="SnToolTask.cs" /> + <Compile Include="TaskStrings.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>TaskStrings.resx</DependentUpon> + </Compile> + <Compile Include="Trim.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="TaskStrings.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>TaskStrings.Designer.cs</LastGenOutput> + </EmbeddedResource> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.BuildTasks/FilterItems.cs b/src/DotNetOpenAuth.BuildTasks/FilterItems.cs new file mode 100644 index 0000000..97631c6 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/FilterItems.cs @@ -0,0 +1,24 @@ +namespace DotNetOpenAuth.BuildTasks { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Microsoft.Build.Utilities; + using Microsoft.Build.Framework; + + public class FilterItems : Task { + [Required] + public ITaskItem[] InputItems { get; set; } + + [Required] + public ITaskItem[] StartsWithAny { get; set; } + + [Output] + public ITaskItem[] FilteredItems { get; set; } + + public override bool Execute() { + FilteredItems = InputItems.Where(item => StartsWithAny.Any(filter => item.ItemSpec.StartsWith(filter.ItemSpec, StringComparison.OrdinalIgnoreCase))).ToArray(); + return true; + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs b/src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs new file mode 100644 index 0000000..e40eb78 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/GetBuildVersion.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Build.Utilities; +using Microsoft.Build.Framework; +using System.IO; + +namespace DotNetOpenAuth.BuildTasks { + public class GetBuildVersion : Task { + + /// <summary> + /// Gets the version string to use in the compiled assemblies. + /// </summary> + [Output] + public string Version { get; private set; } + + /// <summary> + /// The file that contains the version base (Major.Minor.Build) to use. + /// </summary> + [Required] + public string VersionFile { get; set; } + + public override bool Execute() { + try { + Version typedVersion = ReadVersionFromFile(); + typedVersion = new Version(typedVersion.Major, typedVersion.Minor, typedVersion.Build, CalculateJDate(DateTime.Now)); + Version = typedVersion.ToString(); + } catch (ArgumentOutOfRangeException ex) { + Log.LogErrorFromException(ex); + return false; + } + + return true; + } + + private Version ReadVersionFromFile() { + string[] lines = File.ReadAllLines(VersionFile); + string versionLine = lines[0]; + return new Version(versionLine); + } + + private int CalculateJDate(DateTime date) { + int yearLastDigit = date.Year % 10; + DateTime firstOfYear = new DateTime(date.Year, 1, 1); + int dayOfYear = (date - firstOfYear).Days + 1; + int jdate = yearLastDigit * 1000 + dayOfYear; + return jdate; + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/Properties/AssemblyInfo.cs b/src/DotNetOpenAuth.BuildTasks/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6fdcc21 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CustomMsBuildTasks")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CustomMsBuildTasks")] +[assembly: AssemblyCopyright("Copyright © 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("952e3aaa-5dc6-4b71-8c9c-6b485263be19")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/DotNetOpenAuth.BuildTasks/ReSignDelaySignedAssemblies.cs b/src/DotNetOpenAuth.BuildTasks/ReSignDelaySignedAssemblies.cs new file mode 100644 index 0000000..a0ba386 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/ReSignDelaySignedAssemblies.cs @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------- +// <copyright file="ReSignDelaySignedAssemblies.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using System; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + + public class ReSignDelaySignedAssemblies : SnToolTask { + /// <summary> + /// Gets or sets the key file to use for signing. + /// </summary> + public ITaskItem KeyFile { get; set; } + + /// <summary> + /// Gets or sets the key container. + /// </summary> + public ITaskItem KeyContainer { get; set; } + + /// <summary> + /// Gets or sets the assemblies to re-sign. + /// </summary> + public ITaskItem[] Assemblies { get; set; } + + /// <summary> + /// Generates the command line commands. + /// </summary> + protected override string GenerateCommandLineCommands() { + ////if (this.Assemblies.Length != 1) { + //// throw new NotSupportedException("Exactly 1 assembly for signing is supported."); + ////} + CommandLineBuilder args = new CommandLineBuilder(); + args.AppendSwitch("-q"); + + if (this.KeyFile != null) { + args.AppendSwitch("-R"); + } else if (this.KeyContainer != null) { + args.AppendSwitch("-Rc"); + } else { + throw new InvalidOperationException("Either KeyFile or KeyContainer must be set."); + } + + args.AppendFileNameIfNotNull(this.Assemblies[0]); + if (this.KeyFile != null) { + args.AppendFileNameIfNotNull(this.KeyFile); + } else { + args.AppendFileNameIfNotNull(this.KeyContainer); + } + + return args.ToString(); + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/SetEnvironmentVariable.cs b/src/DotNetOpenAuth.BuildTasks/SetEnvironmentVariable.cs new file mode 100644 index 0000000..2de5976 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/SetEnvironmentVariable.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.Build.Utilities; +using Microsoft.Build.Framework; + +namespace DotNetOpenAuth.BuildTasks { + public class SetEnvironmentVariable : Task { + public SetEnvironmentVariable() { + Scope = EnvironmentVariableTarget.Process; + } + + /// <summary> + /// The name of the environment variable to set or clear. + /// </summary> + [Required] + public string Name { get; set; } + /// <summary> + /// The value of the environment variable, or the empty string to clear it. + /// </summary> + [Required] + public string Value { get; set; } + /// <summary> + /// The target environment for the variable. Machine, User, or Process. + /// </summary> + public EnvironmentVariableTarget Scope { get; set; } + + public override bool Execute() { + Environment.SetEnvironmentVariable(Name, Value, Scope); + return true; + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/SignatureVerification.cs b/src/DotNetOpenAuth.BuildTasks/SignatureVerification.cs new file mode 100644 index 0000000..2e69926 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/SignatureVerification.cs @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------- +// <copyright file="SignatureVerification.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using Microsoft.Build.Utilities; + + public class SignatureVerification : SnToolTask { + /// <summary> + /// Gets or sets a value indicating whether to register the given assembly and public key token + /// for skip verification or clear any pre-existing skip verification entry. + /// </summary> + public bool SkipVerification { get; set; } + + /// <summary> + /// Gets or sets the name of the assembly. + /// </summary> + /// <value>The name of the assembly.</value> + public string AssemblyName { get; set; } + + /// <summary> + /// Gets or sets the public key token. + /// </summary> + /// <value>The public key token.</value> + public string PublicKeyToken { get; set; } + + /// <summary> + /// Generates the command line commands. + /// </summary> + protected override string GenerateCommandLineCommands() { + CommandLineBuilder builder = new CommandLineBuilder(); + builder.AppendSwitch("-q"); + if (this.SkipVerification) { + builder.AppendSwitch("-Vr"); + } else { + builder.AppendSwitch("-Vu"); + } + + builder.AppendFileNameIfNotNull(this.AssemblyName + "," + this.PublicKeyToken); + return builder.ToString(); + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/SnToolTask.cs b/src/DotNetOpenAuth.BuildTasks/SnToolTask.cs new file mode 100644 index 0000000..1c32632 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/SnToolTask.cs @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------- +// <copyright file="SnToolTask.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using System; + using System.IO; + using Microsoft.Build.Utilities; + + public abstract class SnToolTask : ToolTask { + /// <summary> + /// Gets the name of the tool. + /// </summary> + /// <value>The name of the tool.</value> + protected override string ToolName { + get { return "sn.exe"; } + } + + /// <summary> + /// Generates the full path to tool. + /// </summary> + protected override string GenerateFullPathToTool() { + string[] versions = new[] { "v6.0A", "v6.1" }; + string fullPath = null; + foreach (string version in versions) { + fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Microsoft SDKs\Windows\" + version + @"\bin\" + this.ToolName); + if (File.Exists(fullPath)) { + return fullPath; + } + } + + throw new FileNotFoundException("Unable to find sn.exe tool.", fullPath); + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/TaskStrings.Designer.cs b/src/DotNetOpenAuth.BuildTasks/TaskStrings.Designer.cs new file mode 100644 index 0000000..a727695 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/TaskStrings.Designer.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:2.0.50727.4918 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace DotNetOpenAuth.BuildTasks { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class TaskStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal TaskStrings() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DotNetOpenAuth.BuildTasks.TaskStrings", typeof(TaskStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// Looks up a localized string similar to Web application '{0}' deleted.. + /// </summary> + internal static string DeletedWebApplication { + get { + return ResourceManager.GetString("DeletedWebApplication", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to The {0} and {1} properties must be set to arrays of equal length.. + /// </summary> + internal static string MismatchingArrayLengths { + get { + return ResourceManager.GetString("MismatchingArrayLengths", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to No web site with the name '{0}' found.. + /// </summary> + internal static string NoMatchingWebSiteFound { + get { + return ResourceManager.GetString("NoMatchingWebSiteFound", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Web application '{0}' was not found, so it was not deleted.. + /// </summary> + internal static string WebApplicationNotFoundSoNotDeleted { + get { + return ResourceManager.GetString("WebApplicationNotFoundSoNotDeleted", resourceCulture); + } + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/TaskStrings.resx b/src/DotNetOpenAuth.BuildTasks/TaskStrings.resx new file mode 100644 index 0000000..2aaa32e --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/TaskStrings.resx @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="DeletedWebApplication" xml:space="preserve"> + <value>Web application '{0}' deleted.</value> + </data> + <data name="MismatchingArrayLengths" xml:space="preserve"> + <value>The {0} and {1} properties must be set to arrays of equal length.</value> + </data> + <data name="NoMatchingWebSiteFound" xml:space="preserve"> + <value>No web site with the name '{0}' found.</value> + </data> + <data name="WebApplicationNotFoundSoNotDeleted" xml:space="preserve"> + <value>Web application '{0}' was not found, so it was not deleted.</value> + </data> +</root>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.BuildTasks/Trim.cs b/src/DotNetOpenAuth.BuildTasks/Trim.cs new file mode 100644 index 0000000..1cc943e --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/Trim.cs @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------- +// <copyright file="Trim.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + + /// <summary> + /// Trims item identities. + /// </summary> + public class Trim : Task { + /// <summary> + /// Gets or sets the characters that should be trimmed off if found at the start of items' ItemSpecs. + /// </summary> + public string StartCharacters { get; set; } + + /// <summary> + /// Gets or sets the characters that should be trimmed off if found at the end of items' ItemSpecs. + /// </summary> + public string EndCharacters { get; set; } + + /// <summary> + /// Gets or sets the items with ItemSpec's to be trimmed. + /// </summary> + [Required] + public ITaskItem[] Inputs { get; set; } + + /// <summary> + /// Gets or sets the items with trimmed ItemSpec strings. + /// </summary> + [Output] + public ITaskItem[] Outputs { get; set; } + + /// <summary> + /// Executes this instance. + /// </summary> + /// <returns>A value indicating whether the task completed successfully.</returns> + public override bool Execute() { + this.Outputs = new ITaskItem[this.Inputs.Length]; + for (int i = 0; i < this.Inputs.Length; i++) { + this.Outputs[i] = new TaskItem(this.Inputs[i]); + if (!string.IsNullOrEmpty(this.StartCharacters)) { + this.Outputs[i].ItemSpec = this.Outputs[i].ItemSpec.TrimStart(this.StartCharacters.ToCharArray()); + } + if (!string.IsNullOrEmpty(this.EndCharacters)) { + this.Outputs[i].ItemSpec = this.Outputs[i].ItemSpec.TrimEnd(this.EndCharacters.ToCharArray()); + } + } + + return true; + } + } +} diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj index f9ec80e..414d3d0 100644 --- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj +++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj @@ -53,9 +53,10 @@ <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> - <PropertyGroup Condition=" '$(Sign)' == 'true' "> + <PropertyGroup> <SignAssembly>true</SignAssembly> - <AssemblyOriginatorKeyFile>..\official-build-key.pfx</AssemblyOriginatorKeyFile> + <DelaySign>true</DelaySign> + <AssemblyOriginatorKeyFile>..\official-build-key.pub</AssemblyOriginatorKeyFile> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU' "> <DebugSymbols>true</DebugSymbols> diff --git a/src/DotNetOpenAuth.vsmdi b/src/DotNetOpenAuth.vsmdi index 8874d7e..bed7c96 100644 --- a/src/DotNetOpenAuth.vsmdi +++ b/src/DotNetOpenAuth.vsmdi @@ -144,7 +144,7 @@ <TestLink id="f4537b23-bb5e-5c6f-da53-64b34472f0dc" name="ChannelGetter" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="75fa4664-bb0e-3a54-de29-c18ac712b231" name="Mode" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="94ba9fd3-851d-13b2-e273-6294b167c13e" name="HttpsSignatureVerification" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> - <TestLink id="ff78d828-b437-aaeb-e48a-85a5ad1fe396" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> + <TestLink id="cbfeb75b-d031-7df3-c281-3c9e1c450042" name="CtorFromRequest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="5460f9c6-ec9d-969d-5aff-b946d6776e25" name="CtorWithNullProtocolMessage" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="d5f4e610-eabe-1dc0-ab3f-7c9dcb17fcc3" name="CtorImpliedLocalIdentifier" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="64d8c630-76c6-e420-937b-19c889dd7f59" name="CtorNonMessageType" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> @@ -241,7 +241,7 @@ <TestLink id="704a32d0-3f50-d462-f767-fd9cf1981b7f" name="ProviderVersion" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="f362baf3-da5b-1b8c-39ae-7c9b2051270a" name="AuthenticationTimeUtcSetUtc" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="3bb818b4-5423-ad91-8cd9-8606ec85d2cb" name="ReadFromRequestAuthorizationScattered" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> - <TestLink id="cbfeb75b-d031-7df3-c281-3c9e1c450042" name="CtorFromRequest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> + <TestLink id="30f3c12b-e510-de63-5acd-ae8e32866592" name="CreateQueryString" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="9302541c-9c30-9ce7-66db-348ee4e9f6ee" name="UnifyExtensionsAsSregWithSreg" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="997253fb-7591-c151-1705-02976b400f27" name="AddAttributeTwice" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="88ae5661-da27-91c5-4d78-1f43cd716127" name="EqualsTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> @@ -331,7 +331,7 @@ <TestLink id="d083396b-db68-1318-e62b-6dc9f89e26bd" name="CtorDefault" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="2f6a81c5-cd04-0ca0-22ee-d4213f9cf147" name="EqualityTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="72d3f240-67f2-0b04-bd31-a99c3f7a8e12" name="SharedAssociationPositive" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> - <TestLink id="30f3c12b-e510-de63-5acd-ae8e32866592" name="CreateQueryString" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> + <TestLink id="3cd9447e-9ffd-f706-37bb-e7eb5828e430" name="InvalidRealmEmpty" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="28fe030c-d36e-13cf-475c-7813210bf886" name="AddAttributeRequestAgain" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="e7a41771-7dda-be44-0755-e06300f3cd92" name="IsSaneTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="2e23dc5a-93ea-11a5-d00d-02d294794e5f" name="AssociateDiffieHellmanOverHttps" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> @@ -349,6 +349,7 @@ <TestLink id="313faac6-6357-5468-2d4d-4c9fba001678" name="TryParseNoThrow" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="7cbe4350-38d0-db7e-335c-93d9398fc95b" name="ExtensionOnlyFacadeLevel" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="2f5cfa57-bcb4-39af-e769-2d7c34e2598e" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> + <TestLink id="ff78d828-b437-aaeb-e48a-85a5ad1fe396" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="29e45877-ca7a-85de-5c39-6d43befe1a1e" name="DiscoveryRequireSslWithInsecureXrdsButSecureLinkTags" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="c351c660-d583-d869-0129-2e312665d815" name="CtorBlank" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="f063a3c6-5a36-2801-53d7-5142416199a9" name="ImplicitConversionFromStringTests" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> @@ -405,7 +406,6 @@ <TestLink id="7cdabb8a-aefa-e90e-c32e-047404b64c2d" name="SerializeTest" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="f6979feb-7016-4e2b-14e2-e6c2c392419f" name="RemoveByKeyValuePair" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="58df167c-cf19-351c-cb09-5c52ae9f97be" name="DeserializeNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> - <TestLink id="80719076-10fd-20a7-7ff3-a0aa2bc661cb" name="CtorNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="a778f331-f14e-9d6e-f942-a023423540f6" name="Ctor" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="a1ff4ada-fe5d-d2f3-b7fb-8e72db02b3c3" name="Full" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="be00d3ef-f24d-eb8a-d251-4d691736ee6f" name="AddAttributeRequestNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> @@ -454,7 +454,7 @@ <TestLink id="62c6ee5b-ac29-461c-2373-bf620e948825" name="InvalidRealmNoScheme" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="115283b9-d95c-9a92-2197-96685ee8e96a" name="TwoExtensionsSameTypeUri" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="352d9fd6-cf38-4b72-478f-e3e17ace55f5" name="NoValueLoose" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> - <TestLink id="3cd9447e-9ffd-f706-37bb-e7eb5828e430" name="InvalidRealmEmpty" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> + <TestLink id="80719076-10fd-20a7-7ff3-a0aa2bc661cb" name="CtorNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="b2b54c72-1d26-8c28-ebf5-7a5a4beeec43" name="VerifyNonZeroLengthOnNull" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="9684f7bf-cdda-a2c5-0822-29cb0add3835" name="ResponseNonceGetter" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> <TestLink id="c4001e1c-75ad-236b-284f-318905d2bc3a" name="CreateRequestOnNonOpenID" storage="..\bin\debug\dotnetopenauth.test.dll" type="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestElement, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.ObjectModel, PublicKeyToken=b03f5f7f11d50a3a" /> diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj index 3da8526..aba573d 100644 --- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj +++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj @@ -25,7 +25,7 @@ <DocumentationFile>..\..\bin\Debug\DotNetOpenAuth.xml</DocumentationFile> <RunCodeAnalysis>false</RunCodeAnalysis> <CodeAnalysisRules>-Microsoft.Design#CA1054;-Microsoft.Design#CA1056;-Microsoft.Design#CA1055</CodeAnalysisRules> - <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking> + <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking> <CodeContractsCustomRewriterAssembly> </CodeContractsCustomRewriterAssembly> <CodeContractsCustomRewriterClass> @@ -48,6 +48,8 @@ <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies> <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations> <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface> + <CodeContractsRuntimeThrowOnFailure>False</CodeContractsRuntimeThrowOnFailure> + <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> @@ -60,7 +62,7 @@ <DocumentationFile>..\..\bin\Release\DotNetOpenAuth.xml</DocumentationFile> <RunCodeAnalysis>true</RunCodeAnalysis> <CodeAnalysisRules>-Microsoft.Design#CA1054;-Microsoft.Design#CA1056;-Microsoft.Design#CA1055</CodeAnalysisRules> - <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking> + <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking> <CodeContractsCustomRewriterAssembly> </CodeContractsCustomRewriterAssembly> <CodeContractsCustomRewriterClass> @@ -81,16 +83,21 @@ <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine> <CodeContractsRunInBackground>True</CodeContractsRunInBackground> <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies> + <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface> + <CodeContractsRuntimeThrowOnFailure>False</CodeContractsRuntimeThrowOnFailure> + <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires> + <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations> </PropertyGroup> - <PropertyGroup Condition=" '$(Sign)' == 'true' "> + <PropertyGroup> <SignAssembly>true</SignAssembly> - <AssemblyOriginatorKeyFile>..\official-build-key.pfx</AssemblyOriginatorKeyFile> + <DelaySign>true</DelaySign> + <AssemblyOriginatorKeyFile>..\official-build-key.pub</AssemblyOriginatorKeyFile> <DefineConstants>$(DefineConstants);StrongNameSigned</DefineConstants> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU' "> <DebugSymbols>true</DebugSymbols> <OutputPath>..\..\bin\CodeAnalysis\</OutputPath> - <DefineConstants>CONTRACTS_FULL;DEBUG;TRACE</DefineConstants> + <DefineConstants>$(DefineConstants);CONTRACTS_FULL;DEBUG;TRACE</DefineConstants> <DocumentationFile>..\..\bin\CodeAnalysis\DotNetOpenAuth.xml</DocumentationFile> <DebugType>full</DebugType> <PlatformTarget>AnyCPU</PlatformTarget> diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/ICombinedOpenIdProviderTokenManager.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/ICombinedOpenIdProviderTokenManager.cs index ff004cb..dd28e71 100644 --- a/src/DotNetOpenAuth/OAuth/ChannelElements/ICombinedOpenIdProviderTokenManager.cs +++ b/src/DotNetOpenAuth/OAuth/ChannelElements/ICombinedOpenIdProviderTokenManager.cs @@ -15,7 +15,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { /// This interface should be implemented by the same class that implements /// <see cref="ITokenManager"/> in order to enable the OpenID+OAuth extension. /// </remarks> - public interface ICombinedOpenIdProviderTokenManager { + public interface ICombinedOpenIdProviderTokenManager : IOpenIdOAuthTokenManager, ITokenManager { /// <summary> /// Gets the OAuth consumer key for a given OpenID relying party realm. /// </summary> diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/PlaintextSigningBindingElement.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/PlaintextSigningBindingElement.cs index 9f99066..22e5f20 100644 --- a/src/DotNetOpenAuth/OAuth/ChannelElements/PlaintextSigningBindingElement.cs +++ b/src/DotNetOpenAuth/OAuth/ChannelElements/PlaintextSigningBindingElement.cs @@ -41,7 +41,12 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { /// <param name="message">The message that needs to be signed.</param> /// <returns>True if this binding element can be used to sign the message. False otherwise.</returns> protected override bool IsMessageApplicable(ITamperResistantOAuthMessage message) { - return string.Equals(message.Recipient.Scheme, "https", StringComparison.OrdinalIgnoreCase); + if (string.Equals(message.Recipient.Scheme, "https", StringComparison.OrdinalIgnoreCase)) { + return true; + } else { + Logger.Bindings.DebugFormat("The {0} element will not sign this message because the URI scheme is not https.", this.GetType().Name); + return false; + } } /// <summary> diff --git a/src/DotNetOpenAuth/OAuth/ServiceProvider.cs b/src/DotNetOpenAuth/OAuth/ServiceProvider.cs index 242e0db..9c37815 100644 --- a/src/DotNetOpenAuth/OAuth/ServiceProvider.cs +++ b/src/DotNetOpenAuth/OAuth/ServiceProvider.cs @@ -236,11 +236,12 @@ namespace DotNetOpenAuth.OAuth { /// <summary> /// Gets the OAuth authorization request included with an OpenID authentication - /// request. + /// request, if there is one. /// </summary> /// <param name="openIdRequest">The OpenID authentication request.</param> /// <returns> - /// The scope of access the relying party is requesting. + /// The scope of access the relying party is requesting, or null if no OAuth request + /// is present. /// </returns> /// <remarks> /// <para>Call this method rather than simply extracting the OAuth extension @@ -270,24 +271,43 @@ namespace DotNetOpenAuth.OAuth { return authzRequest; } - /// <summary> + /// <summary> /// Attaches the authorization response to an OpenID authentication response. /// </summary> /// <param name="openIdAuthenticationRequest">The OpenID authentication request.</param> - /// <param name="consumerKey">The consumer key. May and should be <c>null</c> if and only if <paramref name="scope"/> is null.</param> + /// <param name="consumerKey">The consumer key. Must be <c>null</c> if and only if <paramref name="scope"/> is null.</param> /// <param name="scope">The approved access scope. Use <c>null</c> to indicate no access was granted. The empty string will be interpreted as some default level of access is granted.</param> [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "We want to take IAuthenticationRequest because that's the only supported use case.")] - public void AttachAuthorizationResponse(IAuthenticationRequest openIdAuthenticationRequest, string consumerKey, string scope) { + [Obsolete("Call the overload that doesn't take a consumerKey instead.")] + public void AttachAuthorizationResponse(IHostProcessedRequest openIdAuthenticationRequest, string consumerKey, string scope) { Contract.Requires(openIdAuthenticationRequest != null); Contract.Requires((consumerKey == null) == (scope == null)); Contract.Requires(this.TokenManager is IOpenIdOAuthTokenManager); ErrorUtilities.VerifyArgumentNotNull(openIdAuthenticationRequest, "openIdAuthenticationRequest"); - var openidTokenManager = this.TokenManager as IOpenIdOAuthTokenManager; + var openidTokenManager = this.TokenManager as ICombinedOpenIdProviderTokenManager; ErrorUtilities.VerifyOperation(openidTokenManager != null, OAuthStrings.OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface, typeof(IOpenIdOAuthTokenManager).FullName); + ErrorUtilities.VerifyArgument(consumerKey == null || consumerKey == openidTokenManager.GetConsumerKey(openIdAuthenticationRequest.Realm), "The consumer key and the realm did not match according to the token manager."); + + this.AttachAuthorizationResponse(openIdAuthenticationRequest, scope); + } + + /// <summary> + /// Attaches the authorization response to an OpenID authentication response. + /// </summary> + /// <param name="openIdAuthenticationRequest">The OpenID authentication request.</param> + /// <param name="scope">The approved access scope. Use <c>null</c> to indicate no access was granted. The empty string will be interpreted as some default level of access is granted.</param> + [SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters", Justification = "We want to take IAuthenticationRequest because that's the only supported use case.")] + public void AttachAuthorizationResponse(IHostProcessedRequest openIdAuthenticationRequest, string scope) { + Contract.Requires(openIdAuthenticationRequest != null); + Contract.Requires(this.TokenManager is IOpenIdOAuthTokenManager); + ErrorUtilities.VerifyArgumentNotNull(openIdAuthenticationRequest, "openIdAuthenticationRequest"); + var openidTokenManager = this.TokenManager as ICombinedOpenIdProviderTokenManager; + ErrorUtilities.VerifyOperation(openidTokenManager != null, OAuthStrings.OpenIdOAuthExtensionRequiresSpecialTokenManagerInterface, typeof(ICombinedOpenIdProviderTokenManager).FullName); IOpenIdMessageExtension response; if (scope != null) { // Generate an authorized request token to return to the relying party. + string consumerKey = openidTokenManager.GetConsumerKey(openIdAuthenticationRequest.Realm); var approvedResponse = new AuthorizationApprovedResponse { RequestToken = this.TokenGenerator.GenerateRequestToken(consumerKey), Scope = scope, diff --git a/src/DotNetOpenAuth/OAuth/WebConsumer.cs b/src/DotNetOpenAuth/OAuth/WebConsumer.cs index 56d3029..d86444d 100644 --- a/src/DotNetOpenAuth/OAuth/WebConsumer.cs +++ b/src/DotNetOpenAuth/OAuth/WebConsumer.cs @@ -120,7 +120,8 @@ namespace DotNetOpenAuth.OAuth { } // Prepare a message to exchange the request token for an access token. - var requestAccess = new AuthorizedTokenRequest(this.ServiceProvider.AccessTokenEndpoint, this.ServiceProvider.Version) { + // We are careful to use a v1.0 message version so that the oauth_verifier is not required. + var requestAccess = new AuthorizedTokenRequest(this.ServiceProvider.AccessTokenEndpoint, Protocol.V10.Version) { RequestToken = positiveAuthorization.RequestToken, ConsumerKey = this.ConsumerKey, }; diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs index 9912d0b..060ef21 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/AuthenticationRequest.cs @@ -345,11 +345,12 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { /// before calling this method. /// </remarks> private static IEnumerable<AuthenticationRequest> CreateInternal(Identifier userSuppliedIdentifier, OpenIdRelyingParty relyingParty, Realm realm, Uri returnToUrl, IEnumerable<ServiceEndpoint> serviceEndpoints, bool createNewAssociationsAsNeeded) { - Contract.Requires(userSuppliedIdentifier != null); - Contract.Requires(relyingParty != null); - Contract.Requires(realm != null); - Contract.Requires(serviceEndpoints != null); - Contract.Ensures(Contract.Result<IEnumerable<AuthenticationRequest>>() != null); + // DO NOT USE CODE CONTRACTS IN THIS METHOD, since it uses yield return + ErrorUtilities.VerifyArgumentNotNull(userSuppliedIdentifier, "userSuppliedIdentifier"); + ErrorUtilities.VerifyArgumentNotNull(relyingParty, "relyingParty"); + ErrorUtilities.VerifyArgumentNotNull(realm, "realm"); + ErrorUtilities.VerifyArgumentNotNull(serviceEndpoints, "serviceEndpoints"); + ////Contract.Ensures(Contract.Result<IEnumerable<AuthenticationRequest>>() != null); // If shared associations are required, then we had better have an association store. ErrorUtilities.VerifyOperation(!relyingParty.SecuritySettings.RequireAssociation || relyingParty.AssociationManager.HasAssociationStore, OpenIdStrings.AssociationStoreRequired); diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs index 8451dbd..c584580 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingPartyControlBase.cs @@ -73,6 +73,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { private const bool UsePersistentCookieDefault = false; /// <summary> + /// Default value of <see cref="LoginMode"/>. + /// </summary> + private const LoginSiteNotification LoginModeDefault = LoginSiteNotification.FormsAuthentication; + + /// <summary> /// The default value for the <see cref="RealmUrl"/> property. /// </summary> private const string RealmUrlDefault = "~/"; @@ -102,6 +107,11 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { private const string UsePersistentCookieViewStateKey = "UsePersistentCookie"; /// <summary> + /// The viewstate key to use for the <see cref="LoginMode"/> property. + /// </summary> + private const string LoginModeViewStateKey = "LoginMode"; + + /// <summary> /// The viewstate key to use for the <see cref="RealmUrl"/> property. /// </summary> private const string RealmUrlViewStateKey = "RealmUrl"; @@ -200,6 +210,25 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { #endregion /// <summary> + /// Methods of indicating to the rest of the web site that the user has logged in. + /// </summary> + public enum LoginSiteNotification { + /// <summary> + /// The rest of the web site is unaware that the user just completed an OpenID login. + /// </summary> + None, + + /// <summary> + /// After the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event is fired + /// the control automatically calls <see cref="System.Web.Security.FormsAuthentication.RedirectFromLoginPage(string, bool)"/> + /// with the <see cref="IAuthenticationResponse.ClaimedIdentifier"/> as the username + /// unless the <see cref="OpenIdRelyingPartyControlBase.LoggedIn"/> event handler sets + /// <see cref="OpenIdEventArgs.Cancel"/> property to true. + /// </summary> + FormsAuthentication, + } + + /// <summary> /// Gets or sets the <see cref="OpenIdRelyingParty"/> instance to use. /// </summary> /// <value>The default value is an <see cref="OpenIdRelyingParty"/> instance initialized according to the web.config file.</value> @@ -312,6 +341,16 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } /// <summary> + /// Gets or sets the way a completed login is communicated to the rest of the web site. + /// </summary> + [Bindable(true), DefaultValue(LoginModeDefault), Category(BehaviorCategory)] + [Description("The way a completed login is communicated to the rest of the web site.")] + public LoginSiteNotification LoginMode { + get { return (LoginSiteNotification)(this.ViewState[LoginModeViewStateKey] ?? LoginModeDefault); } + set { this.ViewState[LoginModeViewStateKey] = value; } + } + + /// <summary> /// Gets or sets a value indicating when to use a popup window to complete the login experience. /// </summary> /// <value>The default value is <see cref="PopupBehavior.Never"/>.</value> @@ -515,7 +554,14 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { } if (!args.Cancel) { - FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, this.UsePersistentCookie); + switch (this.LoginMode) { + case LoginSiteNotification.FormsAuthentication: + FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, this.UsePersistentCookie); + break; + case LoginSiteNotification.None: + default: + break; + } } } diff --git a/src/DotNetOpenAuth/Util.cs b/src/DotNetOpenAuth/Util.cs index 1a67966..aeeba88 100644 --- a/src/DotNetOpenAuth/Util.cs +++ b/src/DotNetOpenAuth/Util.cs @@ -11,6 +11,7 @@ namespace DotNetOpenAuth { using System.Net; using System.Reflection; using System.Text; + using DotNetOpenAuth.Messaging; /// <summary> /// A grab-bag utility class. @@ -74,7 +75,8 @@ namespace DotNetOpenAuth { return new DelayedToString<IEnumerable<KeyValuePair<K, V>>>( pairs, p => { - Contract.Requires(pairs != null); + ////Contract.Requires(pairs != null); // CC: anonymous method can't handle it + ErrorUtilities.VerifyArgumentNotNull(pairs, "pairs"); var dictionary = pairs as IDictionary<K, V>; StringBuilder sb = new StringBuilder(dictionary != null ? dictionary.Count * 40 : 200); foreach (var pair in pairs) { @@ -102,13 +104,15 @@ namespace DotNetOpenAuth { /// <param name="list">The list of elements.</param> /// <param name="multiLineElements">if set to <c>true</c>, special formatting will be applied to the output to make it clear where one element ends and the next begins.</param> /// <returns>An object whose ToString method will perform the actual work of generating the string.</returns> + [ContractVerification(false)] internal static object ToStringDeferred<T>(this IEnumerable<T> list, bool multiLineElements) { return new DelayedToString<IEnumerable<T>>( list, l => { - Contract.Requires(l != null); + ////Contract.Requires(l != null); // CC: anonymous method can't handle it + ErrorUtilities.VerifyArgumentNotNull(l, "l"); string newLine = Environment.NewLine; - Contract.Assume(newLine != null && newLine.Length > 0); + ////Contract.Assume(newLine != null && newLine.Length > 0); // CC: anonymous method can't handle it StringBuilder sb = new StringBuilder(); if (multiLineElements) { sb.AppendLine("[{"); diff --git a/src/official-build-key.pub b/src/official-build-key.pub Binary files differnew file mode 100644 index 0000000..6e68f53 --- /dev/null +++ b/src/official-build-key.pub diff --git a/src/version.txt b/src/version.txt index e4604e3..15a2799 100644 --- a/src/version.txt +++ b/src/version.txt @@ -1 +1 @@ -3.2.1 +3.3.0 diff --git a/tools/DotNetOpenAuth.Common.Settings.targets b/tools/DotNetOpenAuth.Common.Settings.targets index 3257583..951366e 100644 --- a/tools/DotNetOpenAuth.Common.Settings.targets +++ b/tools/DotNetOpenAuth.Common.Settings.targets @@ -1,11 +1,24 @@ -<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" InitialTargets="InitializeProps"> <PropertyGroup> <ProductName>DotNetOpenAuth</ProductName> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <ProjectRoot Condition="'$(ProjectRoot)' == ''">$(MSBuildProjectDirectory)</ProjectRoot> - <OutputPath>$(ProjectRoot)\bin\$(Configuration)</OutputPath> - <DocOutputPath>$(ProjectRoot)\doc</DocOutputPath> - <IntermediatePath>$(ProjectRoot)\obj\$(Configuration)</IntermediatePath> - <ToolsDir>$(ProjectRoot)\tools</ToolsDir> + <DropsRoot>$(ProjectRoot)\drops\$(Configuration)\</DropsRoot> + <OutputPath>$(ProjectRoot)\bin\$(Configuration)\</OutputPath> + <DocOutputPath>$(ProjectRoot)\doc\</DocOutputPath> + <IntermediatePath>$(ProjectRoot)\obj\$(Configuration)\</IntermediatePath> + <ToolsDir>$(ProjectRoot)\tools\</ToolsDir> + <PublicKeyFile>$(ProjectRoot)\src\official-build-key.pub</PublicKeyFile> + <KeyPairContainer>DotNetOpenAuth</KeyPairContainer> + <PublicKeyToken>2780CCD10D57B246</PublicKeyToken> </PropertyGroup> -</Project>
\ No newline at end of file + + <Import Project="$(ProjectRoot)\lib\DotNetOpenAuth.BuildTasks.targets" /> + + <Target Name="InitializeProps"> + <CheckAdminRights> + <Output TaskParameter="IsElevated" PropertyName="IsElevated" /> + </CheckAdminRights> + <Message Importance="High" Text="IsElevated = $(IsElevated)" /> + </Target> +</Project> diff --git a/tools/DotNetOpenAuth.Versioning.targets b/tools/DotNetOpenAuth.Versioning.targets index f4b12b0..65d212c 100644 --- a/tools/DotNetOpenAuth.Versioning.targets +++ b/tools/DotNetOpenAuth.Versioning.targets @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> - <!-- Import this .targets file to automaticaly generate AssemblyVersion + <!-- Import this .targets file to automatically generate AssemblyVersion attribute according to DotNetOpenAuth convention. --> <PropertyGroup> <ProjectRoot Condition="'$(ProjectRoot)' == ''">$(MSBuildProjectDirectory)\..\..</ProjectRoot> |