diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2010-02-20 13:55:13 -0800 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2010-02-20 13:55:13 -0800 |
commit | 5e219c5f01391d2d47b108d68c945fa9dcf7d9bc (patch) | |
tree | 3a2b38566e42ad77f720f41e773fdee64c04c109 | |
parent | 5e1a57ba973e31fa11875fc07fb317b5e2c582b7 (diff) | |
parent | f1718afbd134c9b4a5db2dfe3c3ec1f804312123 (diff) | |
download | DotNetOpenAuth-5e219c5f01391d2d47b108d68c945fa9dcf7d9bc.zip DotNetOpenAuth-5e219c5f01391d2d47b108d68c945fa9dcf7d9bc.tar.gz DotNetOpenAuth-5e219c5f01391d2d47b108d68c945fa9dcf7d9bc.tar.bz2 |
Merge branch 'master' into oauthWRAP
Conflicts:
src/DotNetOpenAuth/DotNetOpenAuth.csproj
74 files changed, 1872 insertions, 827 deletions
@@ -1,446 +1,49 @@ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(MSBuildProjectDirectory)\tools\DotNetOpenAuth.props"/> - <PropertyGroup> - <AutomatedBuild>true</AutomatedBuild> - <SolutionPath>$(ProjectRoot)src\$(ProductName).sln</SolutionPath> - <ILMergeOutputAssemblyDirectory>$(OutputPath)unified\</ILMergeOutputAssemblyDirectory> - <ILMergeOutputAssembly>$(ILMergeOutputAssemblyDirectory)$(ProductName).dll</ILMergeOutputAssembly> - <ProjectTemplatesLayoutPath>$(IntermediatePath)projecttemplates\</ProjectTemplatesLayoutPath> - - <VS2008ProjectTemplatesDirectory>$(IntermediatePath)VS2008projecttemplates\</VS2008ProjectTemplatesDirectory> - <ProjectTemplatesVsiDirectory>$(IntermediatePath)vsi\</ProjectTemplatesVsiDirectory> - - <VS2010ProjectTemplatesDirectory>$(IntermediatePath)VS2010projecttemplates\</VS2010ProjectTemplatesDirectory> - <ExtensionVsixLayoutDirectory>$(IntermediatePath)Vsix\</ExtensionVsixLayoutDirectory> - <ZipLevel>6</ZipLevel> - </PropertyGroup> - - <Import Project="$(ProjectRoot)tools\$(ProductName).Versioning.targets"/> - <Import Project="$(ProjectRoot)tools\Documentation.targets"/> - <Import Project="$(ProjectRoot)tools\Publish.targets"/> + <Import Project="$(MSBuildProjectDirectory)\tools\DotNetOpenAuth.automated.props"/> <Import Project="$(ProjectRoot)tools\Translation.targets"/> - <UsingTask AssemblyFile="$(ProjectRoot)lib\MSBuild.Community.Tasks.dll" TaskName="Zip"/> - <UsingTask AssemblyFile="$(ProjectRoot)lib\MSBuild.Community.Tasks.dll" TaskName="ILMerge"/> - <UsingTask AssemblyFile="$(ProjectRoot)lib\MSBuild.Community.Tasks.dll" TaskName="NUnit" /> <ItemGroup> - <SampleProjects Include="$(ProjectRoot)samples\**\*.csproj;$(ProjectRoot)samples\**\*.vbproj" /> - <SampleSites Include="OAuthConsumer;OAuthServiceProvider;InfoCardRelyingParty" /> - <ProjectTemplates Include="$(ProjectRoot)projecttemplates\**\*.csproj" /> - <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"> - <MSBuild Projects="$(SolutionPath)" Targets="Clean" /> - <ItemGroup> - <DirtyDirectories Include=" + <ProjectsInDrop Include=" + samples\tools.proj; + tools\drop.proj; + " /> + <ProjectsToPublish Include=" + samples\samples.proj; + doc\doc.proj; + " /> + + <ProjectsToClean Include=" + $(SolutionPath); + projecttemplates\projecttemplates.proj; + vsi\vsi.proj; + vsix\vsix.proj; + samples\samples.proj; + doc\doc.proj; + "/> + + <DirectoriesToClean Include=" $(ProjectRoot)bin; $(ProjectRoot)**\obj; $(DropsRoot); $(ProjectRoot)src\PrecompiledWeb; - $(ProjectTemplatesLayoutPath); " /> - <DirtyDirectories Include="@(SampleDirectories->'%(FullPath)\bin')" /> - <DirtyDirectories Include="@(SampleDirectories->'%(FullPath)\obj')" /> - <DirtyFiles Include=" - $(ProjectRoot)**\*~; - $(ProjectRoot)**\*.log*; - $(ProjectRoot)doc\$(ProductName).chm; - " /> - </ItemGroup> - <Delete Files="@(DirtyFiles)" /> - <RemoveDir Directories="@(DirtyDirectories)" /> - </Target> - - <Target Name="SkipVerification" Condition="'$(IsElevated)' == 'true'"> - <SignatureVerification SkipVerification="true" AssemblyName="*" PublicKeyToken="$(PublicKeyToken)" /> - </Target> - - <Target Name="BuildProduct" DependsOnTargets="SkipVerification"> - <MSBuild Projects="$(ProjectRoot)src\$(ProductName)\$(ProductName).csproj" /> - </Target> + <FilesToClean Include=" + $(ProjectRoot)**\*~; + $(ProjectRoot)**\*.log*; + $(ProjectRoot)doc\$(ProductName).chm; + " /> + </ItemGroup> <Target Name="BuildTests" DependsOnTargets="SkipVerification"> - <MSBuild Projects="$(SolutionPath)" Targets="DotNetOpenAuth_Test;DotNetOpenAuth_TestWeb" /> - </Target> - - <Target Name="BuildSamples" DependsOnTargets="SkipVerification"> - <MSBuild Projects="@(SampleProjects)" /> - <MSBuild Projects="$(SolutionPath)" Targets="@(SampleSites)" /> + <MSBuild Projects="$(SolutionPath)" Targets="DotNetOpenAuth_Test;DotNetOpenAuth_TestWeb" BuildInParallel="$(BuildInParallel)" /> </Target> <Target Name="Build" DependsOnTargets="SkipVerification"> - <MSBuild Projects="$(SolutionPath)" /> + <MSBuild Projects="$(SolutionPath)" BuildInParallel="$(BuildInParallel)" /> </Target> <Target Name="Rebuild" DependsOnTargets="SkipVerification"> - <MSBuild Projects="$(SolutionPath)" Targets="Rebuild" /> - </Target> - - <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 using key pair container $(KeyPairContainer)." /> - <ReSignDelaySignedAssemblies - KeyContainer="$(KeyPairContainer)" - Assemblies="@(DelaySignedAssemblies)" - Condition="Exists(%(Identity))" /> - </Target> - - <Target Name="ToolsLayout" DependsOnTargets="GetBuildVersion;_SetDropProperties;BuildUnifiedProduct"> - <PropertyGroup> - <ToolsDirectoryNoSlash>$(DropsRoot)$(ProductName)-Tools-$(BuildVersion)</ToolsDirectoryNoSlash> - <ToolsDirectory>$(ToolsDirectoryNoSlash)\</ToolsDirectory> - </PropertyGroup> - - <ItemGroup> - <ToolProjects Include="$(ProjectRoot)Samples\OpenIdOfflineProvider\OpenIdOfflineProvider.csproj" /> - </ItemGroup> - - <MSBuild Projects="@(ToolProjects)" /> - - <ItemGroup> - <OfflineProvider Include=" - $(OutputPath)**\*.dll; - $(OutputPath)OpenIdOfflineProvider.exe" - Exclude=" - $(OutputPath)$(ProductName).*; - $(ILMergeOutputAssembly); - "/> - <OfflineProviderTargets Include=" - @(OfflineProvider->'$(ToolsDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> - <OfflineProvider Include="$(ILMergeOutputAssembly)" /> - <OfflineProviderTargets Include="$(ToolsDirectory)$(ProductName).dll" /> - - <AllToolSources Include="@(OfflineProvider)" /> - <AllToolTargets Include="@(OfflineProviderTargets)" /> - </ItemGroup> - - <MakeDir Directories="@(ToolsDirectory)" /> - <Copy SourceFiles="@(AllToolSources)" DestinationFiles="@(AllToolTargets)" SkipUnchangedFiles="true" /> - - <!-- remove files that shouldn't be in the directory (perhaps from a previous version). --> - <Purge Directories="$(ToolsDirectory)" IntendedFiles="@(AllToolTargets)" /> - </Target> - - <Target Name="Tools" DependsOnTargets="ToolsLayout"> - <PropertyGroup> - <ToolsZip>$(ToolsDirectoryNoSlash).zip</ToolsZip> - </PropertyGroup> - - <Zip ZipFileName="$(ToolsZip)" - Files="@(AllToolTargets)" - WorkingDirectory="$(ToolsDirectory)" - ZipLevel="$(ZipLevel)" /> - </Target> - - <Target Name="BuildProjectTemplates"> - <!-- Deploy the latest SQL script first, so that the class library can embed the latest version. --> - <MSBuild Projects="$(ProjectRoot)projecttemplates\RelyingPartyDatabase\RelyingPartyDatabase.dbproj" Targets="Build;Deploy" /> - - <MSBuild Projects="@(ProjectTemplates)" /> - </Target> - - <Target Name="ProjectTemplatesLayout" DependsOnTargets="GetBuildVersion;BuildUnifiedProduct;ReSignDelaySignedAssemblies;BuildProjectTemplates"> - <ItemGroup> - <ProjectTemplatesSource Include="$(ProjectRoot)projecttemplates\**\*" - Exclude=" - $(ProjectRoot)projecttemplates\**\*.sln.cache; - $(ProjectRoot)projecttemplates\**\*.suo; - $(ProjectRoot)projecttemplates\**\*.gitignore; - $(ProjectRoot)projecttemplates\**\*.log*; - $(ProjectRoot)projecttemplates\**\*~; - $(ProjectRoot)projecttemplates\**\Settings.StyleCop; - $(ProjectRoot)projecttemplates\**\StyleCop.Cache; - $(ProjectRoot)projecttemplates\**\*.user; - $(ProjectRoot)projecttemplates\**\obj\**; - $(ProjectRoot)projecttemplates\**\bin\**; - $(ProjectRoot)projecttemplates\**\*.ldf; - $(ProjectRoot)projecttemplates\**\*.mdf; - "/> - <_ProjectTemplatesTransformSource Include="@(ProjectTemplatesSource)" Condition=" - '%(Extension)' == '.cs' - or '%(Extension)' == '.csproj' - or '%(Extension)' == '.sql' - or '%(Extension)' == '.config' - or '%(Extension)' == '.Master' - or '%(Extension)' == '.aspx' - or '%(Extension)' == '.ascx' - or '%(Extension)' == '.asax' - or '%(Extension)' == '.ashx' - "> - <BeforeTokens>%(RecursiveDir)</BeforeTokens> - <AfterTokens>$safeprojectname$</AfterTokens> - <!-- Projects can get changed after the transform+copy operation, so don't skip copying them. --> - <SkipUnchangedFiles Condition="'%(Extension)' != '.csproj'">true</SkipUnchangedFiles> - <SkipUnchangedFiles Condition="'%(Extension)' == '.csproj'">false</SkipUnchangedFiles> - </_ProjectTemplatesTransformSource> - <ProjectTemplatesSource Remove="@(_ProjectTemplatesTransformSource)" /> - - <ProjectTemplatesLayout Include="@(ProjectTemplatesSource->'$(ProjectTemplatesLayoutPath)%(RecursiveDir)%(FileName)%(Extension)')"/> - <ProjectTemplatesTransformLayout Include="@(_ProjectTemplatesTransformSource->'$(ProjectTemplatesLayoutPath)%(RecursiveDir)%(FileName)%(Extension)')"/> - - <!-- Include the template icon --> - <ProjectTemplatesSource Include="$(ProjectRoot)doc\logo\favicon.ico" /> - <ProjectTemplatesLayout Include="$(ProjectTemplatesLayoutPath)__TemplateIcon.ico" /> - - <!-- Add external libraries --> - <!-- Include the unified, signed version of the library --> - <ProjectTemplateLibraries Include="$(ILMergeOutputAssembly)" /> - <ProjectTemplateLibraries Include="$(ILMergeOutputAssemblyDirectory)$(ProductName).pdb" /> - <ProjectTemplateLibraries Include="$(OutputPath)$(ProductName).xml" /> - <ProjectTemplateLibraries Include="$(OutputPath)$(ProductName).Contracts.dll" /> - <!-- ... and log4net --> - <ProjectTemplateLibraries Include="$(ProjectRoot)lib\log4net.dll" /> - <ProjectTemplateLibraries Include="$(ProjectRoot)lib\log4net.xml" /> - <ProjectTemplateLibrariesTargets Include="@(ProjectTemplateLibraries->'$(ProjectTemplatesLayoutPath)RelyingPartyLogic\lib\%(FileName)%(Extension)')" /> - - <ProjectTemplatesSource Include="@(ProjectTemplateLibraries)" /> - <ProjectTemplatesLayout Include="@(ProjectTemplateLibrariesTargets)" /> - <FixupReferenceAssemblies Include="@(ProjectTemplateLibrariesTargets)" Condition="'%(Extension)' == '.dll'" /> - - <InjectedLibraryItems Include="@(ProjectTemplateLibrariesTargets->'lib\%(FileName)%(Extension)')" /> - <VSProjectTemplates Include="@(ProjectTemplatesLayout)" Condition="'%(Extension)' == '.vstemplate'" /> - </ItemGroup> - - <Trim Inputs="@(_ProjectTemplatesTransformSource)" MetadataName="BeforeTokens" AllAfter="\"> - <Output TaskParameter="Outputs" ItemName="ProjectTemplatesTransformSource" /> - </Trim> - <!--<MSBuild Projects="@(ProjectTemplates)" />--> - <Copy SourceFiles="@(ProjectTemplatesSource)" DestinationFiles="@(ProjectTemplatesLayout)" SkipUnchangedFiles="true" /> - <CopyWithTokenSubstitution SourceFiles="@(ProjectTemplatesTransformSource)" DestinationFiles="@(ProjectTemplatesTransformLayout)"> - <Output TaskParameter="CopiedFiles" ItemName="CopiedProjectTemplateFiles" /> - </CopyWithTokenSubstitution> - <Purge Directories="$(ProjectTemplatesLayoutPath)" - IntendedFiles=" - @(ProjectTemplatesLayout); - @(ProjectTemplatesTransformLayout); - " /> - <ChangeProjectReferenceToAssemblyReference - Projects="@(CopiedProjectTemplateFiles)" - Condition="'%(Extension)' == '.csproj'" - ProjectReference="..\..\src\$(ProductName)\$(ProductName).csproj" - Reference="Lib\$(ProductName).dll" /> - <FixupReferenceHintPaths - Projects="@(CopiedProjectTemplateFiles)" - Condition="'%(CopiedProjectTemplateFiles.Extension)' == '.csproj'" - References="@(FixupReferenceAssemblies)" - /> - <AddProjectItems - Projects="@(CopiedProjectTemplateFiles)" - Condition="'%(CopiedProjectTemplateFiles.FileName)%(CopiedProjectTemplateFiles.Extension)' == 'RelyingPartyLogic.csproj'" - Items="@(InjectedLibraryItems)" - /> - <MergeProjectWithVSTemplate - ProjectItemTypes="@(VsTemplateProjectItemTypes)" - ReplaceParametersExtensions="@(VsTemplateParameterReplaceExtensions)" - Templates="@(VSProjectTemplates)" - /> - </Target> - - <Target Name="ProjectTemplates2008" DependsOnTargets="ProjectTemplatesLayout"> - <ItemGroup> - <ProjectTemplates2008Source Include="$(ProjectTemplatesLayoutPath)**" /> - <ProjectTemplates2008Layout Include="@(ProjectTemplates2008Source->'$(VS2008ProjectTemplatesDirectory)%(RecursiveDir)%(FileName)%(Extension)')" /> - <ProjectTemplates2008Layout> - <HardLink Condition=" '%(Extension)' != '.csproj' ">true</HardLink> - </ProjectTemplates2008Layout> - - <VS2008ProjectTemplates Include="@(ProjectTemplates2008Layout)" Condition="'%(Extension)' == '.vstemplate'" /> - <TopLevelVS2008ProjectTemplates Include="@(VS2008ProjectTemplates)" Condition="'%(RootDir)%(Directory)' == '$(VS2008ProjectTemplatesDirectory)'" /> - <VS2008ProjectTemplateZipFiles Include="@(TopLevelVS2008ProjectTemplates->'%(RootDir)%(Directory)%(FileName).zip')" /> - </ItemGroup> - - <HardLinkCopy SourceFiles="@(ProjectTemplates2008Source)" DestinationFiles="@(ProjectTemplates2008Layout)" /> - - <DowngradeProjects - Projects="@(ProjectTemplates2008Layout)" - Condition="'%(Extension)' == '.csproj'" - DowngradeMvc2ToMvc1="true" - /> - - <Purge Directories="$(VS2008ProjectTemplatesDirectory)" IntendedFiles="@(ProjectTemplates2008Layout)" /> - - <DiscoverProjectTemplates TopLevelTemplates="@(TopLevelVS2008ProjectTemplates)"> - <Output TaskParameter="ProjectTemplates" ItemName="SubVS2008Templates" /> - <Output TaskParameter="ProjectTemplateContents" ItemName="VS2008TemplateItemContents" /> - </DiscoverProjectTemplates> - - <ItemGroup> - <!-- Include in each template .zip file the top-level .vstemplate file itself. --> - <VS2008ProjectTemplateContents Include="@(TopLevelVS2008ProjectTemplates)"> - <ZipFile>$(ProjectTemplatesVsiDirectory)%(FileName).zip</ZipFile> - <WorkingDirectory>$(VS2008ProjectTemplatesDirectory)</WorkingDirectory> - </VS2008ProjectTemplateContents> - - <!-- Now throw in all the files in each of the project-level template's directories and their children. --> - <VS2008ProjectTemplateContents Include="@(VS2008TemplateItemContents)"> - <ZipFile>$(ProjectTemplatesVsiDirectory)%(VS2008TemplateItemContents.TopLevelTemplateFileName).zip</ZipFile> - <WorkingDirectory>$(VS2008ProjectTemplatesDirectory)</WorkingDirectory> - </VS2008ProjectTemplateContents> - - <!-- Include the template icon for each .zip file. --> - <VS2008ProjectTemplateContents Include="@(TopLevelVS2008ProjectTemplates->'$(VS2008ProjectTemplatesDirectory)__TemplateIcon.ico')"> - <ZipFile>$(ProjectTemplatesVsiDirectory)%(TopLevelVS2008ProjectTemplates.FileName).zip</ZipFile> - <WorkingDirectory>$(VS2008ProjectTemplatesDirectory)</WorkingDirectory> - </VS2008ProjectTemplateContents> - </ItemGroup> - - <Zip - Files="@(VS2008ProjectTemplateContents)" - ZipFileName="%(VS2008ProjectTemplateContents.ZipFile)" - WorkingDirectory="%(VS2008ProjectTemplateContents.WorkingDirectory)" - ZipLevel="$(ZipLevel)" - /> - </Target> - - <Target Name="ProjectTemplates2010" DependsOnTargets="ProjectTemplatesLayout"> - <PropertyGroup> - <ProjectTemplateSubdirectory>$(ExtensionVsixLayoutDirectory)PT\CSharp\Web\</ProjectTemplateSubdirectory> - </PropertyGroup> - <ItemGroup> - <ProjectTemplates2010Source Include="$(ProjectTemplatesLayoutPath)**" /> - <ProjectTemplates2010Layout Include="@(ProjectTemplates2010Source->'$(VS2010ProjectTemplatesDirectory)%(RecursiveDir)%(FileName)%(Extension)')" /> - <ProjectTemplates2010Layout> - <HardLink Condition=" '%(Extension)' != '.csproj' ">true</HardLink> - </ProjectTemplates2010Layout> - - <VS2010ProjectTemplates Include="@(ProjectTemplates2010Layout)" Condition="'%(Extension)' == '.vstemplate'" /> - <TopLevelVS2010ProjectTemplates Include="@(VS2010ProjectTemplates)" Condition="'%(RootDir)%(Directory)' == '$(VS2010ProjectTemplatesDirectory)'" /> - <VS2010ProjectTemplateZipFiles Include="@(TopLevelVS2010ProjectTemplates->'%(RootDir)%(Directory)%(FileName).zip')" /> - </ItemGroup> - - <HardLinkCopy SourceFiles="@(ProjectTemplates2010Source)" DestinationFiles="@(ProjectTemplates2010Layout)" /> - - <Purge Directories="$(VS2010ProjectTemplatesDirectory)" IntendedFiles="@(ProjectTemplates2010Layout)" /> - - <DiscoverProjectTemplates TopLevelTemplates="@(TopLevelVS2010ProjectTemplates)"> - <Output TaskParameter="ProjectTemplates" ItemName="SubVS2010Templates" /> - <Output TaskParameter="ProjectTemplateContents" ItemName="VS2010TemplateItemContents" /> - </DiscoverProjectTemplates> - - <ItemGroup> - <!-- Include in each template .zip file the top-level .vstemplate file itself. --> - <VS2010ProjectTemplateContents Include="@(TopLevelVS2010ProjectTemplates)"> - <ZipFile>$(ProjectTemplateSubdirectory)%(FileName).zip</ZipFile> - <WorkingDirectory>$(VS2010ProjectTemplatesDirectory)</WorkingDirectory> - </VS2010ProjectTemplateContents> - - <!-- Now throw in all the files in each of the project-level template's directories and their children. --> - <VS2010ProjectTemplateContents Include="@(VS2010TemplateItemContents)"> - <ZipFile>$(ProjectTemplateSubdirectory)%(VS2010TemplateItemContents.TopLevelTemplateFileName).zip</ZipFile> - <WorkingDirectory>$(VS2010ProjectTemplatesDirectory)</WorkingDirectory> - </VS2010ProjectTemplateContents> - - <!-- Include the template icon for each .zip file. --> - <VS2010ProjectTemplateContents Include="@(TopLevelVS2010ProjectTemplates->'$(VS2010ProjectTemplatesDirectory)__TemplateIcon.ico')"> - <ZipFile>$(ProjectTemplateSubdirectory)%(TopLevelVS2010ProjectTemplates.FileName).zip</ZipFile> - <WorkingDirectory>$(VS2010ProjectTemplatesDirectory)</WorkingDirectory> - </VS2010ProjectTemplateContents> - - <ExtensionVsixContents Include="%(VS2010ProjectTemplateContents.ZipFile)" /> - </ItemGroup> - - <Zip - Files="@(VS2010ProjectTemplateContents)" - ZipFileName="%(VS2010ProjectTemplateContents.ZipFile)" - WorkingDirectory="%(VS2010ProjectTemplateContents.WorkingDirectory)" - ZipLevel="$(ZipLevel)" - /> - </Target> - - <Target Name="vsi" DependsOnTargets="ProjectTemplates2008;_SetDropProperties"> - <PropertyGroup> - <ProjectTemplatesVsi>$(DropDirectoryNoSlash).vsi</ProjectTemplatesVsi> - </PropertyGroup> - <ItemGroup> - <VsiTransformSource Include="$(ProjectRoot)vsi\*.vscontent"> - <BeforeTokens>$version$</BeforeTokens> - <AfterTokens>$(BuildVersion)</AfterTokens> - <SkipUnchangedFiles>false</SkipUnchangedFiles> - </VsiTransformSource> - <VsiTransformLayout Include="@(VsiTransformSource->'$(ProjectTemplatesVsiDirectory)%(RecursiveDir)%(FileName)%(Extension)')" /> - - <ProjectTemplateVsiContents Include=" - $(ProjectTemplatesVsiDirectory)*.zip; - @(VsiTransformLayout); - " /> - </ItemGroup> - - <CopyWithTokenSubstitution SourceFiles="@(VsiTransformSource)" DestinationFiles="@(VsiTransformLayout)" /> - - <Zip - Files="@(ProjectTemplateVsiContents)" - ZipFileName="$(ProjectTemplatesVsi)" - WorkingDirectory="$(ProjectTemplatesVsiDirectory)" - ZipLevel="$(ZipLevel)" - /> - </Target> - - <Target Name="VsixLayout" DependsOnTargets="ProjectTemplates2010"> - <ItemGroup> - <ProjectTemplates2010TransformSource Include=" - $(ProjectRoot)vsix\extension.vsixmanifest; - $(ProjectRoot)LICENSE.txt; - "> - <BeforeTokens>$version$</BeforeTokens> - <AfterTokens>$(BuildVersion)</AfterTokens> - <SkipUnchangedFiles>false</SkipUnchangedFiles> - </ProjectTemplates2010TransformSource> - <ProjectTemplates2010TransformLayout Include="@(ProjectTemplates2010TransformSource->'$(ExtensionVsixLayoutDirectory)%(RecursiveDir)%(FileName)%(Extension)')" /> - - <ExtensionVsixSources Include=" - $(ProjectRoot)vsix\*; - " Exclude=" - $(ProjectRoot)vsix\extension.vsixmanifest; - "> - <SkipUnchangedFiles>true</SkipUnchangedFiles> - </ExtensionVsixSources> - - <ExtensionVsixTargets Include="@(ExtensionVsixSources->'$(ExtensionVsixLayoutDirectory)%(FileName)%(Extension)')" /> - - <ExtensionVsixContents Include=" - @(ExtensionVsixTargets); - @(ProjectTemplates2010TransformLayout); - "/> - </ItemGroup> - - <Copy SourceFiles="@(ExtensionVsixSources)" DestinationFiles="@(ExtensionVsixTargets)" SkipUnchangedFiles="true" /> - <CopyWithTokenSubstitution SourceFiles="@(ProjectTemplates2010TransformSource)" DestinationFiles="@(ProjectTemplates2010TransformLayout)" /> - - <Purge Directories="$(ExtensionVsixLayoutDirectory)" IntendedFiles="@(ExtensionVsixContents)" /> - </Target> - - <Target Name="vsix" DependsOnTargets="VsixLayout;_SetDropProperties"> - <PropertyGroup> - <ExtensionVsix>$(DropDirectoryNoSlash).vsix</ExtensionVsix> - </PropertyGroup> - <Zip - Files="@(ExtensionVsixContents)" - ZipFileName="$(ExtensionVsix)" - WorkingDirectory="$(ExtensionVsixLayoutDirectory)" - ZipLevel="$(ZipLevel)" - /> - </Target> - - <Target Name="Documentation" DependsOnTargets="BuildProduct;Chm" Condition="'$(NoDocumentation)' != 'true'"> + <MSBuild Projects="$(SolutionPath)" Targets="Rebuild" BuildInParallel="$(BuildInParallel)" /> </Target> <Target Name="Test" DependsOnTargets="BuildTests" @@ -456,138 +59,13 @@ ExcludeCategory="$(NUnitExcludeCategories)"/> </Target> - <Target Name="_SetDropProperties"> - <!-- This target is necessary because PropertyGroups within the same Target as - where CallTarget is fired do NOT affect those called targets. --> - <!-- The rest of these are here so that other DependsOn targets have access to these properties. --> - <PropertyGroup> - <DropDirectoryNoSlash>$(DropsRoot)$(ProductName)-$(BuildVersion)</DropDirectoryNoSlash> - <DropDirectory>$(DropDirectoryNoSlash)\</DropDirectory> - </PropertyGroup> - </Target> - - <Target Name="DropLayout" DependsOnTargets="GetBuildVersion;_SetDropProperties;BuildUnifiedProduct;ReSignDelaySignedAssemblies;BuildSamples;vsi;vsix;Documentation"> - <PropertyGroup> - <DropBinDirectory>$(DropDirectory)Bin\</DropBinDirectory> - <DropLibDirectory>$(DropDirectory)Lib\</DropLibDirectory> - <DropProjectTemplatesDirectory>$(DropDirectory)Project Templates\</DropProjectTemplatesDirectory> - <DropSamplesDirectory>$(DropDirectory)Samples\</DropSamplesDirectory> - <DropSpecsDirectory>$(DropDirectory)Specs\</DropSpecsDirectory> - </PropertyGroup> - <ItemGroup> - <DropDirectories Include=" - $(DropDirectory); - $(DropBinDirectory); - $(DropLibDirectory); - $(DropProjectTemplatesDirectory); - $(DropSamplesDirectory); - $(DropSpecsDirectory); - " /> - - <DropSourceFiles Include=" - $(ProjectRoot)Doc\$(ProductName).chm; - $(ProjectRoot)Doc\*.htm*; - $(ProjectRoot)LICENSE.txt; - $(ProjectRoot)CONTRIB.txt; - " - Exclude="$(ProjectRoot)Doc\README.*.html;" /> - <DropBinSourceFiles Include=" - $(ILMergeOutputAssemblyDirectory)$(ProductName).???; - $(OutputPath)**\$(ProductName).resources.dll; - $(OutputPath)$(ProductName).xml; - $(OutputPath)$(ProductName).Contracts.???; - $(ProjectRoot)Doc\README.Bin.html; - $(ProjectRoot)src\$(ProductName)\Configuration\$(ProductName).xsd; - " /> - <DropLibSourceFiles Include=" - $(ProjectRoot)Lib\log4net.*; - " /> - <DropProjectTemplatesSourceFiles Include="$(ProjectTemplatesVsi)" /> - <DropVsixSourceFiles Include="$(ExtensionVsix)" /> - <DropSamplesSourceFiles Include="$(ProjectRoot)Samples\**" Exclude=" - $(ProjectRoot)**\obj\**; - $(ProjectRoot)**\*.sln.cache; - $(ProjectRoot)**\*.suo; - $(ProjectRoot)**\*.user; - $(ProjectRoot)**\*.gitignore; - $(ProjectRoot)**\*.ldf; - $(ProjectRoot)**\*.log*; - $(ProjectRoot)**\*~; - $(ProjectRoot)**\Debug\**; - $(ProjectRoot)**\Settings.StyleCop; - $(ProjectRoot)**\StyleCop.Cache; - $(ProjectRoot)Samples\**\DotNetOpenAuth.???; - $(ProjectRoot)Samples\**\log4net.???; - $(ProjectRoot)Samples\**\PresentationCore.dll; - $(ProjectRoot)Samples\**\System.Printing.dll; - $(ProjectRoot)Samples\**\*.refresh_; - " /> - <!-- Some .refresh files are only applicable to drop builds, so we rename them from *.refresh_ --> - <DropSamplesRefreshSourceFiles Include="$(ProjectRoot)Samples\**\*.refresh_" /> - <DropSpecsSourceFiles Include="$(ProjectRoot)Doc\specs\*.htm*" /> - - <DropFiles Include="@(DropSourceFiles->'$(DropDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> - <DropBinFiles Include="@(DropBinSourceFiles->'$(DropBinDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> - <DropLibFiles Include="@(DropLibSourceFiles->'$(DropLibDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> - <DropProjectTemplatesFiles Include="@(DropProjectTemplatesSourceFiles->'$(DropProjectTemplatesDirectory)%(FileName)%(Extension)')" /> - <DropVsixFiles Include="@(DropVsixSourceFiles->'$(DropProjectTemplatesDirectory)%(FileName)%(Extension)')" /> - <DropSamplesFiles Include="@(DropSamplesSourceFiles->'$(DropSamplesDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> - <DropSamplesRefreshFiles Include="@(DropSamplesRefreshSourceFiles->'$(DropSamplesDirectory)%(RecursiveDir)%(FileName).refresh')"/> - <DropSamplesToolsProjects Include="$(DropSamplesDirectory)OpenIdOfflineProvider\OpenIdOfflineProvider.csproj" /> - <DropSpecsFiles Include="@(DropSpecsSourceFiles->'$(DropSpecsDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> - - <AllDropSources Include=" - @(DropSourceFiles); - @(DropBinSourceFiles); - @(DropLibSourceFiles); - @(DropProjectTemplatesSourceFiles); - @(DropVsixSourceFiles); - @(DropSamplesSourceFiles); - @(DropSamplesRefreshSourceFiles); - @(DropDocSourceFiles); - @(DropSpecsSourceFiles); - " /> - - <AllDropTargets Include=" - @(DropFiles); - @(DropBinFiles); - @(DropLibFiles); - @(DropProjectTemplatesFiles); - @(DropVsixFiles); - @(DropSamplesFiles); - @(DropSamplesRefreshFiles); - @(DropDocFiles); - @(DropSpecsFiles) - " /> - </ItemGroup> - - <!-- clean up any previous drop with the same name so we don't aggregate files. --> - <MakeDir Directories="@(DropDirectories)" /> - <Copy SourceFiles="@(AllDropSources)" DestinationFiles="@(AllDropTargets)" SkipUnchangedFiles="true" /> - <Purge Directories="$(DropDirectory)" IntendedFiles="@(AllDropTargets)" /> - <!-- fix up the samples so that they will compile right out of the drop --> - <ItemGroup> - <SampleProjectTargets Include="$(DropSamplesDirectory)**\*.*proj" /> - <SampleSolutionTargets Include="$(DropSamplesDirectory)**\*.sln" /> - </ItemGroup> - <FixupShippingToolSamples Projects="@(DropSamplesToolsProjects)" - RemoveImportsStartingWith="%24(ProjectRoot)tools\" - AddReferences="Microsoft.Contracts"/> - <ChangeProjectReferenceToAssemblyReference Projects="@(SampleProjectTargets)" - ProjectReference="..\..\src\$(ProductName)\$(ProductName).csproj" Reference="..\..\Bin\$(ProductName).dll" /> - <DowngradeProjects Projects="@(SampleProjectTargets);@(SampleSolutionTargets)" DowngradeMvc2ToMvc1="true" /> + <Target Name="Nightly"> + <MSBuild Projects="@(ProjectsInDrop)" Targets="%(ProjectsInDrop.Targets)" BuildInParallel="$(BuildInParallel)" /> </Target> - <Target Name="Drop" DependsOnTargets="DropLayout"> - <PropertyGroup> - <DropZip>$(DropDirectoryNoSlash).zip</DropZip> - </PropertyGroup> - <Zip Files="@(AllDropTargets)" ZipFileName="$(DropZip)" WorkingDirectory="$(DropsRoot)" ZipLevel="$(ZipLevel)" /> + <Target Name="Publish"> + <MSBuild Projects="@(ProjectsToPublish)" Targets="Publish" BuildInParallel="$(BuildInParallel)" /> </Target> - <!-- Although Nightly includes publishing samples and docs, those targets are conditioned for - running only when the SampleWebRoot and DocWebRoot properties are set, respectively. --> - <Target Name="Nightly" DependsOnTargets="Drop;Tools;PublishSamples;PublishDocumentation"> - - </Target> + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.automated.targets"/> </Project> diff --git a/doc/doc.proj b/doc/doc.proj new file mode 100644 index 0000000..75f3cdc --- /dev/null +++ b/doc/doc.proj @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <!-- Properties that must be set for these targets to function: + $(BranchName): The name of the branch being built. Used to determine the web subdirectory for publishing. + + For creating web sites: + $(PublishDocsWebSiteName): The name of the web site under which the documentation web applications will be created/deleted. + + For creating or publishing to web sites: + $(DocWebRoot): the full physical path to where documentation should be copied to, excluding $(BranchName) + --> + + <Import Project="$(MSBuildProjectDirectory)\..\tools\DotNetOpenAuth.automated.props"/> + + <Target Name="Build" DependsOnTargets="BuildProduct;Chm" Condition=" '$(NoDocumentation)' != 'true' " /> + + <Target Name="Prepare"> + <Error Text="The BranchName property must be set." Condition=" '$(BranchName)' == '' " /> + <Error Text="The DocWebRoot property must be set." Condition=" '$(DocWebRoot)' == '' " /> + <PropertyGroup> + <PublishDocsWebSiteVirtualPath>/$(BranchName)</PublishDocsWebSiteVirtualPath> + </PropertyGroup> + </Target> + + <Target Name="PrepareForPublish" DependsOnTargets="Prepare;BuildProduct;Html"> + <ItemGroup> + <DocSources Include="$(ProjectRoot)doc\api\**\*" /> + <DocTargets Include="@(DocSources->'$(DocWebRoot)\$(BranchName)\%(RecursiveDir)%(Filename)%(Extension)')" /> + </ItemGroup> + </Target> + + <Target Name="Publish" + DependsOnTargets="PrepareForPublish" + Inputs="@(DocSources)" + Outputs="@(DocTargets)"> + <RemoveDir Directories="$(DocWebRoot)\$(BranchName)" /> + <MakeDir Directories="$(DocWebRoot)\$(BranchName)" /> + <Copy SourceFiles="@(DocSources)" DestinationFiles="@(DocTargets)" SkipUnchangedFiles="true" /> + </Target> + + <Target Name="Unpublish" + DependsOnTargets="DeleteSiteOnIis" + Condition=" '$(DocWebRoot)' != '' "> + </Target> + + <Target Name="CreateSiteOnIis" DependsOnTargets="Prepare"> + <Error Text="The PublishDocsWebSiteName property must be set." Condition=" '$(PublishDocsWebSiteName)' == '' "/> + <CreateWebApplication + WebSiteName="$(PublishDocsWebSiteName)" + PhysicalPaths="$(DocWebRoot)\$(BranchName)" + VirtualPaths="$(PublishDocsWebSiteVirtualPath)" + /> + </Target> + + <Target Name="DeleteSiteOnIis" DependsOnTargets="Prepare"> + <Error Text="The PublishDocsWebSiteName property must be set." Condition=" '$(PublishDocsWebSiteName)' == '' "/> + <DeleteWebApplication + WebSiteName="$(PublishDocsWebSiteName)" + VirtualPaths="$(PublishDocsWebSiteVirtualPath)" + /> + </Target> + + <Import Project="$(ProjectRoot)tools\Documentation.targets"/> + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.automated.targets"/> +</Project>
\ No newline at end of file diff --git a/lib/DotNetOpenAuth.BuildTasks.dll b/lib/DotNetOpenAuth.BuildTasks.dll Binary files differindex 8edc333..b3c6244 100644 --- a/lib/DotNetOpenAuth.BuildTasks.dll +++ b/lib/DotNetOpenAuth.BuildTasks.dll diff --git a/lib/DotNetOpenAuth.BuildTasks.pdb b/lib/DotNetOpenAuth.BuildTasks.pdb Binary files differindex e9ed7e3..676ff46 100644 --- a/lib/DotNetOpenAuth.BuildTasks.pdb +++ b/lib/DotNetOpenAuth.BuildTasks.pdb diff --git a/lib/Moq.pdb b/lib/Moq.pdb Binary files differdeleted file mode 100644 index 3964e06..0000000 --- a/lib/Moq.pdb +++ /dev/null diff --git a/projecttemplates/MvcRelyingParty.vsixmanifest b/projecttemplates/MvcRelyingParty.vsixmanifest new file mode 100644 index 0000000..f401277 --- /dev/null +++ b/projecttemplates/MvcRelyingParty.vsixmanifest @@ -0,0 +1,27 @@ +<?xml version="1.0"?> +<Vsix xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010"> + <Identifier Id="DotNetOpenAuth.MvcRelyingParty.15E8EC96-BDC3-47E2-8BB1-0483E9D16705"> + <Name>ASP.NET MVC OpenID web site (C#)</Name> + <Author>DotNetOpenAuth</Author> + <Version>$version$</Version> + <Description>Resources for developing applications that use OpenID, OAuth, and InfoCard.</Description> + <Locale>1033</Locale> + <License>LICENSE.txt</License> + <GettingStartedGuide>http://www.dotnetopenauth.net/ProjectTemplateGettingStarted</GettingStartedGuide> + <Icon>VSIXProject_small.png</Icon> + <PreviewImage>VSIXProject_large.png</PreviewImage> + <InstalledByMsi>false</InstalledByMsi> + <SupportedProducts> + <VisualStudio Version="10.0"> + <Edition>VSTS</Edition> + <Edition>VSTD</Edition> + <Edition>Pro</Edition> + </VisualStudio> + </SupportedProducts> + <SupportedFrameworkRuntimeEdition MinVersion="3.5" MaxVersion="3.5" /> + </Identifier> + <References /> + <Content> + <ProjectTemplate>PT</ProjectTemplate> + </Content> +</Vsix> diff --git a/projecttemplates/MvcRelyingParty/Web.config b/projecttemplates/MvcRelyingParty/Web.config index 8bd0dfc..706b0a1 100644 --- a/projecttemplates/MvcRelyingParty/Web.config +++ b/projecttemplates/MvcRelyingParty/Web.config @@ -165,6 +165,7 @@ <add assembly="System.Data.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /> + <remove assembly="DotNetOpenAuth.Contracts"/> </assemblies> </compilation> diff --git a/projecttemplates/RelyingPartyLogic/CreateDatabase.sql b/projecttemplates/RelyingPartyLogic/CreateDatabase.sql index dd7a69e..0fa1b43 100644 --- a/projecttemplates/RelyingPartyLogic/CreateDatabase.sql +++ b/projecttemplates/RelyingPartyLogic/CreateDatabase.sql @@ -711,6 +711,10 @@ PRINT N'Checking existing data against newly created constraints'; GO +USE [$(DatabaseName)]; + + +GO ALTER TABLE [dbo].[AuthenticationToken] WITH CHECK CHECK CONSTRAINT [FK_AuthenticationToken_User]; ALTER TABLE [dbo].[IssuedToken] WITH CHECK CHECK CONSTRAINT [FK_IssuedToken_Consumer]; diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs index f57faab..35af472 100644 --- a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs +++ b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs @@ -31,34 +31,38 @@ namespace RelyingPartyLogic { HttpRequestMessageProperty httpDetails = operationContext.RequestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; Uri requestUri = operationContext.RequestContext.RequestMessage.Properties["OriginalHttpRequestUri"] as Uri; ServiceProvider sp = OAuthServiceProvider.ServiceProvider; - var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri); - if (auth != null) { - var accessToken = Database.DataContext.IssuedTokens.OfType<IssuedAccessToken>().First(token => token.Token == auth.AccessToken); + try { + var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri); + if (auth != null) { + var accessToken = Database.DataContext.IssuedTokens.OfType<IssuedAccessToken>().First(token => token.Token == auth.AccessToken); - var principal = sp.CreatePrincipal(auth); - var policy = new OAuthPrincipalAuthorizationPolicy(principal); - var policies = new List<IAuthorizationPolicy> { - policy, - }; - - var securityContext = new ServiceSecurityContext(policies.AsReadOnly()); - if (operationContext.IncomingMessageProperties.Security != null) { - operationContext.IncomingMessageProperties.Security.ServiceSecurityContext = securityContext; - } else { - operationContext.IncomingMessageProperties.Security = new SecurityMessageProperty { - ServiceSecurityContext = securityContext, + var principal = sp.CreatePrincipal(auth); + var policy = new OAuthPrincipalAuthorizationPolicy(principal); + var policies = new List<IAuthorizationPolicy> { + policy, }; - } - securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> { - principal.Identity, - }; + var securityContext = new ServiceSecurityContext(policies.AsReadOnly()); + if (operationContext.IncomingMessageProperties.Security != null) { + operationContext.IncomingMessageProperties.Security.ServiceSecurityContext = securityContext; + } else { + operationContext.IncomingMessageProperties.Security = new SecurityMessageProperty { + ServiceSecurityContext = securityContext, + }; + } + + securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> { + principal.Identity, + }; - // Only allow this method call if the access token scope permits it. - string[] scopes = accessToken.Scope.Split('|'); - if (scopes.Contains(operationContext.IncomingMessageHeaders.Action)) { - return true; + // Only allow this method call if the access token scope permits it. + string[] scopes = accessToken.Scope.Split('|'); + if (scopes.Contains(operationContext.IncomingMessageHeaders.Action)) { + return true; + } } + } catch (ProtocolException /*ex*/) { + ////Logger.Error("Error processing OAuth messages.", ex); } return false; diff --git a/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj b/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj index 9f58bfa..07f267d 100644 --- a/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj +++ b/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj @@ -143,6 +143,12 @@ <Project>{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}</Project> <Name>DotNetOpenAuth</Name> </ProjectReference> + <ProjectReference Include="..\RelyingPartyDatabase\RelyingPartyDatabase.dbproj"> + <Name>RelyingPartyDatabase</Name> + <!-- Deploy the latest SQL script first, so that this project can embed the latest version. --> + <Targets>Build;Deploy</Targets> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + </ProjectReference> </ItemGroup> <ItemGroup> <EmbeddedResource Include="CreateDatabase.sql" /> diff --git a/projecttemplates/WebFormsRelyingParty.vsixmanifest b/projecttemplates/WebFormsRelyingParty.vsixmanifest new file mode 100644 index 0000000..75a3646 --- /dev/null +++ b/projecttemplates/WebFormsRelyingParty.vsixmanifest @@ -0,0 +1,27 @@ +<?xml version="1.0"?> +<Vsix xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010"> + <Identifier Id="DotNetOpenAuth.WebFormsRelyingParty.FB0AB0B2-B447-4F10-A03E-F488DDAF024A"> + <Name>ASP.NET OpenID web site (C#)</Name> + <Author>DotNetOpenAuth</Author> + <Version>$version$</Version> + <Description>Resources for developing applications that use OpenID, OAuth, and InfoCard.</Description> + <Locale>1033</Locale> + <License>LICENSE.txt</License> + <GettingStartedGuide>http://www.dotnetopenauth.net/ProjectTemplateGettingStarted</GettingStartedGuide> + <Icon>VSIXProject_small.png</Icon> + <PreviewImage>VSIXProject_large.png</PreviewImage> + <InstalledByMsi>false</InstalledByMsi> + <SupportedProducts> + <VisualStudio Version="10.0"> + <Edition>VSTS</Edition> + <Edition>VSTD</Edition> + <Edition>Pro</Edition> + </VisualStudio> + </SupportedProducts> + <SupportedFrameworkRuntimeEdition MinVersion="3.5" MaxVersion="3.5" /> + </Identifier> + <References /> + <Content> + <ProjectTemplate>PT</ProjectTemplate> + </Content> +</Vsix> diff --git a/projecttemplates/WebFormsRelyingParty/Web.config b/projecttemplates/WebFormsRelyingParty/Web.config index 2092ba0..eabe925 100644 --- a/projecttemplates/WebFormsRelyingParty/Web.config +++ b/projecttemplates/WebFormsRelyingParty/Web.config @@ -158,6 +158,7 @@ <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /> <add assembly="System.Data.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <add assembly="System.Web.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /> + <remove assembly="DotNetOpenAuth.Contracts"/> </assemblies> </compilation> <!-- diff --git a/projecttemplates/projecttemplates.proj b/projecttemplates/projecttemplates.proj new file mode 100644 index 0000000..9df3fa8 --- /dev/null +++ b/projecttemplates/projecttemplates.proj @@ -0,0 +1,256 @@ +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildProjectDirectory)\..\tools\DotNetOpenAuth.automated.props"/> + <Import Project="ProjectTemplates.props"/> + + <PropertyGroup> + <ProjectTemplateMaxPath Condition=" '$(ProjectTemplateMaxPath)' == '' ">6</ProjectTemplateMaxPath> + + <LayoutDependsOn> + BuildUnifiedProduct; + ReSignDelaySignedAssemblies; + DeploySql; + LayoutProjects; + </LayoutDependsOn> + + <!-- We don't need to build the project templates, but to make sure we're not shipping junk, + we default to building them as a validation step. --> + <LayoutDependsOn Condition=" '$(Validation)' == 'Full' "> + Validate; + $(LayoutDependsOn); + </LayoutDependsOn> + </PropertyGroup> + + <ItemGroup> + <ProjectTemplates Include="**\*.*proj" Exclude="$(MSBuildThisFile)" /> + </ItemGroup> + + <Target Name="Validate"> + <MSBuild Projects="@(ProjectTemplates)" BuildInParallel="$(BuildInParallel)" /> + </Target> + + <Target Name="DeploySql"> + <!-- This causes the SQL script that generates the database to be deployed to the RelyingPartyLogic class library. --> + <MSBuild Projects="RelyingPartyDatabase\RelyingPartyDatabase.dbproj" Targets="Build;Deploy" BuildInParallel="$(BuildInParallel)" /> + </Target> + + <Target Name="LayoutProjects"> + <MSBuild Projects="..\src\$(ProductName)\$(ProductName).csproj" Targets="Sign" BuildInParallel="$(BuildInParallel)"> + <Output TaskParameter="TargetOutputs" ItemName="SignedProductAssemblies" /> + </MSBuild> + <ItemGroup> + <TemplateProjects Include="**\*.csproj" Exclude="$(MSBuildThisFile)"> + <AfterTokens>$safeprojectname$</AfterTokens> + <!-- Projects can get changed after the transform+copy operation, so don't skip copying them. --> + <SkipUnchangedFiles>false</SkipUnchangedFiles> + </TemplateProjects> + <TemplateProjects> + <BeforeTokens>%(RecursiveDir)</BeforeTokens> + </TemplateProjects> + <TemplateProjectsLayout Include="@(TemplateProjects->'$(ProjectTemplatesLayoutPath)%(RecursiveDir)%(FileName)%(Extension)')"/> + + <!-- Add external libraries and their symbols --> + <ProjectTemplateLibraries Include="@(SignedProductAssemblies)" /> + <ProjectTemplateLibraries Include="@(SignedProductAssemblies->'%(SymbolPath)')" /> + <ProjectTemplateLibraries Include="$(OutputPath)$(ProductName).xml" /> + <!-- ... and log4net --> + <ProjectTemplateLibraries Include="$(ProjectRoot)lib\log4net.dll" /> + <ProjectTemplateLibraries Include="$(ProjectRoot)lib\log4net.xml" /> + <ProjectTemplateLibrariesTargets Include="@(ProjectTemplateLibraries->'$(ProjectTemplatesLayoutPath)RelyingPartyLogic\lib\%(CultureDir)%(FileName)%(Extension)')"> + <ApparentSource>RelyingPartyLogic\lib\%(ProjectTemplateLibraries.CultureDir)%(FileName)%(Extension)</ApparentSource> + <ActualSource>%(Identity)</ActualSource> + </ProjectTemplateLibrariesTargets> + <ProjectTemplateLibrariesSourceExceptions Include="@(ProjectTemplateLibrariesTargets->'%(ApparentSource)')"/> + + <FixupReferenceAssemblies Include="@(ProjectTemplateLibrariesTargets)" Condition="'%(Extension)' == '.dll'" /> + <InjectedLibraryItems Include="@(ProjectTemplateLibraries->'lib\%(CultureDir)%(FileName)%(Extension)')"> + <Visible/> + <UnsignedAssemblyPath/> + <SymbolPath/> + <OriginalItemSpec/> + <MSBuildSourceProjectFile/> + <MSBuildSourceTargetName/> + <CultureDir/> + </InjectedLibraryItems> + + <VSProjectTemplates Include="**\*.vstemplate" Exclude="*.vstemplate" /> + <VSProjectTemplatesLayout Include="@(VSProjectTemplates->'$(ProjectTemplatesLayoutPath)%(RecursiveDir)%(FileName)%(Extension)')" /> + </ItemGroup> + + <Trim Inputs="@(TemplateProjects)" MetadataName="BeforeTokens" AllAfter="\"> + <Output TaskParameter="Outputs" ItemName="TemplateProjectsTransformSource" /> + </Trim> + <CopyWithTokenSubstitution SourceFiles="@(TemplateProjectsTransformSource)" DestinationFiles="@(TemplateProjectsLayout)"> + <Output TaskParameter="CopiedFiles" ItemName="CopiedProjectFiles" /> + </CopyWithTokenSubstitution> + <ChangeProjectReferenceToAssemblyReference + Projects="@(CopiedProjectFiles)" + Condition=" '%(Extension)' == '.csproj' " + ProjectReferences="..\..\src\$(ProductName)\$(ProductName).csproj;..\RelyingPartyDatabase\RelyingPartyDatabase.dbproj" + References="Lib\$(ProductName).dll;REMOVE" /> + <FixupReferenceHintPaths + Projects="@(CopiedProjectFiles)" + References="@(FixupReferenceAssemblies)" + /> + <AddProjectItems + Projects="@(CopiedProjectFiles)" + Condition="'%(CopiedProjectFiles.FileName)%(CopiedProjectFiles.Extension)' == 'RelyingPartyLogic.csproj'" + Items="@(InjectedLibraryItems)" + /> + <MergeProjectWithVSTemplate + ProjectItemTypes="@(VsTemplateProjectItemTypes)" + ReplaceParametersExtensions="@(VsTemplateParameterReplaceExtensions)" + SourceTemplates="@(VSProjectTemplates)" + SourceProjects="@(TemplateProjectsLayout)" + DestinationTemplates="@(VSProjectTemplatesLayout)" + SourcePathExceptions="@(ProjectTemplateLibrariesSourceExceptions)" + MaximumRelativePathLength="$(ProjectTemplateMaxPath)" + > + <Output TaskParameter="ProjectItems" ItemName="TemplateProjectItems"/> + </MergeProjectWithVSTemplate> + </Target> + + <Target Name="Layout" DependsOnTargets="$(LayoutDependsOn)"> + <ItemGroup> + <TemplateProjectItems Condition=" '%(Transform)' == 'true' "> + <BeforeTokens>%(RecursiveDir)</BeforeTokens> + <AfterTokens>$safeprojectname$</AfterTokens> + </TemplateProjectItems> + <TemplateProjectItems> + <SkipUnchangedFiles>true</SkipUnchangedFiles> + </TemplateProjectItems> + <TemplateProjectItemsForTransformSource Include="@(TemplateProjectItems->'%(SourceFullPath)')" /> + <TemplateProjectItemsForTransformLayout Include="@(TemplateProjectItems->'%(DestinationFullPath)')" /> + <RootVsTemplateSource Include="*.vstemplate" /> + <ProjectTemplatesSource Include="@(RootVsTemplateSource)" /> + <ProjectTemplatesLayout Include="@(RootVsTemplateSource->'$(ProjectTemplatesLayoutPath)%(FileName)%(Extension)')" /> + + <!-- Include the template icon --> + <ProjectTemplatesSource Include="$(ProjectRoot)doc\logo\favicon.ico" /> + <ProjectTemplatesLayout Include="$(ProjectTemplatesLayoutPath)__TemplateIcon.ico" /> + + <TopLevelVS2010ProjectTemplates Include="@(ProjectTemplatesLayout)" Condition=" '%(Extension)' == '.vstemplate' and '%(RootDir)%(Directory)' == '$(ProjectTemplatesLayoutPath)' " /> + <VS2010ProjectTemplateZipFiles Include="@(TopLevelVS2010ProjectTemplates->'%(RootDir)%(Directory)%(FileName).zip')" /> + </ItemGroup> + + <Copy + SourceFiles="@(ProjectTemplatesSource)" + DestinationFiles="@(ProjectTemplatesLayout)" + SkipUnchangedFiles="true" /> + <CopyWithTokenSubstitution + SourceFiles="@(TemplateProjectItemsForTransformSource)" + DestinationFiles="@(TemplateProjectItemsForTransformLayout)" /> + + <ItemGroup> + <ProjectTemplateIntendedFiles Include=" + @(ProjectTemplatesLayout); + @(TemplateProjectItemsForTransformLayout); + @(VSProjectTemplatesLayout); + @(TemplateProjectsLayout); + @(VS2010ProjectTemplateZipFiles); + " /> + <ProjectTemplateIntendedFiles Remove="@(ProjectItemShortPathAdjustments)" /> + </ItemGroup> + <Purge Directories="$(ProjectTemplatesLayoutPath)" + IntendedFiles="@(ProjectTemplateIntendedFiles)" /> + </Target> + + <Target Name="Zip" DependsOnTargets="Layout" Returns="%(VS2010ProjectTemplateContents.ZipFile)"> + <DiscoverProjectTemplates TopLevelTemplates="@(TopLevelVS2010ProjectTemplates)"> + <Output TaskParameter="ProjectTemplates" ItemName="SubVS2010Templates" /> + <Output TaskParameter="ProjectTemplateContents" ItemName="VS2010TemplateItemContents" /> + </DiscoverProjectTemplates> + + <ItemGroup> + <!-- Include in each template .zip file the top-level .vstemplate file itself. --> + <VS2010ProjectTemplateContents Include="@(TopLevelVS2010ProjectTemplates)"> + <ZipFile>$(ProjectTemplatesLayoutPath)%(FileName).zip</ZipFile> + <WorkingDirectory>$(ProjectTemplatesLayoutPath)</WorkingDirectory> + </VS2010ProjectTemplateContents> + + <!-- Now throw in all the files in each of the project-level template's directories and their children. --> + <VS2010ProjectTemplateContents Include="@(VS2010TemplateItemContents)"> + <ZipFile>$(ProjectTemplatesLayoutPath)%(VS2010TemplateItemContents.TopLevelTemplateFileName).zip</ZipFile> + <WorkingDirectory>$(ProjectTemplatesLayoutPath)</WorkingDirectory> + </VS2010ProjectTemplateContents> + + <!-- Include the template icon for each .zip file. --> + <VS2010ProjectTemplateContents Include="@(TopLevelVS2010ProjectTemplates->'$(ProjectTemplatesLayoutPath)__TemplateIcon.ico')"> + <ZipFile>$(ProjectTemplatesLayoutPath)%(TopLevelVS2010ProjectTemplates.FileName).zip</ZipFile> + <WorkingDirectory>$(ProjectTemplatesLayoutPath)</WorkingDirectory> + </VS2010ProjectTemplateContents> + + <ExtensionVsixContents Include="%(VS2010ProjectTemplateContents.ZipFile)" /> + </ItemGroup> + + <Zip + Files="@(VS2010ProjectTemplateContents)" + ZipFileName="%(VS2010ProjectTemplateContents.ZipFile)" + WorkingDirectory="%(VS2010ProjectTemplateContents.WorkingDirectory)" + ZipLevel="$(ZipLevel)" + /> + </Target> + + <Target Name="Layout2008" DependsOnTargets="Layout"> + <ItemGroup> + <ProjectTemplates2008Source Include="$(ProjectTemplatesLayoutPath)**" Exclude="$(ProjectTemplatesLayoutPath)*.zip" /> + <ProjectTemplates2008Layout Include="@(ProjectTemplates2008Source->'$(ProjectTemplates2008LayoutPath)%(RecursiveDir)%(FileName)%(Extension)')" /> + <ProjectTemplates2008Layout> + <HardLink Condition=" '%(Extension)' != '.csproj' ">true</HardLink> + </ProjectTemplates2008Layout> + + <VS2008ProjectTemplates Include="@(ProjectTemplates2008Layout)" Condition="'%(Extension)' == '.vstemplate'" /> + <TopLevelVS2008ProjectTemplates Include="@(VS2008ProjectTemplates)" Condition="'%(RootDir)%(Directory)' == '$(ProjectTemplates2008LayoutPath)'" /> + <VS2008ProjectTemplateZipFiles Include="@(TopLevelVS2008ProjectTemplates->'%(RootDir)%(Directory)%(FileName).zip')" /> + </ItemGroup> + <Message Text="VS2008ProjectTemplates: @(VS2008ProjectTemplates)" /> + + <HardLinkCopy SourceFiles="@(ProjectTemplates2008Source)" DestinationFiles="@(ProjectTemplates2008Layout)" /> + + <DowngradeProjects + Projects="@(ProjectTemplates2008Layout)" + Condition="'%(Extension)' == '.csproj'" + DowngradeMvc2ToMvc1="true" + /> + + <Purge Directories="$(ProjectTemplates2008LayoutPath)" + IntendedFiles="@(ProjectTemplates2008Layout);@(VS2008ProjectTemplateZipFiles)" /> + </Target> + + <Target Name="Zip2008" DependsOnTargets="Layout2008" Returns="%(VS2008ProjectTemplateContents.ZipFile)"> + <DiscoverProjectTemplates TopLevelTemplates="@(TopLevelVS2008ProjectTemplates)"> + <Output TaskParameter="ProjectTemplates" ItemName="SubVS2008Templates" /> + <Output TaskParameter="ProjectTemplateContents" ItemName="VS2008TemplateItemContents" /> + </DiscoverProjectTemplates> + + <ItemGroup> + <!-- Include in each template .zip file the top-level .vstemplate file itself. --> + <VS2008ProjectTemplateContents Include="@(TopLevelVS2008ProjectTemplates)"> + <ZipFile>$(ProjectTemplates2008LayoutPath)%(FileName).zip</ZipFile> + <WorkingDirectory>$(ProjectTemplates2008LayoutPath)</WorkingDirectory> + </VS2008ProjectTemplateContents> + + <!-- Now throw in all the files in each of the project-level template's directories and their children. --> + <VS2008ProjectTemplateContents Include="@(VS2008TemplateItemContents)"> + <ZipFile>$(ProjectTemplates2008LayoutPath)%(VS2008TemplateItemContents.TopLevelTemplateFileName).zip</ZipFile> + <WorkingDirectory>$(ProjectTemplates2008LayoutPath)</WorkingDirectory> + </VS2008ProjectTemplateContents> + + <!-- Include the template icon for each .zip file. --> + <VS2008ProjectTemplateContents Include="@(TopLevelVS2008ProjectTemplates->'$(ProjectTemplates2008LayoutPath)__TemplateIcon.ico')"> + <ZipFile>$(ProjectTemplates2008LayoutPath)%(TopLevelVS2008ProjectTemplates.FileName).zip</ZipFile> + <WorkingDirectory>$(ProjectTemplates2008LayoutPath)</WorkingDirectory> + </VS2008ProjectTemplateContents> + </ItemGroup> + + <Zip + Files="@(VS2008ProjectTemplateContents)" + ZipFileName="%(VS2008ProjectTemplateContents.ZipFile)" + WorkingDirectory="%(VS2008ProjectTemplateContents.WorkingDirectory)" + ZipLevel="$(ZipLevel)" + /> + </Target> + + <Target Name="Build" DependsOnTargets="Zip;Zip2008" /> + + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.automated.targets"/> +</Project>
\ No newline at end of file diff --git a/projecttemplates/projecttemplates.props b/projecttemplates/projecttemplates.props new file mode 100644 index 0000000..2bdc859 --- /dev/null +++ b/projecttemplates/projecttemplates.props @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <!-- We use GetFullPath here because IntermediatePath may be a relative directory, and we need to do full path comparisons. --> + <ProjectTemplatesLayoutPath>$([System.IO.Path]::GetFullPath('$(IntermediatePath)projecttemplates\'))</ProjectTemplatesLayoutPath> + <ProjectTemplates2008LayoutPath>$([System.IO.Path]::GetFullPath('$(IntermediatePath)projecttemplates2008\'))</ProjectTemplates2008LayoutPath> + </PropertyGroup> +</Project>
\ No newline at end of file diff --git a/samples/InfoCardRelyingParty/web.config b/samples/InfoCardRelyingParty/web.config index d91f9e8..7599561 100644 --- a/samples/InfoCardRelyingParty/web.config +++ b/samples/InfoCardRelyingParty/web.config @@ -65,6 +65,7 @@ <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <remove assembly="DotNetOpenAuth.Contracts"/> </assemblies> </compilation> <pages> diff --git a/samples/OAuthConsumer/Web.config b/samples/OAuthConsumer/Web.config index 9467175..496da95 100644 --- a/samples/OAuthConsumer/Web.config +++ b/samples/OAuthConsumer/Web.config @@ -66,6 +66,7 @@ <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <remove assembly="DotNetOpenAuth.Contracts"/> </assemblies> </compilation> <!-- diff --git a/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs b/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs index 8589932..ee90364 100644 --- a/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs +++ b/samples/OAuthServiceProvider/App_Code/OAuthAuthorizationManager.cs @@ -24,34 +24,38 @@ public class OAuthAuthorizationManager : ServiceAuthorizationManager { HttpRequestMessageProperty httpDetails = operationContext.RequestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; Uri requestUri = operationContext.RequestContext.RequestMessage.Properties["OriginalHttpRequestUri"] as Uri; ServiceProvider sp = Constants.CreateServiceProvider(); - var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri); - if (auth != null) { - var accessToken = Global.DataContext.OAuthTokens.Single(token => token.Token == auth.AccessToken); - - var principal = sp.CreatePrincipal(auth); - var policy = new OAuthPrincipalAuthorizationPolicy(principal); - var policies = new List<IAuthorizationPolicy> { - policy, - }; - - var securityContext = new ServiceSecurityContext(policies.AsReadOnly()); - if (operationContext.IncomingMessageProperties.Security != null) { - operationContext.IncomingMessageProperties.Security.ServiceSecurityContext = securityContext; - } else { - operationContext.IncomingMessageProperties.Security = new SecurityMessageProperty { - ServiceSecurityContext = securityContext, + try { + var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri); + if (auth != null) { + var accessToken = Global.DataContext.OAuthTokens.Single(token => token.Token == auth.AccessToken); + + var principal = sp.CreatePrincipal(auth); + var policy = new OAuthPrincipalAuthorizationPolicy(principal); + var policies = new List<IAuthorizationPolicy> { + policy, }; - } - securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> { - principal.Identity, - }; + var securityContext = new ServiceSecurityContext(policies.AsReadOnly()); + if (operationContext.IncomingMessageProperties.Security != null) { + operationContext.IncomingMessageProperties.Security.ServiceSecurityContext = securityContext; + } else { + operationContext.IncomingMessageProperties.Security = new SecurityMessageProperty { + ServiceSecurityContext = securityContext, + }; + } + + securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> { + principal.Identity, + }; - // Only allow this method call if the access token scope permits it. - string[] scopes = accessToken.Scope.Split('|'); - if (scopes.Contains(operationContext.IncomingMessageHeaders.Action)) { - return true; + // Only allow this method call if the access token scope permits it. + string[] scopes = accessToken.Scope.Split('|'); + if (scopes.Contains(operationContext.IncomingMessageHeaders.Action)) { + return true; + } } + } catch (ProtocolException ex) { + Global.Logger.Error("Error processing OAuth messages.", ex); } return false; diff --git a/samples/OAuthServiceProvider/Web.config b/samples/OAuthServiceProvider/Web.config index c21ebd4..3ea490f 100644 --- a/samples/OAuthServiceProvider/Web.config +++ b/samples/OAuthServiceProvider/Web.config @@ -61,6 +61,7 @@ <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <remove assembly="DotNetOpenAuth.Contracts"/> </assemblies> </compilation> <authentication mode="Forms"> diff --git a/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj b/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj index a2a56ba..564ddae 100644 --- a/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj +++ b/samples/OpenIdOfflineProvider/OpenIdOfflineProvider.csproj @@ -19,7 +19,7 @@ <WarningLevel>4</WarningLevel> <UICulture>en-US</UICulture> <TargetFrameworkVersion Condition=" '$(TargetFrameworkVersion)' == '' ">v3.5</TargetFrameworkVersion> - <OutputPath>bin\$(TargetFrameworkVersion)\$(Configuration)\</OutputPath> + <OutputPath Condition=" '$(OutputPath)' == '' ">bin\$(TargetFrameworkVersion)\$(Configuration)\</OutputPath> <ApplicationIcon>openid.ico</ApplicationIcon> <FileUpgradeFlags> </FileUpgradeFlags> diff --git a/samples/OpenIdProviderMvc/Web.config b/samples/OpenIdProviderMvc/Web.config index fcca524..8f145b0 100644 --- a/samples/OpenIdProviderMvc/Web.config +++ b/samples/OpenIdProviderMvc/Web.config @@ -81,6 +81,7 @@ <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <remove assembly="DotNetOpenAuth.Contracts"/> </assemblies> </compilation> <!-- diff --git a/samples/OpenIdProviderWebForms/Web.config b/samples/OpenIdProviderWebForms/Web.config index a978dc7..b76231b 100644 --- a/samples/OpenIdProviderWebForms/Web.config +++ b/samples/OpenIdProviderWebForms/Web.config @@ -75,6 +75,7 @@ <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <remove assembly="DotNetOpenAuth.Contracts"/> </assemblies> </compilation> <sessionState mode="InProc" cookieless="false"/> diff --git a/samples/OpenIdRelyingPartyMvc/Web.config b/samples/OpenIdRelyingPartyMvc/Web.config index f23c5d7..a17e00f 100644 --- a/samples/OpenIdRelyingPartyMvc/Web.config +++ b/samples/OpenIdRelyingPartyMvc/Web.config @@ -77,6 +77,7 @@ <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <remove assembly="DotNetOpenAuth.Contracts"/> </assemblies> </compilation> <!-- diff --git a/samples/OpenIdRelyingPartyWebForms/Web.config b/samples/OpenIdRelyingPartyWebForms/Web.config index b0aa965..5d3a33b 100644 --- a/samples/OpenIdRelyingPartyWebForms/Web.config +++ b/samples/OpenIdRelyingPartyWebForms/Web.config @@ -61,7 +61,11 @@ <system.web> <!--<sessionState cookieless="true" />--> - <compilation debug="true"/> + <compilation debug="true"> + <assemblies> + <remove assembly="DotNetOpenAuth.Contracts"/> + </assemblies> + </compilation> <customErrors mode="RemoteOnly"/> <authentication mode="Forms"> <forms name="OpenIdRelyingPartySession"/> <!-- named cookie prevents conflicts with other samples --> diff --git a/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx b/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx index 78179f7..a00eccd 100644 --- a/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx +++ b/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx @@ -12,5 +12,4 @@ Visible="False" /> <asp:Label ID="loginCanceledLabel" runat="server" EnableViewState="False" Text="Login canceled" Visible="False" /> - <asp:CheckBox ID="noLoginCheckBox" runat="server" Text="Extensions only (no login) -- most OPs don't yet support this" /> </asp:Content>
\ No newline at end of file diff --git a/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx.designer.cs b/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx.designer.cs index 239d7b8..088e305 100644 --- a/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx.designer.cs +++ b/samples/OpenIdRelyingPartyWebForms/loginProgrammatic.aspx.designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. -// Runtime Version:2.0.50727.4918 +// Runtime Version:2.0.50727.4927 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -66,14 +66,5 @@ namespace OpenIdRelyingPartyWebForms { /// To modify move field declaration from designer file to code-behind file. /// </remarks> protected global::System.Web.UI.WebControls.Label loginCanceledLabel; - - /// <summary> - /// noLoginCheckBox 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 noLoginCheckBox; } } diff --git a/samples/OpenIdRelyingPartyWebFormsVB/Web.config b/samples/OpenIdRelyingPartyWebFormsVB/Web.config index f488900..36174a5 100644 --- a/samples/OpenIdRelyingPartyWebFormsVB/Web.config +++ b/samples/OpenIdRelyingPartyWebFormsVB/Web.config @@ -61,7 +61,11 @@ <system.web> <!--<sessionState cookieless="true" />--> - <compilation debug="true"/> + <compilation debug="true"> + <assemblies> + <remove assembly="DotNetOpenAuth.Contracts"/> + </assemblies> + </compilation> <customErrors mode="RemoteOnly"/> <authentication mode="Forms"> <forms name="OpenIdRelyingPartyVBSession"/> <!-- named cookie prevents conflicts with other samples --> diff --git a/samples/OpenIdWebRingSsoProvider/Web.config b/samples/OpenIdWebRingSsoProvider/Web.config index c32e0e3..163c08b 100644 --- a/samples/OpenIdWebRingSsoProvider/Web.config +++ b/samples/OpenIdWebRingSsoProvider/Web.config @@ -79,6 +79,7 @@ <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <remove assembly="DotNetOpenAuth.Contracts"/> </assemblies> </compilation> diff --git a/samples/OpenIdWebRingSsoRelyingParty/Web.config b/samples/OpenIdWebRingSsoRelyingParty/Web.config index 94ef60c..3f50723 100644 --- a/samples/OpenIdWebRingSsoRelyingParty/Web.config +++ b/samples/OpenIdWebRingSsoRelyingParty/Web.config @@ -83,6 +83,7 @@ <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/> + <remove assembly="DotNetOpenAuth.Contracts"/> </assemblies> </compilation> diff --git a/tools/Publish.targets b/samples/Samples.proj index 415750c..c79a0a4 100644 --- a/tools/Publish.targets +++ b/samples/Samples.proj @@ -1,37 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <!-- Properties that must be set for these targets to function: $(BranchName): The name of the branch being built. Used to determine the web subdirectory for publishing. For creating web sites: $(PublishSamplesWebSiteName): The name of the web site under which the sample web applications will be created/deleted. - $(PublishDocsWebSiteName): The name of the web site under which the documentation web applications will be created/deleted. For creating or publishing to web sites: $(SampleWebRoot): the full physical path to where samples should be copied to, excluding $(BranchName) - $(DocWebRoot): the full physical path to where documentation should be copied to, excluding $(BranchName) --> + <Import Project="$(MSBuildProjectDirectory)\..\tools\DotNetOpenAuth.automated.props"/> - <Target Name="PrepareForIIS"> + <ItemGroup> + <SampleProjects Include="**\*.csproj;**\*.vbproj" /> + <SampleSites Include="OAuthConsumer;OAuthServiceProvider;InfoCardRelyingParty" /> + + <ProjectsToClean Include="@(SampleProjects)" /> + <ProjectsToClean Include="$(SolutionPath)"> + <Targets>@(SampleSites->'%(Identity):Clean')</Targets> + </ProjectsToClean> + </ItemGroup> + + <Target Name="Build" DependsOnTargets="SkipVerification"> + <MSBuild Projects="@(SampleProjects)" BuildInParallel="$(BuildInParallel)" /> + <MSBuild Projects="$(SolutionPath)" Targets="@(SampleSites)" BuildInParallel="$(BuildInParallel)" /> + </Target> + + <Target Name="Prepare"> <Error Text="The BranchName property must be set." Condition=" '$(BranchName)' == '' " /> - + <Error Text="The SampleWebRoot property must be set." Condition=" '$(SampleWebRoot)' == '' " /> <PropertyGroup> <PublishSamplesWebSiteVirtualPath>/$(BranchName)</PublishSamplesWebSiteVirtualPath> - <PublishDocsWebSiteVirtualPath>/$(BranchName)</PublishDocsWebSiteVirtualPath> </PropertyGroup> - </Target> - - <Target Name="PrepareForPublishSamples" - Condition=" '$(SampleWebRoot)' != '' " - DependsOnTargets="BuildSamples"> - <Error Text="The BranchName property must be set." Condition=" '$(BranchName)' == '' " /> - <ItemGroup> <_SampleWebConfigs Include="$(ProjectRoot)samples\*\web.config" /> <PublishableWebSamples Include="@(_SampleWebConfigs->'%(RootDir)%(Directory)')" /> - <SampleSources Include="$(ProjectRoot)samples\**\*" /> - <SampleSources> - <PublishedLocation>$(SampleWebRoot)\$(BranchName)\%(RecursiveDir)%(Filename)%(Extension)</PublishedLocation> - </SampleSources> </ItemGroup> <!-- Trim the trailing slash on the web sample paths so we can just get the leaf directory name. --> @@ -45,6 +48,15 @@ <PublishableWebSamplesVirtualPaths Include="@(_PublishableWebSamplesNoTrailingSlash->'$(PublishSamplesWebSiteVirtualPath)/%(Filename)')" /> <PublishableWebSamplesPhysicalPaths Include="@(_PublishableWebSamplesNoTrailingSlash->'$(SampleWebRoot)\$(BranchName)\%(Filename)')" /> </ItemGroup> + </Target> + + <Target Name="PrepareForPublish" DependsOnTargets="Prepare;Build"> + <ItemGroup> + <SampleSources Include="$(ProjectRoot)samples\**\*" /> + <SampleSources> + <PublishedLocation>$(SampleWebRoot)\$(BranchName)\%(RecursiveDir)%(Filename)%(Extension)</PublishedLocation> + </SampleSources> + </ItemGroup> <FilterItems InputItems="@(SampleSources)" @@ -57,8 +69,8 @@ </ItemGroup> </Target> - <Target Name="PublishSamples" - DependsOnTargets="PrepareForPublishSamples" + <Target Name="Publish" + DependsOnTargets="PrepareForPublish" Inputs="@(PublishableWebSampleSources)" Outputs="@(PublishableWebSampleTargets)" Condition=" '$(SampleWebRoot)' != '' "> @@ -67,34 +79,12 @@ <Copy SourceFiles="@(PublishableWebSampleSources)" DestinationFiles="@(PublishableWebSampleTargets)" SkipUnchangedFiles="true" /> </Target> - <Target Name="UnpublishSamples" - DependsOnTargets="DeleteSampleSitesOnIis" + <Target Name="Unpublish" + DependsOnTargets="DeleteSitesOnIis" Condition=" '$(SampleWebRoot)' != '' "> </Target> - - <Target Name="PrepareForPublishDocumentation" DependsOnTargets="Documentation"> - <ItemGroup> - <DocSources Include="$(ProjectRoot)doc\api\**\*" /> - <DocTargets Include="@(DocSources->'$(DocWebRoot)\$(BranchName)\%(RecursiveDir)%(Filename)%(Extension)')" /> - </ItemGroup> - </Target> - - <Target Name="PublishDocumentation" - DependsOnTargets="PrepareForPublishDocumentation" - Inputs="@(DocSources)" - Outputs="@(DocTargets)" - Condition=" '$(DocWebRoot)' != '' "> - <RemoveDir Directories="$(DocWebRoot)\$(BranchName)" /> - <MakeDir Directories="$(DocWebRoot)\$(BranchName)" /> - <Copy SourceFiles="@(DocSources)" DestinationFiles="@(DocTargets)" SkipUnchangedFiles="true" /> - </Target> - <Target Name="UnpublishDocumentation" - DependsOnTargets="DeleteDocumentationSiteOnIis" - Condition=" '$(DocWebRoot)' != '' "> - </Target> - - <Target Name="CreateSampleSitesOnIis" DependsOnTargets="PrepareForIIS;PrepareForPublishSamples"> + <Target Name="CreateSitesOnIis" DependsOnTargets="Prepare"> <Error Text="The PublishSamplesWebSiteName property must be set." Condition=" '$(PublishSamplesWebSiteName)' == '' "/> <Error Text="The SampleWebRoot property must be set." Condition=" '$(SampleWebRoot)' == '' " /> <CreateWebApplication @@ -104,7 +94,7 @@ /> </Target> - <Target Name="DeleteSampleSitesOnIis" DependsOnTargets="PrepareForIIS"> + <Target Name="DeleteSitesOnIis" DependsOnTargets="Prepare"> <Error Text="The PublishSamplesWebSiteName property must be set." Condition=" '$(PublishSamplesWebSiteName)' == '' "/> <DeleteWebApplication WebSiteName="$(PublishSamplesWebSiteName)" @@ -112,21 +102,5 @@ /> </Target> - <Target Name="CreateDocumentationSiteOnIis" DependsOnTargets="PrepareForIIS"> - <Error Text="The PublishDocsWebSiteName property must be set." Condition=" '$(PublishDocsWebSiteName)' == '' "/> - <Error Text="The DocWebRoot property must be set." Condition=" '$(DocWebRoot)' == '' " /> - <CreateWebApplication - WebSiteName="$(PublishDocsWebSiteName)" - PhysicalPaths="$(DocWebRoot)\$(BranchName)" - VirtualPaths="$(PublishDocsWebSiteVirtualPath)" - /> - </Target> - - <Target Name="DeleteDocumentationSiteOnIis" DependsOnTargets="PrepareForIIS"> - <Error Text="The PublishDocsWebSiteName property must be set." Condition=" '$(PublishDocsWebSiteName)' == '' "/> - <DeleteWebApplication - WebSiteName="$(PublishDocsWebSiteName)" - VirtualPaths="$(PublishDocsWebSiteVirtualPath)" - /> - </Target> + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.automated.targets"/> </Project> diff --git a/samples/tools.proj b/samples/tools.proj new file mode 100644 index 0000000..74f6457 --- /dev/null +++ b/samples/tools.proj @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildProjectDirectory)\..\tools\DotNetOpenAuth.automated.props"/> + + <Target Name="Layout"> + <PropertyGroup> + <ToolsDirectoryNoSlash>$(DropsRoot)$(ProductName)-Tools-$(BuildVersion)</ToolsDirectoryNoSlash> + <ToolsDirectory>$(ToolsDirectoryNoSlash)\</ToolsDirectory> + </PropertyGroup> + + <ItemGroup> + <ToolProjects Include="$(ProjectRoot)Samples\OpenIdOfflineProvider\OpenIdOfflineProvider.csproj"> + <Targets>Sign</Targets> + </ToolProjects> + </ItemGroup> + + <MSBuild Projects="@(ToolProjects)" Targets="%(ToolProjects.Targets)" BuildInParallel="$(BuildInParallel)"> + <Output TaskParameter="TargetOutputs" ItemName="OfflineProvider"/> + </MSBuild> + + <ItemGroup> + <!-- Remove the un-unified assembly. --> + <OfflineProvider Remove="$(OutputPath)$(SignedSubPath)$(ProductName).dll" /> + <!-- add the PDBs --> + <OfflineProvider Include="@(OfflineProvider->'%(SymbolPath)')" /> + <OfflineProviderTargets Include=" + @(OfflineProvider->'$(ToolsDirectory)%(CultureDir)%(FileName)%(Extension)')"/> + + <AllToolSources Include="@(OfflineProvider)" /> + <AllToolTargets Include="@(OfflineProviderTargets)" /> + </ItemGroup> + + <MakeDir Directories="@(ToolsDirectory)" /> + <Copy SourceFiles="@(AllToolSources)" DestinationFiles="@(AllToolTargets)" SkipUnchangedFiles="true" /> + + <!-- remove files that shouldn't be in the directory (perhaps from a previous version). --> + <Purge Directories="$(ToolsDirectory)" IntendedFiles="@(AllToolTargets)" /> + </Target> + + <Target Name="Build" DependsOnTargets="Layout"> + <PropertyGroup> + <ToolsZip>$(ToolsDirectoryNoSlash).zip</ToolsZip> + </PropertyGroup> + + <Zip ZipFileName="$(ToolsZip)" + Files="@(AllToolTargets)" + WorkingDirectory="$(ToolsDirectory)" + ZipLevel="$(ZipLevel)" /> + </Target> + + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.automated.targets"/> +</Project>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs b/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs index 30fa284..0b84398 100644 --- a/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs +++ b/src/DotNetOpenAuth.BuildTasks/AddProjectItems.cs @@ -6,13 +6,13 @@ namespace DotNetOpenAuth.BuildTasks { using System; + using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Build.BuildEngine; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; - using System.Collections; public class AddProjectItems : Task { /// <summary> @@ -49,7 +49,10 @@ namespace DotNetOpenAuth.BuildTasks { BuildItem newItem = project.AddNewItem(itemType, projectItem.ItemSpec, false); var customMetadata = projectItem.CloneCustomMetadata(); foreach (DictionaryEntry entry in customMetadata) { - newItem.SetMetadata((string)entry.Key, (string)entry.Value); + string value = (string)entry.Value; + if (value.Length > 0) { + newItem.SetMetadata((string)entry.Key, value); + } } } diff --git a/src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs b/src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs index f940a72..503e168 100644 --- a/src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs +++ b/src/DotNetOpenAuth.BuildTasks/ChangeProjectReferenceToAssemblyReference.cs @@ -1,47 +1,59 @@ -using System; -using System.Linq; -using System.IO; -using System.Xml; +namespace DotNetOpenAuth.BuildTasks { + using System; + using System.IO; + using System.Linq; + using System.Xml; + using Microsoft.Build.BuildEngine; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; -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 { + private const string msbuildNamespace = "http://schemas.microsoft.com/developer/msbuild/2003"; + /// <summary> /// The projects to alter. /// </summary> [Required] public ITaskItem[] Projects { get; set; } + /// <summary> - /// The project reference to remove. + /// The project references to remove. /// </summary> [Required] - public string ProjectReference { get; set; } + public ITaskItem[] ProjectReferences { get; set; } + /// <summary> - /// The assembly reference to add. + /// The assembly references to add. /// </summary> [Required] - public string Reference { get; set; } + public ITaskItem[] References { get; set; } - const string msbuildNamespace = "http://schemas.microsoft.com/developer/msbuild/2003"; public override bool Execute() { - foreach (var project in Projects) { - Log.LogMessage(MessageImportance.Normal, "Changing P2P references to assembly references in \"{0}\".", project.ItemSpec); + if (this.ProjectReferences.Length != this.References.Length) { + this.Log.LogError("ProjectReferences and References arrays do not have matching lengths."); + } + 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), true); - newReference.SetMetadata("HintPath", Reference); + var projectReferences = doc.EvaluatedItems.OfType<BuildItem>().Where(item => item.Name == "ProjectReference"); + var matchingReferences = from reference in projectReferences + join refToRemove in this.ProjectReferences on reference.Include equals refToRemove.ItemSpec + let addIndex = Array.IndexOf(this.ProjectReferences, refToRemove) + select new { Remove = reference, Add = this.References[addIndex] }; + foreach (var matchingReference in matchingReferences) { + this.Log.LogMessage("Removing project reference to \"{0}\" from \"{1}\".", matchingReference.Remove.Include, project.ItemSpec); + doc.RemoveItem(matchingReference.Remove); + if (matchingReference.Add.ItemSpec != "REMOVE") { + this.Log.LogMessage("Adding assembly reference to \"{0}\" to \"{1}\".", matchingReference.Add.ItemSpec, project.ItemSpec); + var newReference = doc.AddNewItem("Reference", Path.GetFileNameWithoutExtension(matchingReference.Add.ItemSpec), true); + newReference.SetMetadata("HintPath", matchingReference.Add.ItemSpec); + } + } doc.Save(project.ItemSpec); } diff --git a/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs b/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs index 38f3b50..5b097ab 100644 --- a/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs +++ b/src/DotNetOpenAuth.BuildTasks/CopyWithTokenSubstitution.cs @@ -56,7 +56,12 @@ namespace DotNetOpenAuth.BuildTasks { for (int i = 0; i < this.SourceFiles.Length; i++) { string sourcePath = this.SourceFiles[i].ItemSpec; string destPath = this.DestinationFiles[i].ItemSpec; - bool skipUnchangedFiles = bool.Parse(this.SourceFiles[i].GetMetadata("SkipUnchangedFiles")); + bool skipUnchangedFiles; + bool.TryParse(this.SourceFiles[i].GetMetadata("SkipUnchangedFiles"), out skipUnchangedFiles); + + if (!Directory.Exists(Path.GetDirectoryName(destPath))) { + Directory.CreateDirectory(Path.GetDirectoryName(destPath)); + } if (string.IsNullOrEmpty(this.SourceFiles[i].GetMetadata("BeforeTokens"))) { // this is just a standard copy without token substitution @@ -65,7 +70,7 @@ namespace DotNetOpenAuth.BuildTasks { continue; } - Log.LogMessage(MessageImportance.Normal, "Copying \"{0}\" -> \"{1}\"", sourcePath, destPath); + Log.LogMessage(MessageImportance.Normal, "Copying file from \"{0}\" to \"{1}\"", sourcePath, destPath); File.Copy(sourcePath, destPath, true); } else { // We deliberably consider newer destination files to be up-to-date rather than @@ -85,9 +90,6 @@ namespace DotNetOpenAuth.BuildTasks { } using (StreamReader sr = File.OpenText(sourcePath)) { - if (!Directory.Exists(Path.GetDirectoryName(destPath))) { - Directory.CreateDirectory(Path.GetDirectoryName(destPath)); - } using (StreamWriter sw = File.CreateText(destPath)) { StringBuilder line = new StringBuilder(); while (!sr.EndOfStream) { diff --git a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj index 3f76f78..365bec5 100644 --- a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj +++ b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.csproj @@ -118,6 +118,7 @@ <Compile Include="JsPack.cs" /> <Compile Include="NativeMethods.cs" /> <Compile Include="ParseMaster.cs" /> + <Compile Include="PathSegment.cs" /> <Compile Include="Publicize.cs" /> <Compile Include="Purge.cs" /> <Compile Include="ReSignDelaySignedAssemblies.cs" /> @@ -131,6 +132,7 @@ <DependentUpon>TaskStrings.resx</DependentUpon> </Compile> <Compile Include="Trim.cs" /> + <Compile Include="Utilities.cs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="TaskStrings.resx"> diff --git a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln index 34a8e46..f3e3982 100644 --- a/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln +++ b/src/DotNetOpenAuth.BuildTasks/DotNetOpenAuth.BuildTasks.sln @@ -4,11 +4,20 @@ Microsoft Visual Studio Solution File, Format Version 11.00 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{ABBE14A3-0404-4123-9093-E598C3DD3E9B}" ProjectSection(SolutionItems) = preProject ..\..\build.proj = ..\..\build.proj + ..\..\doc\doc.proj = ..\..\doc\doc.proj + ..\..\tools\DotNetOpenAuth.automated.props = ..\..\tools\DotNetOpenAuth.automated.props + ..\..\tools\DotNetOpenAuth.automated.targets = ..\..\tools\DotNetOpenAuth.automated.targets ..\..\lib\DotNetOpenAuth.BuildTasks.targets = ..\..\lib\DotNetOpenAuth.BuildTasks.targets ..\..\tools\DotNetOpenAuth.Common.Settings.targets = ..\..\tools\DotNetOpenAuth.Common.Settings.targets ..\..\tools\DotNetOpenAuth.props = ..\..\tools\DotNetOpenAuth.props ..\..\tools\DotNetOpenAuth.targets = ..\..\tools\DotNetOpenAuth.targets ..\..\tools\DotNetOpenAuth.Versioning.targets = ..\..\tools\DotNetOpenAuth.Versioning.targets + ..\..\tools\drop.proj = ..\..\tools\drop.proj + ..\..\projecttemplates\projecttemplates.proj = ..\..\projecttemplates\projecttemplates.proj + ..\..\samples\Samples.proj = ..\..\samples\Samples.proj + ..\..\samples\tools.proj = ..\..\samples\tools.proj + ..\..\vsi\vsi.proj = ..\..\vsi\vsi.proj + ..\..\vsix\vsix.proj = ..\..\vsix\vsix.proj EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetOpenAuth.BuildTasks", "DotNetOpenAuth.BuildTasks.csproj", "{AC231A51-EF60-437C-A33F-AF8ADEB8EB74}" diff --git a/src/DotNetOpenAuth.BuildTasks/FixupReferenceHintPaths.cs b/src/DotNetOpenAuth.BuildTasks/FixupReferenceHintPaths.cs index 13a4b8f..babaab3 100644 --- a/src/DotNetOpenAuth.BuildTasks/FixupReferenceHintPaths.cs +++ b/src/DotNetOpenAuth.BuildTasks/FixupReferenceHintPaths.cs @@ -40,7 +40,13 @@ namespace DotNetOpenAuth.BuildTasks { // Figure out what the assembly names are of the references that are available. AssemblyName[] availableReferences = new AssemblyName[this.References.Length]; for (int i = 0; i < this.References.Length; i++) { - availableReferences[i] = AssemblyName.GetAssemblyName(this.References[i].ItemSpec); + if (File.Exists(this.References[i].ItemSpec)) { + availableReferences[i] = AssemblyName.GetAssemblyName(this.References[i].ItemSpec); + } else { + availableReferences[i] = new AssemblyName(Path.GetFileNameWithoutExtension(this.References[i].ItemSpec)) { + CodeBase = this.References[i].GetMetadata("FullPath"), + }; + } } foreach (var projectTaskItem in this.Projects) { diff --git a/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs b/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs index 1a8a17d..d162cd6 100644 --- a/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs +++ b/src/DotNetOpenAuth.BuildTasks/MergeProjectWithVSTemplate.cs @@ -7,18 +7,27 @@ namespace DotNetOpenAuth.BuildTasks { using System; using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Diagnostics.Contracts; + using System.Globalization; + using System.IO; using System.Linq; using System.Text; - using Microsoft.Build.Framework; - using Microsoft.Build.Utilities; using System.Xml.Linq; - using System.IO; using Microsoft.Build.BuildEngine; - using System.Diagnostics.Contracts; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; public class MergeProjectWithVSTemplate : Task { internal const string VSTemplateNamespace = "http://schemas.microsoft.com/developer/vstemplate/2005"; + internal const string VsixNamespace = "http://schemas.microsoft.com/developer/vsx-schema/2010"; + + /// <summary> + /// A dictionary where the key is the project name and the value is the path contribution. + /// </summary> + private Dictionary<string, string> vsixContributionToPath = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + [Required] public string[] ProjectItemTypes { get; set; } @@ -26,13 +35,44 @@ namespace DotNetOpenAuth.BuildTasks { public string[] ReplaceParametersExtensions { get; set; } [Required] - public ITaskItem[] Templates { get; set; } + public ITaskItem[] SourceTemplates { get; set; } + + [Required] + public ITaskItem[] SourceProjects { get; set; } + + [Required] + public ITaskItem[] DestinationTemplates { get; set; } + + public ITaskItem[] SourcePathExceptions { get; set; } + + /// <summary> + /// Gets or sets the maximum length a project item's relative path should + /// be limited to, artificially renaming them as necessary. + /// </summary> + /// <value>Use 0 to disable the renaming feature.</value> + public int MaximumRelativePathLength { get; set; } + + /// <summary> + /// Gets or sets the project item paths from the source project to copy to the destination location. + /// </summary> + [Output] + public ITaskItem[] ProjectItems { get; set; } /// <summary> /// Executes this instance. /// </summary> public override bool Execute() { - foreach(ITaskItem sourceTemplateTaskItem in this.Templates) { + if (this.DestinationTemplates.Length != this.SourceTemplates.Length) { + this.Log.LogError("SourceTemplates array has length {0} while DestinationTemplates array has length {1}, but must equal.", this.SourceTemplates.Length, this.DestinationTemplates.Length); + } + if (this.SourceProjects.Length != this.SourceTemplates.Length) { + this.Log.LogError("SourceTemplates array has length {0} while SourceProjects array has length {1}, but must equal.", this.SourceTemplates.Length, this.SourceProjects.Length); + } + + var projectItemsToCopy = new List<ITaskItem>(); + + for (int iTemplate = 0; iTemplate < this.SourceTemplates.Length; iTemplate++) { + ITaskItem sourceTemplateTaskItem = this.SourceTemplates[iTemplate]; var template = XElement.Load(sourceTemplateTaskItem.ItemSpec); var templateContentElement = template.Element(XName.Get("TemplateContent", VSTemplateNamespace)); var projectElement = templateContentElement.Element(XName.Get("Project", VSTemplateNamespace)); @@ -41,37 +81,65 @@ namespace DotNetOpenAuth.BuildTasks { continue; } - var projectPath = Path.Combine(Path.GetDirectoryName(sourceTemplateTaskItem.ItemSpec), projectElement.Attribute("File").Value); + var projectPath = this.SourceProjects[iTemplate].ItemSpec; + var projectDirectory = Path.GetDirectoryName(Path.Combine(Path.GetDirectoryName(sourceTemplateTaskItem.GetMetadata("FullPath")), projectElement.Attribute("File").Value)); Log.LogMessage("Merging project \"{0}\" with \"{1}\".", projectPath, sourceTemplateTaskItem.ItemSpec); var sourceProject = new Project(); sourceProject.Load(projectPath); + var projectItems = sourceProject.EvaluatedItems.Cast<BuildItem>().Where(item => this.ProjectItemTypes.Contains(item.Name)); + + // Figure out where every project item is in source, and where it will go in the destination, + // taking into account a given maximum path length that may require that we shorten the path. + PathSegment root = new PathSegment(); + root.Add(projectItems.Select(item => item.Include)); + root.EnsureSelfAndChildrenNoLongerThan(this.MaximumRelativePathLength); // Collect the project items from the project that are appropriate // to include in the .vstemplate file. - var itemsByFolder = from item in sourceProject.EvaluatedItems.Cast<BuildItem>() - where this.ProjectItemTypes.Contains(item.Name) - orderby item.Include - group item by Path.GetDirectoryName(item.Include); - foreach (var folder in itemsByFolder) { - XElement parentNode = FindOrCreateParent(folder.Key, projectElement); - - foreach (var item in folder) { - bool replaceParameters = this.ReplaceParametersExtensions.Contains(Path.GetExtension(item.Include)); + foreach (var folder in root.SelfAndDescendents.Where(path => !path.IsLeaf && path.LeafChildren.Any())) { + XElement parentNode = projectElement; + parentNode = FindOrCreateParent(folder.CurrentPath, projectElement); + if (folder.NameChanged) { + parentNode.SetAttributeValue("TargetFolderName", folder.OriginalName); + } + + foreach (var item in folder.LeafChildren) { var itemName = XName.Get("ProjectItem", VSTemplateNamespace); - var projectItem = parentNode.Elements(itemName).FirstOrDefault(el => string.Equals(el.Value, Path.GetFileName(item.Include), StringComparison.OrdinalIgnoreCase)); + // The project item MAY be hard-coded in the .vstemplate file, under the original name. + var projectItem = parentNode.Elements(itemName).FirstOrDefault(el => string.Equals(el.Value, Path.GetFileName(item.OriginalName), StringComparison.OrdinalIgnoreCase)); if (projectItem == null) { - projectItem = new XElement(itemName, Path.GetFileName(item.Include)); + projectItem = new XElement(itemName, item.CurrentName); parentNode.Add(projectItem); } - if (replaceParameters) { + if (item.NameChanged) { + projectItem.Value = item.CurrentName; // set Value in case it was a hard-coded item in the .vstemplate file. + projectItem.SetAttributeValue("TargetFileName", item.OriginalName); + } + if (this.ReplaceParametersExtensions.Contains(Path.GetExtension(item.OriginalPath))) { projectItem.SetAttributeValue("ReplaceParameters", "true"); } } } - template.Save(sourceTemplateTaskItem.ItemSpec); + template.Save(this.DestinationTemplates[iTemplate].ItemSpec); + foreach (var pair in root.LeafDescendents) { + TaskItem item = new TaskItem(Path.Combine(Path.GetDirectoryName(this.SourceTemplates[iTemplate].ItemSpec), pair.OriginalPath)); + string apparentSource = Path.Combine(Path.GetDirectoryName(this.SourceTemplates[iTemplate].ItemSpec), pair.OriginalPath); + var sourcePathException = this.SourcePathExceptions.FirstOrDefault(ex => string.Equals(ex.ItemSpec, apparentSource)); + if (sourcePathException != null) { + item.SetMetadata("SourceFullPath", sourcePathException.GetMetadata("ActualSource")); + } else { + item.SetMetadata("SourceFullPath", Path.GetFullPath(apparentSource)); + } + item.SetMetadata("DestinationFullPath", Path.GetFullPath(Path.Combine(Path.GetDirectoryName(this.DestinationTemplates[iTemplate].ItemSpec), pair.CurrentPath))); + item.SetMetadata("RecursiveDir", Path.GetDirectoryName(this.SourceTemplates[iTemplate].ItemSpec)); + item.SetMetadata("Transform", this.ReplaceParametersExtensions.Contains(Path.GetExtension(pair.OriginalName)) ? "true" : "false"); + projectItemsToCopy.Add(item); + } } + this.ProjectItems = projectItemsToCopy.ToArray(); + return !Log.HasLoggedErrors; } diff --git a/src/DotNetOpenAuth.BuildTasks/PathSegment.cs b/src/DotNetOpenAuth.BuildTasks/PathSegment.cs new file mode 100644 index 0000000..56655ff --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/PathSegment.cs @@ -0,0 +1,321 @@ +//----------------------------------------------------------------------- +// <copyright file="PathSegment.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Diagnostics; + using System.Diagnostics.Contracts; + using System.IO; + using System.Linq; + using System.Text; + + internal class PathSegment { + private const float ParentChildResizeThreshold = 0.30f; + private readonly PathSegment parent; + private readonly string originalName; + private string currentName; + private bool minimized; + private static readonly string[] ReservedFileNames = "CON PRN AUX CLOCK$ NUL COM0 COM1 COM2 COM3 COM4 COM5 COM6 COM7 COM8 COM9 LPT0 LPT1 LPT2 LPT3 LPT4 LPT5 LPT6 LPT7 LPT8 LPT9".Split(' '); + + internal PathSegment() { + this.currentName = string.Empty; + this.originalName = string.Empty; + this.minimized = true; + this.Children = new Collection<PathSegment>(); + } + + private PathSegment(string originalName, PathSegment parent) + : this() { + Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(originalName)); + Contract.Requires<ArgumentNullException>(parent != null); + this.currentName = this.originalName = originalName; + this.parent = parent; + this.minimized = false; + } + + internal string OriginalPath { + get { + if (this.parent != null) { + return Path.Combine(this.parent.OriginalPath, this.originalName); + } else { + return this.originalName; + } + } + } + + internal string CurrentPath { + get { + if (this.parent != null) { + return Path.Combine(this.parent.CurrentPath, this.currentName); + } else { + return this.currentName; + } + } + } + + internal string CurrentName { + get { return this.currentName; } + } + + internal string OriginalName { + get { return this.originalName; } + } + + private int SegmentCount { + get { + int parents = this.parent != null ? this.parent.SegmentCount : 0; + return parents + 1; + } + } + + internal int FullLength { + get { + if (this.parent != null) { + int parentLength = this.parent.FullLength; + if (parentLength > 0) { + parentLength++; // allow for an in between slash + } + return parentLength + this.currentName.Length; + } else { + return this.currentName.Length; + } + } + } + + internal bool NameChanged { + get { return !string.Equals(this.currentName, this.originalName, StringComparison.OrdinalIgnoreCase); } + } + + internal bool IsLeaf { + get { return this.Children.Count == 0; } + } + + internal IEnumerable<PathSegment> Descendents { + get { + IEnumerable<PathSegment> result = this.Children; + foreach (PathSegment child in this.Children) { + result = result.Concat(child.Descendents); + } + + return result; + } + } + + internal IEnumerable<PathSegment> Ancestors { + get { + PathSegment parent = this.parent; + while (parent != null) { + yield return parent; + parent = parent.parent; + } + } + } + + internal IEnumerable<PathSegment> SelfAndDescendents { + get { + yield return this; + foreach (var child in this.Descendents) { + yield return child; + } + } + } + + internal IEnumerable<PathSegment> SelfAndAncestors { + get { + yield return this; + foreach (var parent in this.Ancestors) { + yield return parent; + } + } + } + + internal IEnumerable<PathSegment> LeafChildren { + get { return this.Children.Where(child => child.IsLeaf); } + } + + internal IEnumerable<PathSegment> LeafDescendents { + get { return this.Descendents.Where(child => child.IsLeaf); } + } + + internal IEnumerable<PathSegment> Siblings { + get { return this.parent != null ? this.parent.Children : Enumerable.Empty<PathSegment>(); } + } + + internal Collection<PathSegment> Children { get; private set; } + + public override string ToString() { + string path; + if (this.NameChanged) { + path = "{" + this.originalName + " => " + this.currentName + "}"; + } else { + path = this.currentName; + } + + if (path.Length > 0 && !this.IsLeaf) { + path += "\\"; + } + + if (this.parent != null) { + path = parent.ToString() + path; + } + + return path; + } + + internal PathSegment Add(string originalPath) { + Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(originalPath)); + Contract.Ensures(Contract.Result<PathSegment>() != null); + string[] segments = originalPath.Split(Path.DirectorySeparatorChar); + return this.Add(segments, 0); + } + + internal void Add(IEnumerable<string> originalPaths) { + foreach (string path in originalPaths) { + this.Add(path); + } + } + + internal int EnsureSelfAndChildrenNoLongerThan(int maxLength) { + Contract.Requires<ArgumentOutOfRangeException>(maxLength > 0, "A path can only have a positive length."); + Contract.Requires<ArgumentOutOfRangeException>(this.parent == null || maxLength > this.parent.FullLength + 1, "A child path cannot possibly be made shorter than its parent."); + Contract.Ensures(Contract.Result<int>() <= maxLength); + const int uniqueBase = 16; + + // Find the items that are too long, and always work on the longest one + var longPaths = this.SelfAndDescendents.Where(path => path.FullLength > maxLength).OrderByDescending(path => path.FullLength); + PathSegment longPath; + while ((longPath = longPaths.FirstOrDefault()) != null) { + // Keep working on this one until it's short enough. + do { + int tooLongBy = longPath.FullLength - maxLength; + var longSegments = longPath.SelfAndAncestors.Where(segment => !segment.minimized).OrderByDescending(segment => segment.CurrentName.Length); + PathSegment longestSegment = longSegments.FirstOrDefault(); + if (longestSegment == null) { + throw new InvalidOperationException("Unable to shrink path length sufficiently."); + } + PathSegment secondLongestSegment = longSegments.Skip(1).FirstOrDefault(); + int shortenByUpTo; + if (secondLongestSegment != null) { + shortenByUpTo = Math.Min(tooLongBy, Math.Max(1, longestSegment.CurrentName.Length - secondLongestSegment.CurrentName.Length)); + } else { + shortenByUpTo = tooLongBy; + } + int minimumGuaranteedUniqueLength = Math.Max(1, RoundUp(Math.Log(longestSegment.Siblings.Count(), uniqueBase))); + int allowableSegmentLength = Math.Max(minimumGuaranteedUniqueLength, longestSegment.CurrentName.Length - shortenByUpTo); + if (allowableSegmentLength >= longestSegment.CurrentName.Length) { + // We can't make this segment any shorter. + longestSegment.minimized = true; + } + longestSegment.currentName = longestSegment.CreateUniqueShortFileName(longestSegment.CurrentName, allowableSegmentLength); + } while (longPath.FullLength > maxLength); + } + + // Return the total length of self or longest child. + return this.SelfAndDescendents.Max(c => c.FullLength); + } + + internal PathSegment FindByOriginalPath(string originalPath) { + Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(originalPath)); + string[] segments = originalPath.Split(Path.DirectorySeparatorChar); + return this.FindByOriginalPath(segments, 0); + } + + private string GetUniqueShortName(string preferredPrefix, string preferredSuffix, int allowableLength) { + Contract.Requires<ArgumentNullException>(preferredPrefix != null); + Contract.Requires<ArgumentNullException>(preferredSuffix != null); + Contract.Requires<ArgumentException>(allowableLength > 0); + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>())); + Contract.Ensures(Contract.Result<string>().Length <= allowableLength); + string candidateName = string.Empty; + int i; + for (i = -1; candidateName.Length == 0 || ReservedFileNames.Contains(candidateName, StringComparer.OrdinalIgnoreCase) || this.Siblings.Any(child => string.Equals(child.CurrentName, candidateName, StringComparison.OrdinalIgnoreCase)); i++) { + string unique = i < 0 ? string.Empty : i.ToString("x"); + if (allowableLength < unique.Length) { + throw new InvalidOperationException("Unable to shorten path sufficiently to fit constraints."); + } + + candidateName = unique; + + // Suffix gets higher priority than the prefix, but only if the entire suffix can be appended. + if (candidateName.Length + preferredSuffix.Length <= allowableLength) { + candidateName += preferredSuffix; + } + + // Now prepend as much of the prefix as fits. + candidateName = preferredPrefix.Substring(0, Math.Min(allowableLength - candidateName.Length, preferredPrefix.Length)) + candidateName; + } + + return candidateName; + } + + private static int RoundUp(double value) { + int roundedValue = (int)value; + if (roundedValue < value) { + roundedValue++; + } + + return roundedValue; + } + + private string CreateUniqueShortFileName(string fileName, int targetLength) { + Contract.Requires<ArgumentException>(!string.IsNullOrEmpty(fileName)); + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result<string>())); + Contract.Ensures(Contract.Result<string>().Length <= targetLength); + + // The filename may already full within the target length. + if (fileName.Length <= targetLength) { + return fileName; + } + + string preferredPrefix = Path.GetFileNameWithoutExtension(fileName); + string preferredSuffix = Path.GetExtension(fileName); + + string shortenedFileName = GetUniqueShortName(preferredPrefix, preferredSuffix, targetLength); + return shortenedFileName; + } + + private void ShortenThis(int targetLength) { + this.currentName = CreateUniqueShortFileName(this.originalName, targetLength); + } + + private PathSegment Add(string[] segments, int segmentIndex) { + Contract.Requires<ArgumentNullException>(segments != null); + Contract.Requires<ArgumentOutOfRangeException>(segmentIndex < segments.Length); + Contract.Ensures(Contract.Result<PathSegment>() != null); + var match = this.Children.SingleOrDefault(child => String.Equals(child.originalName, segments[segmentIndex])); + if (match == null) { + match = new PathSegment(segments[segmentIndex], this); + this.Children.Add(match); + if (segments.Length == segmentIndex + 1) { + return match; + } + } + + return match.Add(segments, segmentIndex + 1); + } + + private PathSegment FindByOriginalPath(string[] segments, int segmentIndex) { + Contract.Requires<ArgumentNullException>(segments != null); + Contract.Requires<ArgumentOutOfRangeException>(segmentIndex < segments.Length); + if (string.Equals(this.originalName, segments[segmentIndex], StringComparison.OrdinalIgnoreCase)) { + if (segmentIndex == segments.Length - 1) { + return this; + } + + foreach (var child in this.Children) { + var match = child.FindByOriginalPath(segments, segmentIndex + 1); + if (match != null) { + return match; + } + } + } + + return null; + } + } +} diff --git a/src/DotNetOpenAuth.BuildTasks/Purge.cs b/src/DotNetOpenAuth.BuildTasks/Purge.cs index e19e485..cf1a214 100644 --- a/src/DotNetOpenAuth.BuildTasks/Purge.cs +++ b/src/DotNetOpenAuth.BuildTasks/Purge.cs @@ -7,12 +7,12 @@ namespace DotNetOpenAuth.BuildTasks { using System; using System.Collections.Generic; + using System.IO; using System.Linq; using System.Text; - using Microsoft.Build.Utilities; - using Microsoft.Build.Framework; - using System.IO; using System.Text.RegularExpressions; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; /// <summary> /// Purges directory trees of all directories and files that are not on a whitelist. @@ -40,6 +40,7 @@ namespace DotNetOpenAuth.BuildTasks { /// <summary> /// Gets or sets the files that should be NOT be purged. /// </summary> + [Required] public ITaskItem[] IntendedFiles { get; set; } /// <summary> @@ -82,7 +83,7 @@ namespace DotNetOpenAuth.BuildTasks { } private static string NormalizePath(string path) { - return Regex.Replace(path, @"\\+", @"\"); + return Path.GetFullPath(Regex.Replace(path, @"\\+", @"\")); } } } diff --git a/src/DotNetOpenAuth.BuildTasks/Utilities.cs b/src/DotNetOpenAuth.BuildTasks/Utilities.cs new file mode 100644 index 0000000..80e1733 --- /dev/null +++ b/src/DotNetOpenAuth.BuildTasks/Utilities.cs @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------- +// <copyright file="Utilities.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.BuildTasks { + using System; + using System.Collections.Generic; + using System.Diagnostics.Contracts; + using System.Linq; + using System.Text; + + internal static class Utilities { + internal static string SuppressCharacters(string fileName, char[] suppress, char replacement) { + Contract.Requires<ArgumentNullException>(fileName != null); + Contract.Requires<ArgumentNullException>(suppress != null); + + if (fileName.IndexOfAny(suppress) < 0) { + return fileName; + } + + StringBuilder builder = new StringBuilder(fileName); + foreach (char ch in suppress) { + builder.Replace(ch, replacement); + } + + return builder.ToString(); + } + } +} diff --git a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj index 632d2fd..6540714 100644 --- a/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj +++ b/src/DotNetOpenAuth.Test/DotNetOpenAuth.Test.csproj @@ -289,6 +289,7 @@ <Compile Include="OpenId\RelyingParty\NegativeAuthenticationResponseTests.cs" /> <Compile Include="OpenId\RelyingParty\OpenIdTextBoxTests.cs" /> <Compile Include="OpenId\RelyingParty\PositiveAnonymousResponseTests.cs" /> + <Compile Include="OpenId\RelyingParty\PositiveAuthenticationResponseSnapshotTests.cs" /> <Compile Include="OpenId\RelyingParty\PositiveAuthenticationResponseTests.cs" /> <Compile Include="OpenId\RelyingParty\OpenIdRelyingPartyTests.cs" /> <Compile Include="OpenId\RelyingParty\RelyingPartySecuritySettingsTests.cs" /> @@ -374,4 +375,4 @@ </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" /> -</Project> +</Project>
\ No newline at end of file diff --git a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs index 8a8ae25..2b0e8f9 100644 --- a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs @@ -153,6 +153,7 @@ namespace DotNetOpenAuth.Test.Messaging Match m = Regex.Match(req.ContentType, "multipart/form-data; boundary=(.+)"); Assert.IsTrue(m.Success, "Content-Type HTTP header not set correctly."); string boundary = m.Groups[1].Value; + boundary = boundary.Substring(0, boundary.IndexOf(';')); // trim off charset string expectedEntity = "--{0}\r\nContent-Disposition: form-data; name=\"a\"\r\n\r\nb\r\n--{0}--\r\n"; expectedEntity = string.Format(expectedEntity, boundary); string actualEntity = httpHandler.RequestEntityAsString; diff --git a/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs b/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs index 16576d6..10045de 100644 --- a/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/OutgoingWebResponseTests.cs @@ -6,6 +6,7 @@ namespace DotNetOpenAuth.Test.Messaging { using System.Net; + using System.Net.Mime; using System.Text; using DotNetOpenAuth.Messaging; using NUnit.Framework; @@ -30,7 +31,8 @@ namespace DotNetOpenAuth.Test.Messaging { CollectionAssert.AreEqual(expectedBuffer, actualBuffer); // Verify that the header was set correctly. - Assert.AreEqual(encoding.HeaderName, response.Headers[HttpResponseHeader.ContentEncoding]); + Assert.IsNull(response.Headers[HttpResponseHeader.ContentEncoding]); + Assert.AreEqual(encoding.HeaderName, new ContentType(response.Headers[HttpResponseHeader.ContentType]).CharSet); } } } diff --git a/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshotTests.cs b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshotTests.cs new file mode 100644 index 0000000..e069c44 --- /dev/null +++ b/src/DotNetOpenAuth.Test/OpenId/RelyingParty/PositiveAuthenticationResponseSnapshotTests.cs @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------- +// <copyright file="PositiveAuthenticationResponseSnapshotTests.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace DotNetOpenAuth.Test.OpenId.RelyingParty { + using System.Collections.Generic; + using System.IO; + using System.Runtime.Serialization; + using System.Runtime.Serialization.Formatters.Binary; + using DotNetOpenAuth.OpenId; + using DotNetOpenAuth.OpenId.Messages; + using DotNetOpenAuth.OpenId.RelyingParty; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; + + [TestClass] + public class PositiveAuthenticationResponseSnapshotTests : OpenIdTestBase { + /// <summary> + /// Verifies that the PositiveAuthenticationResponseSnapshot is serializable, + /// as required by the <see cref="OpenIdRelyingPartyAjaxControlBase"/> class. + /// </summary> + [TestMethod] + public void Serializable() { + var response = new Mock<IAuthenticationResponse>(MockBehavior.Strict); + response.Setup(o => o.ClaimedIdentifier).Returns(VanityUri); + response.Setup(o => o.FriendlyIdentifierForDisplay).Returns(VanityUri.AbsoluteUri); + response.Setup(o => o.Status).Returns(AuthenticationStatus.Authenticated); + response.Setup(o => o.Provider).Returns(new ProviderEndpointDescription(OPUri, Protocol.Default.Version)); + response.Setup(o => o.GetUntrustedCallbackArguments()).Returns(new Dictionary<string, string>()); + response.Setup(o => o.GetCallbackArguments()).Returns(new Dictionary<string, string>()); + var snapshot = new PositiveAuthenticationResponseSnapshot(response.Object); + MemoryStream ms = new MemoryStream(); + IFormatter formatter = new BinaryFormatter(); + formatter.Serialize(ms, snapshot); + } + } +} diff --git a/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd index 18e1c5c..a9c5965 100644 --- a/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd +++ b/src/DotNetOpenAuth/Configuration/DotNetOpenAuth.xsd @@ -658,6 +658,14 @@ </xs:documentation> </xs:annotation> </xs:attribute> + <xs:attribute name="cacheDiscovery" type="xs:boolean"> + <xs:annotation> + <xs:documentation> + Whether the results of identifier discovery should be cached for a short time to improve performance + on subsequent requests, at the potential risk of reading stale data. + </xs:documentation> + </xs:annotation> + </xs:attribute> </xs:complexType> </xs:element> <xs:element name="oauth"> diff --git a/src/DotNetOpenAuth/Configuration/DotNetOpenAuthSection.cs b/src/DotNetOpenAuth/Configuration/DotNetOpenAuthSection.cs index aa956d1..117a542 100644 --- a/src/DotNetOpenAuth/Configuration/DotNetOpenAuthSection.cs +++ b/src/DotNetOpenAuth/Configuration/DotNetOpenAuthSection.cs @@ -51,7 +51,10 @@ namespace DotNetOpenAuth.Configuration { /// Gets the configuration section from the .config file. /// </summary> public static DotNetOpenAuthSection Configuration { - get { return (DotNetOpenAuthSection)ConfigurationManager.GetSection(SectionName) ?? new DotNetOpenAuthSection(); } + get { + Contract.Ensures(Contract.Result<DotNetOpenAuthSection>() != null); + return (DotNetOpenAuthSection)ConfigurationManager.GetSection(SectionName) ?? new DotNetOpenAuthSection(); + } } /// <summary> @@ -59,8 +62,14 @@ namespace DotNetOpenAuth.Configuration { /// </summary> [ConfigurationProperty(MessagingElementName)] public MessagingElement Messaging { - get { return (MessagingElement)this[MessagingElementName] ?? new MessagingElement(); } - set { this[MessagingElementName] = value; } + get { + Contract.Ensures(Contract.Result<MessagingElement>() != null); + return (MessagingElement)this[MessagingElementName] ?? new MessagingElement(); + } + + set { + this[MessagingElementName] = value; + } } /// <summary> @@ -68,8 +77,14 @@ namespace DotNetOpenAuth.Configuration { /// </summary> [ConfigurationProperty(OpenIdElementName)] internal OpenIdElement OpenId { - get { return (OpenIdElement)this[OpenIdElementName] ?? new OpenIdElement(); } - set { this[OpenIdElementName] = value; } + get { + Contract.Ensures(Contract.Result<OpenIdElement>() != null); + return (OpenIdElement)this[OpenIdElementName] ?? new OpenIdElement(); + } + + set { + this[OpenIdElementName] = value; + } } /// <summary> @@ -77,8 +92,14 @@ namespace DotNetOpenAuth.Configuration { /// </summary> [ConfigurationProperty(OAuthElementName)] internal OAuthElement OAuth { - get { return (OAuthElement)this[OAuthElementName] ?? new OAuthElement(); } - set { this[OAuthElementName] = value; } + get { + Contract.Ensures(Contract.Result<OAuthElement>() != null); + return (OAuthElement)this[OAuthElementName] ?? new OAuthElement(); + } + + set { + this[OAuthElementName] = value; + } } /// <summary> @@ -86,8 +107,14 @@ namespace DotNetOpenAuth.Configuration { /// </summary> [ConfigurationProperty(ReportingElementName)] internal ReportingElement Reporting { - get { return (ReportingElement)this[ReportingElementName] ?? new ReportingElement(); } - set { this[ReportingElementName] = value; } + get { + Contract.Ensures(Contract.Result<ReportingElement>() != null); + return (ReportingElement)this[ReportingElementName] ?? new ReportingElement(); + } + + set { + this[ReportingElementName] = value; + } } } } diff --git a/src/DotNetOpenAuth/DotNetOpenAuth.csproj b/src/DotNetOpenAuth/DotNetOpenAuth.csproj index d0c4d94..7f5b298 100644 --- a/src/DotNetOpenAuth/DotNetOpenAuth.csproj +++ b/src/DotNetOpenAuth/DotNetOpenAuth.csproj @@ -775,7 +775,31 @@ http://opensource.org/licenses/ms-pl.html </BootstrapperPackage> <Content Include="DotNetOpenAuth.ico" /> </ItemGroup> - <ItemGroup /> + + <ItemGroup> + <SignDependsOn Include="BuildUnifiedProduct" /> + <DelaySignedAssemblies Include="$(ILMergeOutputAssembly); + $(OutputPath)$(ProductName).Contracts.dll; + " /> + </ItemGroup> + <PropertyGroup> + <!-- Don't sign the non-unified version of the assembly. --> + <SuppressTargetPathDelaySignedAssembly>true</SuppressTargetPathDelaySignedAssembly> + </PropertyGroup> + + <Target Name="BuildUnifiedProduct" + DependsOnTargets="Build" + Inputs="@(ILMergeInputAssemblies)" + Outputs="$(ILMergeOutputAssembly)"> + <MakeDir Directories="$(ILMergeOutputAssemblyDirectory)" /> + <ILMerge ExcludeFile="$(ProjectRoot)ILMergeInternalizeExceptions.txt" + InputAssemblies="@(ILMergeInputAssemblies)" + OutputFile="$(ILMergeOutputAssembly)" + KeyFile="$(PublicKeyFile)" + DelaySign="true" + /> + </Target> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.targets" /> -</Project>
\ No newline at end of file +</Project> diff --git a/src/DotNetOpenAuth/Messaging/Channel.cs b/src/DotNetOpenAuth/Messaging/Channel.cs index 1bddf02..7198c78 100644 --- a/src/DotNetOpenAuth/Messaging/Channel.cs +++ b/src/DotNetOpenAuth/Messaging/Channel.cs @@ -16,6 +16,7 @@ namespace DotNetOpenAuth.Messaging { using System.Linq; using System.Net; using System.Net.Cache; + using System.Net.Mime; using System.Text; using System.Threading; using System.Web; @@ -39,6 +40,13 @@ namespace DotNetOpenAuth.Messaging { protected internal const string HttpFormUrlEncoded = "application/x-www-form-urlencoded"; /// <summary> + /// The content-type used on HTTP POST requests where the POST entity is a + /// URL-encoded series of key=value pairs. + /// This includes the <see cref="PostEntityEncoding"/> character encoding. + /// </summary> + protected internal static readonly ContentType HttpFormUrlEncodedContentType = new ContentType(HttpFormUrlEncoded) { CharSet = PostEntityEncoding.WebName }; + + /// <summary> /// The maximum allowable size for a 301 Redirect response before we send /// a 200 OK response with a scripted form POST with the parameters instead /// in order to ensure successfully sending a large payload to another server @@ -927,15 +935,9 @@ namespace DotNetOpenAuth.Messaging { Contract.Requires<ArgumentNullException>(httpRequest != null); Contract.Requires<ArgumentNullException>(fields != null); - httpRequest.ContentType = HttpFormUrlEncoded; - - // Setting the content-encoding to "utf-8" causes Google to reply - // with a 415 UnsupportedMediaType. But adding it doesn't buy us - // anything specific, so we disable it until we know how to get it right. - ////httpRequest.Headers[HttpRequestHeader.ContentEncoding] = PostEntityEncoding.WebName; - string requestBody = MessagingUtilities.CreateQueryString(fields); byte[] requestBytes = PostEntityEncoding.GetBytes(requestBody); + httpRequest.ContentType = HttpFormUrlEncodedContentType.ToString(); httpRequest.ContentLength = requestBytes.Length; Stream requestStream = this.WebRequestHandler.GetRequestStream(httpRequest); try { diff --git a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs index 94990c8..6ce87a8 100644 --- a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs +++ b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs @@ -13,6 +13,7 @@ namespace DotNetOpenAuth.Messaging { using System.Globalization; using System.IO; using System.Net; + using System.Net.Mime; using System.ServiceModel.Channels; using System.Web; @@ -233,7 +234,8 @@ namespace DotNetOpenAuth.Messaging { get { Contract.Ensures(Contract.Result<NameValueCollection>() != null); if (this.form == null) { - if (this.HttpMethod == "POST" && this.Headers[HttpRequestHeader.ContentType] == Channel.HttpFormUrlEncoded) { + ContentType contentType = string.IsNullOrEmpty(this.Headers[HttpRequestHeader.ContentType]) ? null : new ContentType(this.Headers[HttpRequestHeader.ContentType]); + if (this.HttpMethod == "POST" && contentType != null && string.Equals(contentType.MediaType, Channel.HttpFormUrlEncoded, StringComparison.Ordinal)) { StreamReader reader = new StreamReader(this.InputStream); long originalPosition = 0; if (this.InputStream.CanSeek) { diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs index c29ec8c..a52f51b 100644 --- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs +++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs @@ -14,6 +14,7 @@ namespace DotNetOpenAuth.Messaging { using System.IO; using System.Linq; using System.Net; + using System.Net.Mime; using System.Security; using System.Security.Cryptography; using System.Text; @@ -106,14 +107,7 @@ namespace DotNetOpenAuth.Messaging { Contract.Requires<InvalidOperationException>(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired); HttpContext context = HttpContext.Current; - // We use Request.Url for the full path to the server, and modify it - // with Request.RawUrl to capture both the cookieless session "directory" if it exists - // and the original path in case URL rewriting is going on. We don't want to be - // fooled by URL rewriting because we're comparing the actual URL with what's in - // the return_to parameter in some cases. - // Response.ApplyAppPathModifier(builder.Path) would have worked for the cookieless - // session, but not the URL rewriting problem. - return new Uri(context.Request.Url, context.Request.RawUrl); + return HttpRequestInfo.GetPublicFacingUrl(context.Request, context.Request.ServerVariables); } /// <summary> @@ -198,20 +192,19 @@ namespace DotNetOpenAuth.Messaging { string initialPartLeadingBoundary = string.Format(CultureInfo.InvariantCulture, "--{0}\r\n", boundary); string partLeadingBoundary = string.Format(CultureInfo.InvariantCulture, "\r\n--{0}\r\n", boundary); string finalTrailingBoundary = string.Format(CultureInfo.InvariantCulture, "\r\n--{0}--\r\n", boundary); + var contentType = new ContentType("multipart/form-data") { + Boundary = boundary, + CharSet = Channel.PostEntityEncoding.WebName, + }; request.Method = "POST"; - request.ContentType = "multipart/form-data; boundary=" + boundary; + request.ContentType = contentType.ToString(); long contentLength = parts.Sum(p => partLeadingBoundary.Length + p.Length) + finalTrailingBoundary.Length; if (parts.Any()) { contentLength -= 2; // the initial part leading boundary has no leading \r\n } request.ContentLength = contentLength; - // Setting the content-encoding to "utf-8" causes Google to reply - // with a 415 UnsupportedMediaType. But adding it doesn't buy us - // anything specific, so we disable it until we know how to get it right. - ////request.Headers[HttpRequestHeader.ContentEncoding] = Channel.PostEntityEncoding.WebName; - var requestStream = requestHandler.GetRequestStream(request); try { StreamWriter writer = new StreamWriter(requestStream, Channel.PostEntityEncoding); diff --git a/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs b/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs index 52d0e39..cf22bb2 100644 --- a/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs +++ b/src/DotNetOpenAuth/Messaging/OutgoingWebResponse.cs @@ -10,6 +10,7 @@ namespace DotNetOpenAuth.Messaging { using System.Diagnostics.Contracts; using System.IO; using System.Net; + using System.Net.Mime; using System.Text; using System.Threading; using System.Web; @@ -87,7 +88,7 @@ namespace DotNetOpenAuth.Messaging { /// </summary> public string Body { get { return this.ResponseStream != null ? this.GetResponseReader().ReadToEnd() : null; } - set { this.SetResponse(value); } + set { this.SetResponse(value, null); } } /// <summary> @@ -205,13 +206,23 @@ namespace DotNetOpenAuth.Messaging { /// Sets the response to some string, encoded as UTF-8. /// </summary> /// <param name="body">The string to set the response to.</param> - internal void SetResponse(string body) { + /// <param name="contentType">Type of the content. May be null.</param> + internal void SetResponse(string body, ContentType contentType) { if (body == null) { this.ResponseStream = null; return; } - this.Headers[HttpResponseHeader.ContentEncoding] = bodyStringEncoder.HeaderName; + if (contentType == null) { + contentType = new ContentType("text/html"); + contentType.CharSet = bodyStringEncoder.WebName; + } else if (contentType.CharSet != bodyStringEncoder.WebName) { + // clone the original so we're not tampering with our inputs if it came as a parameter. + contentType = new ContentType(contentType.ToString()); + contentType.CharSet = bodyStringEncoder.WebName; + } + + this.Headers[HttpResponseHeader.ContentType] = contentType.ToString(); this.ResponseStream = new MemoryStream(); StreamWriter writer = new StreamWriter(this.ResponseStream, bodyStringEncoder); writer.Write(body); diff --git a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs index b0e938f..ed41183 100644 --- a/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs +++ b/src/DotNetOpenAuth/OAuth/ChannelElements/OAuthChannel.cs @@ -13,6 +13,7 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { using System.IO; using System.Linq; using System.Net; + using System.Net.Mime; using System.Text; using System.Web; using DotNetOpenAuth.Messaging; @@ -141,9 +142,12 @@ namespace DotNetOpenAuth.OAuth.ChannelElements { } // Scrape the entity - if (string.Equals(request.Headers[HttpRequestHeader.ContentType], HttpFormUrlEncoded, StringComparison.Ordinal)) { - foreach (string key in request.Form) { - fields.Add(key, request.Form[key]); + if (!string.IsNullOrEmpty(request.Headers[HttpRequestHeader.ContentType])) { + ContentType contentType = new ContentType(request.Headers[HttpRequestHeader.ContentType]); + if (string.Equals(contentType.MediaType, HttpFormUrlEncoded, StringComparison.Ordinal)) { + foreach (string key in request.Form) { + fields.Add(key, request.Form[key]); + } } } diff --git a/src/DotNetOpenAuth/OAuth/ConsumerBase.cs b/src/DotNetOpenAuth/OAuth/ConsumerBase.cs index 48f54d7..dddbe9e 100644 --- a/src/DotNetOpenAuth/OAuth/ConsumerBase.cs +++ b/src/DotNetOpenAuth/OAuth/ConsumerBase.cs @@ -224,7 +224,7 @@ namespace DotNetOpenAuth.OAuth { // Fine-tune our understanding of the SP's supported OAuth version if it's wrong. if (this.ServiceProvider.Version != requestTokenResponse.Version) { - Logger.OAuth.WarnFormat("Expected OAuth service provider at endpoint {0} to use OAuth {1} but {2} was detected. Adjusting service description to new version.", this.ServiceProvider.RequestTokenEndpoint, this.ServiceProvider.Version, requestTokenResponse.Version); + Logger.OAuth.WarnFormat("Expected OAuth service provider at endpoint {0} to use OAuth {1} but {2} was detected. Adjusting service description to new version.", this.ServiceProvider.RequestTokenEndpoint.Location, this.ServiceProvider.Version, requestTokenResponse.Version); this.ServiceProvider.ProtocolVersion = Protocol.Lookup(requestTokenResponse.Version).ProtocolVersion; } diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs index 358db9b..2dc9c69 100644 --- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs +++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeRequest.cs @@ -15,6 +15,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// the Attribute Exchange extension. /// </summary> [Serializable] + [DebuggerDisplay("{TypeUri} (required: {IsRequired}) ({Count})")] public class AttributeRequest { /// <summary> /// Backing field for the <see cref="Count"/> property. diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs index 6466cda..b2fc1fe 100644 --- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs +++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/AttributeValues.cs @@ -7,6 +7,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Diagnostics.Contracts; using DotNetOpenAuth.Messaging; @@ -16,6 +17,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// a fetch request, or by a relying party as part of a store request. /// </summary> [Serializable] + [DebuggerDisplay("{TypeUri}")] public class AttributeValues { /// <summary> /// Initializes a new instance of the <see cref="AttributeValues"/> class. diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs index a69e226..124a18c 100644 --- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs +++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchRequest.cs @@ -8,6 +8,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { using System; using System.Collections.Generic; using System.Collections.ObjectModel; + using System.Diagnostics.Contracts; using System.Globalization; using System.Linq; using DotNetOpenAuth.Messaging; @@ -67,7 +68,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// <value>A collection where the keys are the attribute type URIs, and the value /// is all the attribute request details.</value> public KeyedCollection<string, AttributeRequest> Attributes { - get { return this.attributes; } + get { + Contract.Ensures(Contract.Result<KeyedCollection<string, AttributeRequest>>() != null); + return this.attributes; + } } /// <summary> diff --git a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs index 758b20c..14b1caa 100644 --- a/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs +++ b/src/DotNetOpenAuth/OpenId/Extensions/AttributeExchange/FetchResponse.cs @@ -7,6 +7,7 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { using System; using System.Collections.ObjectModel; + using System.Diagnostics.Contracts; using System.Linq; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OpenId.Messages; @@ -52,7 +53,10 @@ namespace DotNetOpenAuth.OpenId.Extensions.AttributeExchange { /// Gets a sequence of the attributes whose values are provided by the OpenID Provider. /// </summary> public KeyedCollection<string, AttributeValues> Attributes { - get { return this.attributesProvided; } + get { + Contract.Ensures(Contract.Result<KeyedCollection<string, AttributeValues>>() != null); + return this.attributesProvided; + } } /// <summary> diff --git a/src/DotNetOpenAuth/OpenId/Identifier.cs b/src/DotNetOpenAuth/OpenId/Identifier.cs index 548a673..2ab5360 100644 --- a/src/DotNetOpenAuth/OpenId/Identifier.cs +++ b/src/DotNetOpenAuth/OpenId/Identifier.cs @@ -68,6 +68,8 @@ namespace DotNetOpenAuth.OpenId { [DebuggerStepThrough] public static implicit operator Identifier(string identifier) { Contract.Requires<ArgumentException>(identifier == null || identifier.Length > 0); + Contract.Ensures((identifier == null) == (Contract.Result<Identifier>() == null)); + if (identifier == null) { return null; } @@ -82,6 +84,7 @@ namespace DotNetOpenAuth.OpenId { [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "We have a Parse function.")] [DebuggerStepThrough] public static implicit operator Identifier(Uri identifier) { + Contract.Ensures((identifier == null) == (Contract.Result<Identifier>() == null)); if (identifier == null) { return null; } @@ -97,7 +100,7 @@ namespace DotNetOpenAuth.OpenId { [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "We have a Parse function.")] [DebuggerStepThrough] public static implicit operator string(Identifier identifier) { - Contract.Ensures((identifier == null && Contract.Result<string>() == null) || (identifier != null && Contract.Result<string>() != null)); + Contract.Ensures((identifier == null) == (Contract.Result<string>() == null)); if (identifier == null) { return null; } @@ -113,6 +116,8 @@ namespace DotNetOpenAuth.OpenId { [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Some of these identifiers are not properly formatted to be Uris at this stage.")] public static Identifier Parse(string identifier) { Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(identifier)); + Contract.Ensures(Contract.Result<Identifier>() != null); + if (XriIdentifier.IsValidXri(identifier)) { return new XriIdentifier(identifier); } else { diff --git a/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs b/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs index f778b76..445978e 100644 --- a/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs +++ b/src/DotNetOpenAuth/OpenId/Provider/ProviderEndpoint.cs @@ -43,7 +43,12 @@ namespace DotNetOpenAuth.OpenId.Provider { /// <summary> /// Backing field for the <see cref="Provider"/> property. /// </summary> - private static OpenIdProvider provider = CreateProvider(); + private static OpenIdProvider provider; + + /// <summary> + /// The lock that must be obtained when initializing the provider field. + /// </summary> + private static object providerInitializerLock = new object(); /// <summary> /// Fired when an incoming OpenID request is an authentication challenge @@ -64,6 +69,15 @@ namespace DotNetOpenAuth.OpenId.Provider { /// <value>The default value is an <see cref="OpenIdProvider"/> instance initialized according to the web.config file.</value> public static OpenIdProvider Provider { get { + Contract.Ensures(Contract.Result<OpenIdProvider>() != null); + if (provider == null) { + lock (providerInitializerLock) { + if (provider == null) { + provider = CreateProvider(); + } + } + } + return provider; } @@ -83,8 +97,14 @@ namespace DotNetOpenAuth.OpenId.Provider { /// before responding to the relying party's authentication request. /// </remarks> public static IAuthenticationRequest PendingAuthenticationRequest { - get { return HttpContext.Current.Session[PendingRequestKey] as IAuthenticationRequest; } - set { HttpContext.Current.Session[PendingRequestKey] = value; } + get { + Contract.Ensures(Contract.Result<IAuthenticationRequest>() == null || PendingRequest != null); + return HttpContext.Current.Session[PendingRequestKey] as IAuthenticationRequest; + } + + set { + HttpContext.Current.Session[PendingRequestKey] = value; + } } /// <summary> @@ -97,8 +117,14 @@ namespace DotNetOpenAuth.OpenId.Provider { /// before responding to the relying party's request. /// </remarks> public static IAnonymousRequest PendingAnonymousRequest { - get { return HttpContext.Current.Session[PendingRequestKey] as IAnonymousRequest; } - set { HttpContext.Current.Session[PendingRequestKey] = value; } + get { + Contract.Ensures(Contract.Result<IAnonymousRequest>() == null || PendingRequest != null); + return HttpContext.Current.Session[PendingRequestKey] as IAnonymousRequest; + } + + set { + HttpContext.Current.Session[PendingRequestKey] = value; + } } /// <summary> @@ -159,7 +185,7 @@ namespace DotNetOpenAuth.OpenId.Provider { // Then try the configuration file specified one. Finally, use the default // in-memory one that's built into OpenIdProvider. // determine what incoming message was received - IRequest request = provider.GetRequest(); + IRequest request = Provider.GetRequest(); if (request != null) { PendingRequest = null; @@ -179,7 +205,7 @@ namespace DotNetOpenAuth.OpenId.Provider { } } if (request.IsResponseReady) { - provider.SendResponse(request); + Provider.SendResponse(request); Page.Response.End(); PendingAuthenticationRequest = null; } @@ -218,6 +244,7 @@ namespace DotNetOpenAuth.OpenId.Provider { /// </summary> /// <returns>The new instance of OpenIdProvider.</returns> private static OpenIdProvider CreateProvider() { + Contract.Ensures(Contract.Result<OpenIdProvider>() != null); return new OpenIdProvider(DotNetOpenAuthSection.Configuration.OpenId.Provider.ApplicationStore.CreateInstance(OpenIdProvider.HttpApplicationStore)); } } diff --git a/src/DotNetOpenAuth/OpenId/ProviderEndpointDescription.cs b/src/DotNetOpenAuth/OpenId/ProviderEndpointDescription.cs index bb4a9ba..6514ffd 100644 --- a/src/DotNetOpenAuth/OpenId/ProviderEndpointDescription.cs +++ b/src/DotNetOpenAuth/OpenId/ProviderEndpointDescription.cs @@ -21,6 +21,7 @@ namespace DotNetOpenAuth.OpenId { /// <remarks> /// This is an immutable type. /// </remarks> + [Serializable] internal sealed class ProviderEndpointDescription : IProviderEndpoint { /// <summary> /// Initializes a new instance of the <see cref="ProviderEndpointDescription"/> class. diff --git a/src/DotNetOpenAuth/OpenId/Realm.cs b/src/DotNetOpenAuth/OpenId/Realm.cs index 818718a..4137c72 100644 --- a/src/DotNetOpenAuth/OpenId/Realm.cs +++ b/src/DotNetOpenAuth/OpenId/Realm.cs @@ -112,6 +112,8 @@ namespace DotNetOpenAuth.OpenId { public static Realm AutoDetect { get { Contract.Requires<InvalidOperationException>(HttpContext.Current != null && HttpContext.Current.Request != null, MessagingStrings.HttpContextRequired); + Contract.Ensures(Contract.Result<Realm>() != null); + HttpRequestInfo requestInfo = new HttpRequestInfo(HttpContext.Current.Request); UriBuilder realmUrl = new UriBuilder(requestInfo.UrlBeforeRewriting); realmUrl.Path = HttpContext.Current.Request.ApplicationPath; @@ -252,6 +254,7 @@ namespace DotNetOpenAuth.OpenId { [SuppressMessage("Microsoft.Usage", "CA2234:PassSystemUriObjectsInsteadOfStrings", Justification = "Not all Realms are valid URLs.")] [DebuggerStepThrough] public static implicit operator Realm(string uri) { + Contract.Ensures((Contract.Result<Realm>() != null) == (uri != null)); return uri != null ? new Realm(uri) : null; } @@ -262,6 +265,7 @@ namespace DotNetOpenAuth.OpenId { /// <returns>The result of the conversion.</returns> [DebuggerStepThrough] public static implicit operator Realm(Uri uri) { + Contract.Ensures((Contract.Result<Realm>() != null) == (uri != null)); return uri != null ? new Realm(uri) : null; } @@ -272,6 +276,7 @@ namespace DotNetOpenAuth.OpenId { /// <returns>The result of the conversion.</returns> [DebuggerStepThrough] public static implicit operator string(Realm realm) { + Contract.Ensures((Contract.Result<string>() != null) == (realm != null)); return realm != null ? realm.ToString() : null; } diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs index f89ec0a..c13c61c 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdLogin.cs @@ -643,11 +643,13 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { set { base.UsePersistentCookie = value; - // use conditional here to prevent infinite recursion - // with CheckedChanged event. - bool rememberMe = value != LogOnPersistence.Session; - if (this.rememberMeCheckBox.Checked != rememberMe) { - this.rememberMeCheckBox.Checked = rememberMe; + if (this.rememberMeCheckBox != null) { + // use conditional here to prevent infinite recursion + // with CheckedChanged event. + bool rememberMe = value != LogOnPersistence.Session; + if (this.rememberMeCheckBox.Checked != rememberMe) { + this.rememberMeCheckBox.Checked = rememberMe; + } } } } @@ -782,7 +784,7 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { cell = new TableCell(); this.rememberMeCheckBox = new CheckBox(); this.rememberMeCheckBox.Text = RememberMeTextDefault; - this.rememberMeCheckBox.Checked = RememberMeDefault; + this.rememberMeCheckBox.Checked = this.UsePersistentCookie != LogOnPersistence.Session; this.rememberMeCheckBox.Visible = RememberMeVisibleDefault; this.rememberMeCheckBox.CheckedChanged += this.RememberMeCheckBox_CheckedChanged; cell.Controls.Add(this.rememberMeCheckBox); diff --git a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs index c9106de..a0a0fb9 100644 --- a/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs +++ b/src/DotNetOpenAuth/OpenId/RelyingParty/OpenIdRelyingParty.cs @@ -109,7 +109,10 @@ namespace DotNetOpenAuth.OpenId.RelyingParty { // replay attacks. But only 2.0+ Providers can be expected to provide // replay protection. if (nonceStore == null) { - this.SecuritySettings.MinimumRequiredOpenIdVersion = ProtocolVersion.V20; + if (this.SecuritySettings.MinimumRequiredOpenIdVersion < ProtocolVersion.V20) { + Logger.OpenId.Warn("Raising minimum OpenID version requirement for Providers to 2.0 to protect this stateless RP from replay attacks."); + this.SecuritySettings.MinimumRequiredOpenIdVersion = ProtocolVersion.V20; + } } this.channel = new OpenIdChannel(associationStore, nonceStore, this.SecuritySettings); diff --git a/src/DotNetOpenAuth/Reporting.cs b/src/DotNetOpenAuth/Reporting.cs index 2235986..c4421c4 100644 --- a/src/DotNetOpenAuth/Reporting.cs +++ b/src/DotNetOpenAuth/Reporting.cs @@ -30,7 +30,27 @@ namespace DotNetOpenAuth { /// The statistical reporting mechanism used so this library's project authors /// know what versions and features are in use. /// </summary> - internal static class Reporting { + public static class Reporting { + /// <summary> + /// A value indicating whether reporting is desirable or not. Must be logical-AND'd with !<see cref="broken"/>. + /// </summary> + private static bool enabled; + + /// <summary> + /// A value indicating whether reporting experienced an error and cannot be enabled. + /// </summary> + private static bool broken; + + /// <summary> + /// A value indicating whether the reporting class has been initialized or not. + /// </summary> + private static bool initialized; + + /// <summary> + /// The object to lock during initialization. + /// </summary> + private static object initializationSync = new object(); + /// <summary> /// The isolated storage to use for collecting data in between published reports. /// </summary> @@ -93,37 +113,31 @@ namespace DotNetOpenAuth { [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Reporting MUST NOT cause unhandled exceptions.")] static Reporting() { Enabled = DotNetOpenAuthSection.Configuration.Reporting.Enabled; - if (Enabled) { - try { - file = GetIsolatedStorage(); - reportOriginIdentity = GetOrCreateOriginIdentity(); - - webRequestHandler = new StandardWebRequestHandler(); - observations.Add(observedRequests = new PersistentHashSet(file, "requests.txt", 3)); - observations.Add(observedCultures = new PersistentHashSet(file, "cultures.txt", 20)); - observations.Add(observedFeatures = new PersistentHashSet(file, "features.txt", int.MaxValue)); - - // Record site-wide features in use. - if (HttpContext.Current != null && HttpContext.Current.ApplicationInstance != null) { - // MVC or web forms? - // front-end or back end web farm? - // url rewriting? - ////RecordFeatureUse(IsMVC ? "ASP.NET MVC" : "ASP.NET Web Forms"); - } - } catch (Exception e) { - // This is supposed to be as low-risk as possible, so if it fails, just disable reporting - // and avoid rethrowing. - Enabled = false; - Logger.Library.Error("Error while trying to initialize reporting.", e); - } - } } /// <summary> /// Gets or sets a value indicating whether this reporting is enabled. /// </summary> /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value> - internal static bool Enabled { get; set; } + /// <remarks> + /// Setting this property to <c>true</c> <i>may</i> have no effect + /// if reporting has already experienced a failure of some kind. + /// </remarks> + public static bool Enabled { + get { + return enabled && !broken; + } + + set { + if (value) { + Initialize(); + } + + // Only set the static field here, so that other threads + // don't try to use reporting while we're initializing it. + enabled = value; + } + } /// <summary> /// Gets the configuration to use for reporting. @@ -302,6 +316,40 @@ namespace DotNetOpenAuth { } /// <summary> + /// Initializes Reporting if it has not been initialized yet. + /// </summary> + private static void Initialize() { + lock (initializationSync) { + if (!broken && !initialized) { + try { + file = GetIsolatedStorage(); + reportOriginIdentity = GetOrCreateOriginIdentity(); + + webRequestHandler = new StandardWebRequestHandler(); + observations.Add(observedRequests = new PersistentHashSet(file, "requests.txt", 3)); + observations.Add(observedCultures = new PersistentHashSet(file, "cultures.txt", 20)); + observations.Add(observedFeatures = new PersistentHashSet(file, "features.txt", int.MaxValue)); + + // Record site-wide features in use. + if (HttpContext.Current != null && HttpContext.Current.ApplicationInstance != null) { + // MVC or web forms? + // front-end or back end web farm? + // url rewriting? + ////RecordFeatureUse(IsMVC ? "ASP.NET MVC" : "ASP.NET Web Forms"); + } + + initialized = true; + } catch (Exception e) { + // This is supposed to be as low-risk as possible, so if it fails, just disable reporting + // and avoid rethrowing. + broken = true; + Logger.Library.Error("Error while trying to initialize reporting.", e); + } + } + } + } + + /// <summary> /// Assembles a report for submission. /// </summary> /// <returns>A stream that contains the report.</returns> @@ -459,7 +507,7 @@ namespace DotNetOpenAuth { } catch (Exception ex) { // Something bad and unexpected happened. Just deactivate to avoid more trouble. Logger.Library.Error("Error while trying to submit statistical report.", ex); - Enabled = false; + broken = true; } }); } diff --git a/tools/Documentation.targets b/tools/Documentation.targets index dff4d88..faf1f75 100644 --- a/tools/Documentation.targets +++ b/tools/Documentation.targets @@ -5,7 +5,6 @@ <ProjectRoot Condition="'$(ProjectRoot)' == ''">$(MSBuildProjectDirectory)\..\..\</ProjectRoot> <OutputAssembly>DotNetOpenAuth</OutputAssembly> <DocOutputPath>$(ProjectRoot)doc\</DocOutputPath> - <IntermediatePath>$(ProjectRoot)obj\$(Configuration)\</IntermediatePath> <DocumentationFile>$(OutputPath)$(OutputAssembly).xml</DocumentationFile> </PropertyGroup> diff --git a/tools/DotNetOpenAuth.automated.props b/tools/DotNetOpenAuth.automated.props new file mode 100644 index 0000000..f66c1fe --- /dev/null +++ b/tools/DotNetOpenAuth.automated.props @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> + <Import Project="DotNetOpenAuth.props"/> + + <PropertyGroup> + <AutomatedBuild>true</AutomatedBuild> + <SolutionPath>$(ProjectRoot)src\$(ProductName).sln</SolutionPath> + <BuildInParallel Condition=" '$(BuildInParallel)' == '' ">true</BuildInParallel> + <!-- Validation controls whether extra builds are done in order to fully validate what we're distributing, + even if we're not distributing the built bits (as is the case for project templates). --> + <Validation Condition=" '$(Validation)' == '' ">Full</Validation> + </PropertyGroup> +</Project> diff --git a/tools/DotNetOpenAuth.automated.targets b/tools/DotNetOpenAuth.automated.targets new file mode 100644 index 0000000..5333b34 --- /dev/null +++ b/tools/DotNetOpenAuth.automated.targets @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" InitialTargets="_SetDropProperties"> + <Import Project="$(ProjectRoot)tools\$(ProductName).targets"/> + <UsingTask AssemblyFile="$(ProjectRoot)lib\MSBuild.Community.Tasks.dll" TaskName="Zip"/> + <UsingTask AssemblyFile="$(ProjectRoot)lib\MSBuild.Community.Tasks.dll" TaskName="NUnit" /> + + <Target Name="Rebuild" DependsOnTargets="Clean;Build"/> + + <Target Name="Clean"> + <ItemGroup> + <ProjectsToClean> + <Targets Condition=" '%(ProjectsToClean.Targets)' == '' ">Clean</Targets> + </ProjectsToClean> + </ItemGroup> + + <Delete Files="@(FilesToClean)" /> + <RemoveDir Directories="@(DirectoriesToClean)" /> + <MSBuild Projects="@(ProjectsToClean)" Targets="%(ProjectsToClean.Targets)" BuildInParallel="$(BuildInParallel)" /> + </Target> + + <Target Name="_SetDropProperties" DependsOnTargets="GetBuildVersion"> + <!-- This target is necessary because PropertyGroups within the same Target as + where CallTarget is fired do NOT affect those called targets. --> + <!-- The rest of these are here so that other DependsOn targets have access to these properties. --> + <PropertyGroup> + <DropDirectoryNoSlash>$(DropsRoot)$(ProductName)-$(BuildVersion)</DropDirectoryNoSlash> + <DropDirectory>$(DropDirectoryNoSlash)\</DropDirectory> + </PropertyGroup> + </Target> + + <Target Name="SkipVerification" Condition="'$(IsElevated)' == 'true'"> + <SignatureVerification SkipVerification="true" AssemblyName="*" PublicKeyToken="$(PublicKeyToken)" /> + </Target> + + <Target Name="BuildProduct" DependsOnTargets="SkipVerification"> + <MSBuild BuildInParallel="$(BuildInParallel)" + Projects="$(ProjectRoot)src\$(ProductName)\$(ProductName).csproj" /> + </Target> + + <Target Name="BuildUnifiedProduct" DependsOnTargets="BuildProduct"> + <MSBuild BuildInParallel="$(BuildInParallel)" + Projects="$(ProjectRoot)src\$(ProductName)\$(ProductName).csproj" + Targets="BuildUnifiedProduct" /> + </Target> +</Project> diff --git a/tools/DotNetOpenAuth.props b/tools/DotNetOpenAuth.props index a3ad973..6815fca 100644 --- a/tools/DotNetOpenAuth.props +++ b/tools/DotNetOpenAuth.props @@ -4,13 +4,14 @@ <ProductName>DotNetOpenAuth</ProductName> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <TargetFrameworkVersion Condition=" '$(TargetFrameworkVersion)' == '' ">v3.5</TargetFrameworkVersion> - <ProjectRoot Condition="'$(ProjectRoot)' == ''">$(MSBuildProjectDirectory)\</ProjectRoot> - <DropsRoot>$(ProjectRoot)drops\$(Configuration)\</DropsRoot> + <ProjectRoot Condition="'$(ProjectRoot)' == ''">$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\'))</ProjectRoot> + <DropsRoot>$(ProjectRoot)drops\$(TargetFrameworkVersion)\$(Configuration)\</DropsRoot> <OutputPath>$(ProjectRoot)bin\$(TargetFrameworkVersion)\$(Configuration)\</OutputPath> <DocOutputPath>$(ProjectRoot)doc\</DocOutputPath> <IntermediatePath>$(ProjectRoot)obj\$(TargetFrameworkVersion)\$(Configuration)\</IntermediatePath> <BaseIntermediateOutputPath Condition=" '$(BaseIntermediateOutputPath)' == '' ">obj\$(TargetFrameworkVersion)\</BaseIntermediateOutputPath> <ToolsDir>$(ProjectRoot)tools\</ToolsDir> + <ZipLevel>6</ZipLevel> <ClrVersion Condition=" '$(TargetFrameworkVersion)' == 'v4.0' ">4</ClrVersion> <ClrVersion Condition=" '$(TargetFrameworkVersion)' != 'v4.0' ">2</ClrVersion> @@ -20,8 +21,18 @@ <KeyPairContainer Condition="'$(KeyPairContainer)' == ''">DotNetOpenAuth</KeyPairContainer> <PublicKeyToken>2780CCD10D57B246</PublicKeyToken> <DelaySign>true</DelaySign> + <SignedSubPath>signed\</SignedSubPath> + + <ILMergeOutputAssemblyDirectory>$(OutputPath)unified\</ILMergeOutputAssemblyDirectory> + <ILMergeOutputAssembly>$(ILMergeOutputAssemblyDirectory)$(ProductName).dll</ILMergeOutputAssembly> </PropertyGroup> + <ItemGroup> + <SignDependsOn Include="Build" /> + <ILMergeInputAssemblies Include="$(OutputPath)$(ProductName).dll; + $(ProjectRoot)lib\Microsoft.Contracts.dll; "/> + </ItemGroup> + <Import Project="$(ProjectRoot)lib\DotNetOpenAuth.BuildTasks.targets" /> <Target Name="InitializeProps"> diff --git a/tools/DotNetOpenAuth.targets b/tools/DotNetOpenAuth.targets index 9a2c6f9..cab4413 100644 --- a/tools/DotNetOpenAuth.targets +++ b/tools/DotNetOpenAuth.targets @@ -2,12 +2,27 @@ <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> <Import Project="DotNetOpenAuth.Versioning.targets" /> <Import Project="JavascriptPacker.targets" /> + <UsingTask AssemblyFile="$(ProjectRoot)lib\MSBuild.Community.Tasks.dll" TaskName="ILMerge"/> + + <!-- Prevent our own item types from appearing in Solution Explorer. --> + <ItemDefinitionGroup> + <SignDependsOn> + <Visible>false</Visible> + </SignDependsOn> + <DelaySignedAssemblies> + <Visible>false</Visible> + </DelaySignedAssemblies> + </ItemDefinitionGroup> <PropertyGroup> <DefineConstants Condition=" '$(SignAssembly)' == 'true' ">$(DefineConstants);StrongNameSigned</DefineConstants> <DefineConstants Condition=" '$(ClrVersion)' == '4' ">$(DefineConstants);CLR4</DefineConstants> </PropertyGroup> + <ItemGroup> + <DelaySignedAssemblies Include="$(TargetPath)" Condition=" '$(SuppressTargetPathDelaySignedAssembly)' != 'true' "/> + </ItemGroup> + <ItemGroup Condition=" '$(ClrVersion)' != '4' "> <Reference Include="Microsoft.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=736440c9b414ea16, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> @@ -48,4 +63,58 @@ <Output TaskParameter="AccessorAssembly" ItemName="ReferencePath" /> </Publicize> </Target> + + <Target Name="Sign" DependsOnTargets="@(SignDependsOn)" Outputs="@(SignedDependencies);@(SignedAssemblyTargets)" Condition=" '@(DelaySignedAssemblies)' != '' "> + <!-- Make sure that all dependencies are also signed. --> + <MSBuild Projects="@(ProjectReference)" Targets="Sign" BuildInParallel="$(BuildInParallel)"> + <Output TaskParameter="TargetOutputs" ItemName="SignedDependencies"/> + </MSBuild> + + <!-- Add the resource assemblies. --> + <ItemGroup> + <!-- Make sure that we consider the TargetPath's satellites even if TargetPath itself was suppressed. --> + <DelaySignedAssembliesForSatellites Include="@(DelaySignedAssemblies)" /> + <DelaySignedAssembliesForSatellites Include="$(TargetPath)" Condition=" '$(SuppressTargetPathDelaySignedAssembly)' == 'true' "/> + </ItemGroup> + <PropertyGroup> + <DelaySignedSatelliteAssembliesPattern>@(DelaySignedAssembliesForSatellites->'%(RootDir)%(Directory)*\%(FileName).resources.*')</DelaySignedSatelliteAssembliesPattern> + </PropertyGroup> + <ItemGroup> + <DelaySignedSatelliteAssemblies Include="$(DelaySignedSatelliteAssembliesPattern)" /> + <DelaySignedSatelliteAssemblies> + <CultureDir>$([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName('%(Directory)'))))\</CultureDir> + </DelaySignedSatelliteAssemblies> + </ItemGroup> + + <!-- Don't sign assemblies in place. Lots of reasons for this, not the least of which is that + subsequent builds of web site projects will cause the satellite assemblies to be regenerated (bizarre) + and erase the signature. --> + <ItemGroup> + <AssembliesToSign Include="@(DelaySignedAssemblies);@(DelaySignedSatelliteAssemblies)" /> + <SignedAssemblyTargets Include="@(AssembliesToSign->'%(RootDir)%(Directory)$(SignedSubPath)%(FileName)%(Extension)')"> + <UnsignedAssemblyPath>%(AssembliesToSign.Identity)</UnsignedAssemblyPath> + <SymbolPath Condition="Exists('%(RootDir)%(Directory)%(FileName).pdb')">%(RootDir)%(Directory)%(FileName).pdb</SymbolPath> + </SignedAssemblyTargets> + </ItemGroup> + + <Message Text="Signing delay-signed assemblies using key pair container $(KeyPairContainer)." /> + <Copy SourceFiles="@(AssembliesToSign)" DestinationFiles="@(SignedAssemblyTargets)" /> + <ReSignDelaySignedAssemblies + KeyContainer="$(KeyPairContainer)" + Assemblies="@(SignedAssemblyTargets)" + Condition="Exists(%(Identity))" /> + </Target> + + <Target Name="ResignDelaySignedAssemblies" Outputs="@(ResignedAssembliesOutputs)"> + <ItemGroup> + <DelaySignedProjects Include=" + $(ProjectRoot)src\dotnetopenauth\dotnetopenauth.csproj; + $(ProjectRoot)src\dotnetopenauth.test\dotnetopenauth.test.csproj; + $(ProjectRoot)samples\openidofflineprovider\openidofflineprovider.csproj; + " /> + </ItemGroup> + <MSBuild Projects="@(DelaySignedProjects)" Targets="Sign" BuildInParallel="$(BuildInParallel)"> + <Output TaskParameter="TargetOutputs" ItemName="ResignedAssembliesOutputs"/> + </MSBuild> + </Target> </Project> diff --git a/tools/drop.proj b/tools/drop.proj new file mode 100644 index 0000000..02fdd20 --- /dev/null +++ b/tools/drop.proj @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildProjectDirectory)\DotNetOpenAuth.automated.props"/> + + <Target Name="Layout" DependsOnTargets="BuildUnifiedProduct;ReSignDelaySignedAssemblies"> + <!-- Note that we use an MSBuild task for these dependencies rather than individual DependsOnTargets entries + so that these builds can be executed in parallel. --> + <MSBuild BuildInParallel="$(BuildInParallel)" + Projects=" + $(ProjectRoot)samples\samples.proj; + $(ProjectRoot)vsi\vsi.proj; + $(ProjectRoot)vsix\vsix.proj; + $(ProjectRoot)doc\doc.proj; + "> + <Output TaskParameter="TargetOutputs" ItemName="DropLayoutDependencies"/> + </MSBuild> + <PropertyGroup> + <DropBinDirectory>$(DropDirectory)Bin\</DropBinDirectory> + <DropLibDirectory>$(DropDirectory)Lib\</DropLibDirectory> + <DropProjectTemplatesDirectory>$(DropDirectory)Project Templates\</DropProjectTemplatesDirectory> + <DropSamplesDirectory>$(DropDirectory)Samples\</DropSamplesDirectory> + <DropSpecsDirectory>$(DropDirectory)Specs\</DropSpecsDirectory> + </PropertyGroup> + <ItemGroup> + <ExtensionVsix Include="@(DropLayoutDependencies)" Condition=" '%(DropLayoutDependencies.MSBuildSourceProjectFile)' == '$(ProjectRoot)vsix\vsix.proj' " /> + <ProjectTemplatesVsi Include="@(DropLayoutDependencies)" Condition=" '%(DropLayoutDependencies.MSBuildSourceProjectFile)' == '$(ProjectRoot)vsi\vsi.proj' " /> + <DropDirectories Include=" + $(DropDirectory); + $(DropBinDirectory); + $(DropLibDirectory); + $(DropProjectTemplatesDirectory); + $(DropSamplesDirectory); + $(DropSpecsDirectory); + " /> + + <DropSourceFiles Include=" + $(ProjectRoot)Doc\$(ProductName).chm; + $(ProjectRoot)Doc\*.htm*; + $(ProjectRoot)LICENSE.txt; + $(ProjectRoot)CONTRIB.txt; + " + Exclude="$(ProjectRoot)Doc\README.*.html;" /> + <DropBinSourceFiles Include=" + $(ILMergeOutputAssemblyDirectory)$(SignedSubPath)$(ProductName).???; + $(OutputPath)$(ProductName).xml; + $(OutputPath)$(SignedSubPath)$(ProductName).Contracts.???; + $(ProjectRoot)Doc\README.Bin.html; + $(ProjectRoot)src\$(ProductName)\Configuration\$(ProductName).xsd; + " /> + <DropSatelliteSourceFiles Include="$(OutputPath)**\$(SignedSubPath)$(ProductName).resources.dll" /> + <DropSatelliteSourceFiles> + <CultureDir>$([System.IO.Path]::GetDirectoryName('$([System.IO.Path]::GetDirectoryName('%(RecursiveDir)'))'))\</CultureDir> + </DropSatelliteSourceFiles> + <DropLibSourceFiles Include=" + $(ProjectRoot)Lib\log4net.*; + " /> + <DropProjectTemplatesSourceFiles Include="@(ProjectTemplatesVsi)" /> + <DropVsixSourceFiles Include="@(ExtensionVsix)" Condition=" '%(ExtensionVsix.IncludeInDrop)' == 'true' " /> + <DropSamplesSourceFiles Include="$(ProjectRoot)Samples\**" Exclude=" + $(ProjectRoot)**\obj\**; + $(ProjectRoot)**\*.sln.cache; + $(ProjectRoot)**\*.suo; + $(ProjectRoot)**\*.user; + $(ProjectRoot)**\*.gitignore; + $(ProjectRoot)**\*.ldf; + $(ProjectRoot)**\*.log*; + $(ProjectRoot)**\*~; + $(ProjectRoot)**\Debug\**; + $(ProjectRoot)**\Settings.StyleCop; + $(ProjectRoot)**\StyleCop.Cache; + $(ProjectRoot)Samples\**\DotNetOpenAuth.???; + $(ProjectRoot)Samples\**\DotNetOpenAuth.resources.???; + $(ProjectRoot)Samples\**\log4net.???; + $(ProjectRoot)Samples\**\PresentationCore.dll; + $(ProjectRoot)Samples\**\System.Printing.dll; + $(ProjectRoot)Samples\**\*.refresh_; + $(ProjectRoot)Samples\*.proj; + " /> + <!-- Some .refresh files are only applicable to drop builds, so we rename them from *.refresh_ --> + <DropSamplesRefreshSourceFiles Include="$(ProjectRoot)Samples\**\*.refresh_" /> + <DropSpecsSourceFiles Include="$(ProjectRoot)Doc\specs\*.htm*" /> + + <DropFiles Include="@(DropSourceFiles->'$(DropDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> + <DropBinFiles Include="@(DropBinSourceFiles->'$(DropBinDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> + <DropSatelliteFiles Include="@(DropSatelliteSourceFiles->'$(DropBinDirectory)%(CultureDir)%(FileName)%(Extension)')" /> + <DropLibFiles Include="@(DropLibSourceFiles->'$(DropLibDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> + <DropProjectTemplatesFiles Include="@(DropProjectTemplatesSourceFiles->'$(DropProjectTemplatesDirectory)%(FileName)%(Extension)')" /> + <DropVsixFiles Include="@(DropVsixSourceFiles->'$(DropProjectTemplatesDirectory)%(FileName)%(Extension)')" /> + <DropSamplesFiles Include="@(DropSamplesSourceFiles->'$(DropSamplesDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> + <DropSamplesRefreshFiles Include="@(DropSamplesRefreshSourceFiles->'$(DropSamplesDirectory)%(RecursiveDir)%(FileName).refresh')"/> + <DropSamplesToolsProjects Include="$(DropSamplesDirectory)OpenIdOfflineProvider\OpenIdOfflineProvider.csproj" /> + <DropSpecsFiles Include="@(DropSpecsSourceFiles->'$(DropSpecsDirectory)%(RecursiveDir)%(FileName)%(Extension)')"/> + + <AllDropSources Include=" + @(DropSourceFiles); + @(DropBinSourceFiles); + @(DropSatelliteSourceFiles); + @(DropLibSourceFiles); + @(DropProjectTemplatesSourceFiles); + @(DropVsixSourceFiles); + @(DropSamplesSourceFiles); + @(DropSamplesRefreshSourceFiles); + @(DropDocSourceFiles); + @(DropSpecsSourceFiles); + " /> + + <AllDropTargets Include=" + @(DropFiles); + @(DropBinFiles); + @(DropSatelliteFiles); + @(DropLibFiles); + @(DropProjectTemplatesFiles); + @(DropVsixFiles); + @(DropSamplesFiles); + @(DropSamplesRefreshFiles); + @(DropDocFiles); + @(DropSpecsFiles) + " /> + </ItemGroup> + + <!-- clean up any previous drop with the same name so we don't aggregate files. --> + <MakeDir Directories="@(DropDirectories)" /> + <Copy SourceFiles="@(AllDropSources)" DestinationFiles="@(AllDropTargets)" SkipUnchangedFiles="true" /> + <Purge Directories="$(DropDirectory)" IntendedFiles="@(AllDropTargets)" /> + <!-- fix up the samples so that they will compile right out of the drop --> + <ItemGroup> + <SampleProjectTargets Include="$(DropSamplesDirectory)**\*.*proj" /> + <SampleSolutionTargets Include="$(DropSamplesDirectory)**\*.sln" /> + </ItemGroup> + <FixupShippingToolSamples Projects="@(DropSamplesToolsProjects)" + RemoveImportsStartingWith="%24(ProjectRoot)tools\" + AddReferences="Microsoft.Contracts"/> + <ChangeProjectReferenceToAssemblyReference Projects="@(SampleProjectTargets)" + ProjectReferences="..\..\src\$(ProductName)\$(ProductName).csproj" References="..\..\Bin\$(ProductName).dll" /> + <DowngradeProjects Projects="@(SampleProjectTargets);@(SampleSolutionTargets)" DowngradeMvc2ToMvc1="true" /> + </Target> + + <Target Name="Build" DependsOnTargets="Layout"> + <PropertyGroup> + <DropZip>$(DropDirectoryNoSlash).zip</DropZip> + </PropertyGroup> + <Zip Files="@(AllDropTargets)" ZipFileName="$(DropZip)" WorkingDirectory="$(DropsRoot)" ZipLevel="$(ZipLevel)" /> + </Target> + + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.automated.targets"/> +</Project>
\ No newline at end of file diff --git a/vsi/vsi.proj b/vsi/vsi.proj new file mode 100644 index 0000000..be0c73b --- /dev/null +++ b/vsi/vsi.proj @@ -0,0 +1,52 @@ +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildProjectDirectory)\..\tools\DotNetOpenAuth.automated.props"/> + <Import Project="..\projecttemplates\ProjectTemplates.props"/> + + <PropertyGroup> + <ProjectTemplatesVsiDirectory>$(IntermediatePath)vsi\</ProjectTemplatesVsiDirectory> + </PropertyGroup> + + <ItemGroup> + <DirectoriesToClean Include="$(ProjectTemplatesLayoutPath)" /> + <ProjectTemplates Include="$(ProjectRoot)projecttemplates\**\*.*proj" /> + </ItemGroup> + + <Target Name="Build" Returns="$(ProjectTemplatesVsi)"> + <MSBuild Projects="..\projecttemplates\projecttemplates.proj" Targets="Zip2008" BuildInParallel="$(BuildInParallel)"> + <Output TaskParameter="TargetOutputs" ItemName="ProjectTemplate2008ZipSource"/> + </MSBuild> + + <PropertyGroup> + <ProjectTemplatesVsi>$(DropDirectoryNoSlash).vsi</ProjectTemplatesVsi> + </PropertyGroup> + <ItemGroup> + <VsiTransformSource Include="*.vscontent"> + <BeforeTokens>$version$</BeforeTokens> + <AfterTokens>$(BuildVersion)</AfterTokens> + <SkipUnchangedFiles>false</SkipUnchangedFiles> + </VsiTransformSource> + <VsiTransformLayout Include="@(VsiTransformSource->'$(ProjectTemplatesVsiDirectory)%(RecursiveDir)%(FileName)%(Extension)')" /> + + <ProjectTemplate2008ZipSource> + <HardLink>true</HardLink> + </ProjectTemplate2008ZipSource> + <ProjectTemplate2008ZipTargets Include="@(ProjectTemplate2008ZipSource->'$(ProjectTemplatesVsiDirectory)%(FileName)%(Extension)')" /> + <ProjectTemplateVsiContents Include=" + @(VsiTransformLayout); + @(ProjectTemplate2008ZipTargets); + " /> + </ItemGroup> + + <CopyWithTokenSubstitution SourceFiles="@(VsiTransformSource)" DestinationFiles="@(VsiTransformLayout)" /> + <HardLinkCopy SourceFiles="@(ProjectTemplate2008ZipSource)" DestinationFiles="@(ProjectTemplate2008ZipTargets)" /> + + <Zip + Files="@(ProjectTemplateVsiContents)" + ZipFileName="$(ProjectTemplatesVsi)" + WorkingDirectory="$(ProjectTemplatesVsiDirectory)" + ZipLevel="$(ZipLevel)" + /> + </Target> + + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.automated.targets"/> +</Project>
\ No newline at end of file diff --git a/vsix/DotNetOpenAuthSDK.pkgdef b/vsix/DotNetOpenAuthSDK.pkgdef deleted file mode 100644 index 1a515e1..0000000 --- a/vsix/DotNetOpenAuthSDK.pkgdef +++ /dev/null @@ -1,5 +0,0 @@ -[$RootKey$\Packages\{d2122791-8de4-4d3b-a414-7563c9a8cd6e}] -@="Hey there" - -;[HKEY_CURRENT_USER\Software\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx\DotNetOpenAuth SDK] -;@="$PackageFolder$"
\ No newline at end of file diff --git a/vsix/extension.vsixmanifest b/vsix/extension.vsixmanifest index 4bb59dc..20c2472 100644 --- a/vsix/extension.vsixmanifest +++ b/vsix/extension.vsixmanifest @@ -23,6 +23,6 @@ <References /> <Content> <ProjectTemplate>PT</ProjectTemplate> - <VsPackage>DotNetOpenAuthSDK.pkgdef</VsPackage> + <!--<VsPackage>DotNetOpenAuthSDK.pkgdef</VsPackage>--> </Content> </Vsix> diff --git a/vsix/vsix.proj b/vsix/vsix.proj new file mode 100644 index 0000000..dcd0e85 --- /dev/null +++ b/vsix/vsix.proj @@ -0,0 +1,131 @@ +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildProjectDirectory)\..\tools\DotNetOpenAuth.automated.props"/> + <Import Project="..\projecttemplates\ProjectTemplates.props"/> + + <PropertyGroup> + <ExtensionVsixLayoutDirectory>$(IntermediatePath)vsix\</ExtensionVsixLayoutDirectory> + <ProjectTemplateSubdirectory>$(ExtensionVsixLayoutDirectory)PT\CSharp\Web\</ProjectTemplateSubdirectory> + </PropertyGroup> + + <Target Name="Layout"> + <MSBuild Projects="..\projecttemplates\projecttemplates.proj" Targets="Zip" BuildInParallel="$(BuildInParallel)"> + <Output TaskParameter="TargetOutputs" ItemName="ProjectTemplateZipSource"/> + </MSBuild> + + <ItemGroup> + <ProjectTemplateZipSource> + <HardLink>true</HardLink> + </ProjectTemplateZipSource> + <ProjectTemplateZipTargets Include="@(ProjectTemplateZipSource->'$(ProjectTemplateSubdirectory)%(FileName)%(Extension)')" /> + + <ExtensionVsixTransformSource Include=" + $(ProjectRoot)vsix\extension.vsixmanifest; + $(ProjectRoot)LICENSE.txt; + "> + <BeforeTokens>$version$</BeforeTokens> + <AfterTokens>$(BuildVersion)</AfterTokens> + <SkipUnchangedFiles>false</SkipUnchangedFiles> + </ExtensionVsixTransformSource> + <ExtensionVsixTransformLayout Include="@(ExtensionVsixTransformSource->'$(ExtensionVsixLayoutDirectory)%(RecursiveDir)%(FileName)%(Extension)')" /> + + <ExtensionVsixSources Include=" + $(ProjectRoot)vsix\*; + " Exclude=" + $(ProjectRoot)vsix\extension.vsixmanifest; + $(ProjectRoot)vsix\$(MSBuildThisFile); + "> + <SkipUnchangedFiles>true</SkipUnchangedFiles> + </ExtensionVsixSources> + <ExtensionVsixTargets Include="@(ExtensionVsixSources->'$(ExtensionVsixLayoutDirectory)%(FileName)%(Extension)')" /> + + <ExtensionVsixContents Include=" + @(ExtensionVsixTargets); + @(ExtensionVsixTransformLayout); + @(ProjectTemplateZipTargets); + "/> + </ItemGroup> + + <CopyWithTokenSubstitution SourceFiles="@(ExtensionVsixTransformSource)" DestinationFiles="@(ExtensionVsixTransformLayout)" /> + <Copy SourceFiles="@(ExtensionVsixSources)" DestinationFiles="@(ExtensionVsixTargets)" SkipUnchangedFiles="true" /> + <HardLinkCopy SourceFiles="@(ProjectTemplateZipSource)" DestinationFiles="@(ProjectTemplateZipTargets)" /> + <Purge Directories="$(ExtensionVsixLayoutDirectory)" IntendedFiles="@(ExtensionVsixContents)" /> + </Target> + + <Target Name="VSGalleryVsixLayout" DependsOnTargets="Layout"> + <!-- Build individual VSIX files for each project template for the Visual Studio Gallery, + which only allows one project template per VSIX. --> + <ItemGroup> + <VSGalleryVsixRawSources Include="$(ExtensionVsixLayoutDirectory)*" + Exclude="$(ExtensionVsixLayoutDirectory)*.vsixmanifest"> + <VSGalleryVsix>$(DropsRoot)$(ProductName) %(ProjectTemplateZipTargets.FileName)-$(BuildVersion).vsix</VSGalleryVsix> + <TopLevelTemplate>%(ProjectTemplateZipTargets.FileName)</TopLevelTemplate> + </VSGalleryVsixRawSources> + <VSGalleryVsixSources Include="@(VSGalleryVsixRawSources)"> + <TargetPath>$(IntermediatePath)%(TopLevelTemplate).vsix\%(FileName)%(Extension)</TargetPath> + </VSGalleryVsixSources> + + <VSGalleryVsixZipSources Include="$(ExtensionVsixLayoutDirectory)**\*.zip" /> + <VSGalleryVsixSources Include="@(VSGalleryVsixZipSources)"> + <TopLevelTemplate>%(FileName)</TopLevelTemplate> + <VSGalleryVsix>$(DropsRoot)$(ProductName) %(FileName)-$(BuildVersion).vsix</VSGalleryVsix> + <!-- The A in the path below used to be %(FileName), but to fit inside MAX_PATH when VS expands, we shorten it. --> + <TargetPath>$(IntermediatePath)%(FileName).vsix\%(RecursiveDir)A%(Extension)</TargetPath> + </VSGalleryVsixSources> + + <VSGalleryVsixSources Include="@(ProjectTemplateZipTargets->'$(ProjectRoot)projecttemplates\%(FileName).vsixmanifest')"> + <VSGalleryVsix>$(DropsRoot)$(ProductName) %(ProjectTemplateZipTargets.FileName)-$(BuildVersion).vsix</VSGalleryVsix> + <TopLevelTemplate>%(ProjectTemplateZipTargets.FileName)</TopLevelTemplate> + <TargetPath>$(IntermediatePath)%(ProjectTemplateZipTargets.FileName).vsix\extension.vsixmanifest</TargetPath> + <Transform>true</Transform> + <BeforeTokens>$version$</BeforeTokens> + <AfterTokens>$(BuildVersion)</AfterTokens> + <SkipUnchangedFiles>false</SkipUnchangedFiles> + </VSGalleryVsixSources> + + <VSGalleryVsixTargets Include="@(VSGalleryVsixSources->'%(TargetPath)')"> + <WorkingDirectory>$(IntermediatePath)%(TopLevelTemplate).vsix</WorkingDirectory> + </VSGalleryVsixTargets> + <VSGalleryVsixPathsToPurge Include="@(ProjectTemplateZipTargets->'$(IntermediatePath)%(FileName).vsix')"/> + </ItemGroup> + + <HardLinkCopy + SourceFiles="@(VSGalleryVsixSources)" + DestinationFiles="%(VSGalleryVsixSources.TargetPath)" + Condition=" '%(VSGalleryVsixSources.Transform)' != 'true' "/> + <CopyWithTokenSubstitution + SourceFiles="@(VSGalleryVsixSources)" + DestinationFiles="%(VSGalleryVsixSources.TargetPath)" + Condition=" '%(VSGalleryVsixSources.Transform)' == 'true' "/> + <Purge + Directories="@(VSGalleryVsixPathsToPurge)" + IntendedFiles="@(VSGalleryVsixTargets)" /> + </Target> + + <Target Name="Build" DependsOnTargets="Layout;VSGalleryVsixLayout" Returns="@(GeneratedVsix)"> + <PropertyGroup> + <ExtensionVsix>$(DropsRoot)$(ProductName) SDK-$(BuildVersion).vsix</ExtensionVsix> + </PropertyGroup> + <ItemGroup> + <GeneratedVsix Include="$(ExtensionVsix)"> + <IncludeInDrop>true</IncludeInDrop> + </GeneratedVsix> + <GeneratedVsix Include="%(VSGalleryVsixTargets.VSGalleryVsix)" /> + </ItemGroup> + + <Zip + Files="@(ExtensionVsixContents)" + ZipFileName="$(ExtensionVsix)" + WorkingDirectory="$(ExtensionVsixLayoutDirectory)" + ZipLevel="$(ZipLevel)" + /> + + <Zip + Files="@(VSGalleryVsixTargets)" + ZipFileName="%(VSGalleryVsixTargets.VSGalleryVsix)" + WorkingDirectory="%(VSGalleryVsixTargets.WorkingDirectory)" + ZipLevel="$(ZipLevel)" + /> + </Target> + + <Import Project="$(ProjectRoot)tools\DotNetOpenAuth.automated.targets"/> +</Project>
\ No newline at end of file |