From f46ca6a9dce91607ffc9855270dd6998216e1a8b Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 14 Jul 2022 06:05:28 -0700 Subject: Support remote Payloads Closes 5601 Closes 6802 --- src/api/wix/WixToolset.Data/WarningMessages.cs | 2 +- .../WixToolset.Core.Burn/Bind/BindBundleCommand.cs | 6 +- src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs | 6 ++ src/wix/WixToolset.Core/Compile/CompilerPayload.cs | 13 ++-- src/wix/WixToolset.Core/Compiler_Bundle.cs | 36 +++++++--- .../BundlePackageFixture.cs | 4 +- .../BurnRemotePayloadSubcommandFixture.cs | 4 +- .../PayloadFixture.cs | 81 ++++++++++++++++++++++ .../RemotePayloadInBootstrapperApplication.wxs | 17 +++++ .../TestData/Payload/RemotePayloadInPackage.wxs | 17 +++++ 10 files changed, 164 insertions(+), 22 deletions(-) create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/Payload/RemotePayloadInBootstrapperApplication.wxs create mode 100644 src/wix/test/WixToolsetTest.CoreIntegration/TestData/Payload/RemotePayloadInPackage.wxs (limited to 'src') diff --git a/src/api/wix/WixToolset.Data/WarningMessages.cs b/src/api/wix/WixToolset.Data/WarningMessages.cs index 5d3f06f8..d39ead3d 100644 --- a/src/api/wix/WixToolset.Data/WarningMessages.cs +++ b/src/api/wix/WixToolset.Data/WarningMessages.cs @@ -650,7 +650,7 @@ namespace WixToolset.Data public static Message UxPayloadsOnlySupportEmbedding(SourceLineNumber sourceLineNumbers, string sourceFile) { - return Message(sourceLineNumbers, Ids.UxPayloadsOnlySupportEmbedding, "A bootstrapper application payload ('{0}') was marked for something other than embedded packaging, possibly because it included a @DownloadUrl attribute. At present, bootstrapper application payloads must be embedded in the bundle, so the requested packaging is being ignored.", sourceFile); + return Message(sourceLineNumbers, Ids.UxPayloadsOnlySupportEmbedding, "A bootstrapper application or bundle extension payload ('{0}') was marked for something other than embedded packaging, possibly because it included a @DownloadUrl attribute. Bootstrapper application and bundle extension payloads must be embedded in the bundle, so the requested packaging is being ignored and the file is being embedded anyway.", sourceFile); } public static Message ValidationFailedDueToSystemPolicy() diff --git a/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs b/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs index a961ef0f..44fb84c7 100644 --- a/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs +++ b/src/wix/WixToolset.Core.Burn/Bind/BindBundleCommand.cs @@ -300,7 +300,11 @@ namespace WixToolset.Core.Burn // downloaded. The current engine requires the UX to be fully present before any downloading starts, // so that rules out downloading. Also, the burn engine does not currently copy external UX payloads // into the temporary UX directory correctly, so we don't allow external either. - if (PackagingType.Embedded != payload.Packaging) + if (payload.SourceFile is null) + { + this.Messaging.Write(BurnBackendErrors.BAContainerCannotContainRemotePayload(payload.SourceLineNumbers, payload.Name)); + } + else if (PackagingType.Embedded != payload.Packaging) { this.Messaging.Write(WarningMessages.UxPayloadsOnlySupportEmbedding(payload.SourceLineNumbers, payload.SourceFile.Path)); payload.Packaging = PackagingType.Embedded; diff --git a/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs b/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs index 04290667..cc3a998f 100644 --- a/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs +++ b/src/wix/WixToolset.Core.Burn/BurnBackendErrors.cs @@ -95,6 +95,11 @@ namespace WixToolset.Core.Burn return Message(sourceLineNumbers, Ids.InvalidBundleManifest, "Unable to read bundle executable '{0}'. Its manifest is invalid. {1}", bundleExecutable, reason); } + public static Message BAContainerCannotContainRemotePayload(SourceLineNumber sourceLineNumbers, string payloadName) + { + return Message(sourceLineNumbers, Ids.BAContainerCannotContainRemotePayload, "Bootstrapper application and bundle extension payloads must be embedded in the bundle. The payload '{0}' is remote thus cannot be found for embedding. Provide a full path to the payload via the Payload/@SourceFile attribute.", payloadName); + } + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) { return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); @@ -116,6 +121,7 @@ namespace WixToolset.Core.Burn FailedToAddIconOrSplashScreenToBundle = 8011, InvalidBundleManifest = 8012, BundleMultipleProviders = 8013, + BAContainerCannotContainRemotePayload = 8014, } // last available is 8499. 8500 is BurnBackendWarnings. } } diff --git a/src/wix/WixToolset.Core/Compile/CompilerPayload.cs b/src/wix/WixToolset.Core/Compile/CompilerPayload.cs index 98ab1579..a83f1d8b 100644 --- a/src/wix/WixToolset.Core/Compile/CompilerPayload.cs +++ b/src/wix/WixToolset.Core/Compile/CompilerPayload.cs @@ -247,13 +247,12 @@ namespace WixToolset.Core { this.CalculateAndVerifyFields(); this.GenerateIdFromFilename(); - this.GenerateIdFromPrefix("ppy"); } - public void FinishCompilingPayload() + public void FinishCompilingPayload(string parentId) { this.CalculateAndVerifyFields(); - this.GenerateIdFromPrefix("pay"); + this.GenerateIdFromPrefix("pay", parentId); } private void GenerateIdFromFilename() @@ -268,14 +267,18 @@ namespace WixToolset.Core { this.Id = this.Core.CreateIdentifierFromFilename(Path.GetFileName(this.SourceFile)); } + else // if Name and SourceFile were not specified an error was already reported. + { + this.Id = Identifier.Invalid; + } } } - private void GenerateIdFromPrefix(string prefix) + private void GenerateIdFromPrefix(string prefix, string parentId) { if (this.Id == null) { - this.Id = this.Core.CreateIdentifier(prefix, this.SourceFile?.ToUpperInvariant() ?? String.Empty); + this.Id = this.Core.CreateIdentifier(prefix, parentId, this.SourceFile?.ToUpperInvariant() ?? this.Name?.ToUpperInvariant()); } } diff --git a/src/wix/WixToolset.Core/Compiler_Bundle.cs b/src/wix/WixToolset.Core/Compiler_Bundle.cs index 3ff8216b..376d0150 100644 --- a/src/wix/WixToolset.Core/Compiler_Bundle.cs +++ b/src/wix/WixToolset.Core/Compiler_Bundle.cs @@ -698,7 +698,7 @@ namespace WixToolset.Core this.ParseBootstrapperApplicationDllElement(child, id); break; case "Payload": - this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); + this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, isRemoteAllowed: false); break; case "PayloadGroupRef": this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); @@ -788,7 +788,7 @@ namespace WixToolset.Core } } - compilerPayload.FinishCompilingPayload(); + compilerPayload.FinishCompilingPayload(Compiler.BurnUXContainerId.Id); // Now that the Id is known, we can parse the extension attributes. var context = new Dictionary @@ -872,7 +872,7 @@ namespace WixToolset.Core switch (child.Name.LocalName) { case "Payload": - this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); + this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, isRemoteAllowed: false); break; case "PayloadGroupRef": this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); @@ -1237,7 +1237,7 @@ namespace WixToolset.Core } } - compilerPayload.FinishCompilingPayload(); + compilerPayload.FinishCompilingPayload(Compiler.BurnUXContainerId.Id); // Now that the Id is known, we can parse the extension attributes. var context = new Dictionary @@ -1259,7 +1259,7 @@ namespace WixToolset.Core switch (child.Name.LocalName) { case "Payload": - this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); + this.ParsePayloadElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, isRemoteAllowed: false); break; case "PayloadGroupRef": this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId); @@ -1393,12 +1393,16 @@ namespace WixToolset.Core /// Element to parse /// ComplexReferenceParentType of parent element. (BA or PayloadGroup) /// Identifier of parent element. - private Identifier ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId) + /// Indicates if the Payload element can be remote or not. + private Identifier ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId, bool isRemoteAllowed) { Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType); var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node); + var compilerPayload = new CompilerPayload(this.Core, sourceLineNumbers, node) + { + IsRemoteAllowed = isRemoteAllowed + }; // This list lets us evaluate extension attributes *after* all core attributes // have been parsed and dealt with, regardless of authoring order. @@ -1414,12 +1418,24 @@ namespace WixToolset.Core case "Id": compilerPayload.ParseId(attrib); break; + case "CertificatePublicKey": + compilerPayload.ParseCertificatePublicKey(attrib); + break; + case "CertificateThumbprint": + compilerPayload.ParseCertificateThumbprint(attrib); + break; case "Compressed": compilerPayload.ParseCompressed(attrib); break; + case "Hash": + compilerPayload.ParseHash(attrib); + break; case "Name": compilerPayload.ParseName(attrib); break; + case "Size": + compilerPayload.ParseSize(attrib); + break; case "SourceFile": compilerPayload.ParseSourceFile(attrib); break; @@ -1442,7 +1458,7 @@ namespace WixToolset.Core } } - compilerPayload.FinishCompilingPayload(); + compilerPayload.FinishCompilingPayload(parentId?.Id); // Now that the PayloadId is known, we can parse the extension attributes. var context = new Dictionary @@ -1539,7 +1555,7 @@ namespace WixToolset.Core packageType = WixBundlePackageType.Msu; break; case "Payload": - this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id); + this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id, isRemoteAllowed: true); break; case "PayloadGroupRef": this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.PayloadGroup, id); @@ -2263,7 +2279,7 @@ namespace WixToolset.Core } break; case "Payload": - this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id); + this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id, isRemoteAllowed: true); break; case "PayloadGroupRef": this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Package, id); diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs index eb1d02f2..7bf9fc70 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundlePackageFixture.cs @@ -103,7 +103,7 @@ namespace WixToolsetTest.CoreIntegration "" + "" + "" + - "" + + "" + "", }, bundlePackages); @@ -175,7 +175,7 @@ namespace WixToolsetTest.CoreIntegration var payloads = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Payload", ignoreAttributesByElementName); WixAssert.CompareLineByLine(new[] { - "", + "", "", }, payloads); diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BurnRemotePayloadSubcommandFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BurnRemotePayloadSubcommandFixture.cs index f9059db0..4d4d3f83 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/BurnRemotePayloadSubcommandFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/BurnRemotePayloadSubcommandFixture.cs @@ -398,7 +398,7 @@ namespace WixToolsetTest.CoreIntegration } } - [Fact(Skip = "Blocked by https://github.com/wixtoolset/issues/issues/5601 - Support RemotePayload for Payload elements")] + [Fact] public void CanGetRemotePayloadWithCertificate() { var folder = TestData.Get(@"TestData"); @@ -441,9 +441,7 @@ namespace WixToolsetTest.CoreIntegration var remotePayloadSourceText = "" + " " + " " + - " " + String.Join(Environment.NewLine, elements) + - " " + " " + " " + ""; diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs index 868b6c21..58357ca9 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/PayloadFixture.cs @@ -201,5 +201,86 @@ namespace WixToolsetTest.CoreIntegration }, containers); } } + + [Fact] + public void CanBuildBundleWithRemotePackagePaylod() + { + var folder = TestData.Get(@"TestData"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var bundlePath = Path.Combine(baseFolder, @"bin\test.exe"); + var baFolderPath = Path.Combine(baseFolder, "ba"); + var extractFolderPath = Path.Combine(baseFolder, "extract"); + + var result = WixRunner.Execute(false, new[] + { + "build", + Path.Combine(folder, "Payload", "RemotePayloadInPackage.wxs"), + Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"), + "-bindpath", Path.Combine(folder, ".Data"), + "-bindpath", Path.Combine(folder, "SimpleBundle", "data"), + "-intermediateFolder", intermediateFolder, + "-o", bundlePath + }); + + result.AssertSuccess(); + + Assert.True(File.Exists(bundlePath)); + + var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); + extractResult.AssertSuccess(); + + var payloadElements = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Payload"); + WixAssert.CompareLineByLine(new[] + { + "", + "", + "", + "", + }, payloadElements); + + var payloadRefElements = extractResult.GetManifestTestXmlLines("/burn:BurnManifest/burn:Chain/burn:ExePackage/burn:PayloadRef"); + WixAssert.CompareLineByLine(new[] + { + "", + "", + "", + "" + }, payloadRefElements); + } + } + + [Fact] + public void CannotBuildRemotePayloadInBootstrapperApplication() + { + var folder = TestData.Get(@"TestData"); + + using (var fs = new DisposableFileSystem()) + { + var baseFolder = fs.GetFolder(); + var intermediateFolder = Path.Combine(baseFolder, "obj"); + var bundlePath = Path.Combine(baseFolder, "bin", "test.exe"); + + var result = WixRunner.Execute(false, new[] + { + "build", + Path.Combine(folder, "Payload", "RemotePayloadInBootstrapperApplication.wxs"), + Path.Combine(folder, "SimpleBundle", "MultiFileBootstrapperApplication.wxs"), + "-bindpath", Path.Combine(folder, "SimpleBundle", "data"), + "-bindpath", Path.Combine(folder, ".Data"), + "-intermediateFolder", intermediateFolder, + "-o", bundlePath, + }); + + WixAssert.CompareLineByLine(new[] + { + "The Payload 'RemotePayload' is being added to Container 'WixUXContainer', overriding its Compressed value of 'no'.", + "Bootstrapper application and bundle extension payloads must be embedded in the bundle. The payload 'someremotefile.txt' is remote thus cannot be found for embedding. Provide a full path to the payload via the Payload/@SourceFile attribute." + }, result.Messages.Select(m => m.ToString()).ToArray()); + } + } } } diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Payload/RemotePayloadInBootstrapperApplication.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Payload/RemotePayloadInBootstrapperApplication.wxs new file mode 100644 index 00000000..b8d8139a --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Payload/RemotePayloadInBootstrapperApplication.wxs @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Payload/RemotePayloadInPackage.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Payload/RemotePayloadInPackage.wxs new file mode 100644 index 00000000..18654ec1 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/Payload/RemotePayloadInPackage.wxs @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + -- cgit v1.2.3-55-g6feb