aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs9
-rw-r--r--src/ext/Util/wixext/UtilCompiler.cs36
-rw-r--r--src/wix/WixToolset.Converters/WixConverter.cs128
-rw-r--r--src/wix/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs82
4 files changed, 237 insertions, 18 deletions
diff --git a/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs b/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs
index 0634d7d4..09f0a724 100644
--- a/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs
+++ b/src/ext/Util/test/WixToolsetTest.Util/TestData/PermissionEx/PackageComponents.wxs
@@ -1,4 +1,4 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util"> 1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
2 <Fragment> 2 <Fragment>
3 <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER"> 3 <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
4 <Component> 4 <Component>
@@ -15,7 +15,12 @@
15 <util:PermissionEx User="Everyone" GenericAll="yes" /> 15 <util:PermissionEx User="Everyone" GenericAll="yes" />
16 </RegistryKey> 16 </RegistryKey>
17 <RegistryValue Root="HKLM" Key="TestRegistryValueKey" Value="abc"> 17 <RegistryValue Root="HKLM" Key="TestRegistryValueKey" Value="abc">
18 <util:PermissionEx User="Everyone" GenericAll="yes" /> 18 <!--
19 Example of placing the namespace on the extension element. This is NOT recommended
20 in v4 and its converter will move namespaces to the root, but WiX v3 allowed it so
21 we'll continued to do so for now.
22 -->
23 <PermissionEx User="Everyone" GenericAll="yes" xmlns="http://wixtoolset.org/schemas/v4/wxs/util" />
19 </RegistryValue> 24 </RegistryValue>
20 </Component> 25 </Component>
21 </ComponentGroup> 26 </ComponentGroup>
diff --git a/src/ext/Util/wixext/UtilCompiler.cs b/src/ext/Util/wixext/UtilCompiler.cs
index 47f82ca6..96b2ee0a 100644
--- a/src/ext/Util/wixext/UtilCompiler.cs
+++ b/src/ext/Util/wixext/UtilCompiler.cs
@@ -1286,6 +1286,8 @@ namespace WixToolset.Util
1286 var bits = new BitArray(32); 1286 var bits = new BitArray(32);
1287 string user = null; 1287 string user = null;
1288 1288
1289 var validBitNames = new HashSet<string>(UtilConstants.StandardPermissions.Concat(UtilConstants.GenericPermissions).Concat(UtilConstants.FolderPermissions));
1290
1289 foreach (var attrib in element.Attributes()) 1291 foreach (var attrib in element.Attributes())
1290 { 1292 {
1291 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) 1293 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
@@ -1297,18 +1299,18 @@ namespace WixToolset.Util
1297 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.User, user); 1299 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, UtilSymbolDefinitions.User, user);
1298 break; 1300 break;
1299 default: 1301 default:
1300 var attribValue = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); 1302 if (validBitNames.Contains(attrib.Name.LocalName))
1301 if (!this.TrySetBitFromName(UtilConstants.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16))
1302 { 1303 {
1303 if (!this.TrySetBitFromName(UtilConstants.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28)) 1304 var attribValue = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
1305 if (this.TrySetBitFromName(UtilConstants.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16) ||
1306 this.TrySetBitFromName(UtilConstants.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28) ||
1307 this.TrySetBitFromName(UtilConstants.FolderPermissions, attrib.Name.LocalName, attribValue, bits, 0))
1304 { 1308 {
1305 if (!this.TrySetBitFromName(UtilConstants.FolderPermissions, attrib.Name.LocalName, attribValue, bits, 0)) 1309 break;
1306 {
1307 this.ParseHelper.UnexpectedAttribute(element, attrib);
1308 break;
1309 }
1310 } 1310 }
1311 } 1311 }
1312
1313 this.ParseHelper.UnexpectedAttribute(element, attrib);
1312 break; 1314 break;
1313 } 1315 }
1314 } 1316 }
@@ -2477,6 +2479,8 @@ namespace WixToolset.Util
2477 break; 2479 break;
2478 } 2480 }
2479 2481
2482 var validBitNames = new HashSet<string>(UtilConstants.StandardPermissions.Concat(UtilConstants.GenericPermissions).Concat(specialPermissions));
2483
2480 foreach (var attrib in element.Attributes()) 2484 foreach (var attrib in element.Attributes())
2481 { 2485 {
2482 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) 2486 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
@@ -2500,18 +2504,18 @@ namespace WixToolset.Util
2500 user = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); 2504 user = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2501 break; 2505 break;
2502 default: 2506 default:
2503 var attribValue = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib); 2507 if (validBitNames.Contains(attrib.Name.LocalName))
2504 if (!this.TrySetBitFromName(UtilConstants.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16))
2505 { 2508 {
2506 if (!this.TrySetBitFromName(UtilConstants.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28)) 2509 var attribValue = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
2510 if (this.TrySetBitFromName(UtilConstants.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16) ||
2511 this.TrySetBitFromName(UtilConstants.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28) ||
2512 this.TrySetBitFromName(specialPermissions, attrib.Name.LocalName, attribValue, bits, 0))
2507 { 2513 {
2508 if (!this.TrySetBitFromName(specialPermissions, attrib.Name.LocalName, attribValue, bits, 0)) 2514 break;
2509 {
2510 this.ParseHelper.UnexpectedAttribute(element, attrib);
2511 break;
2512 }
2513 } 2515 }
2514 } 2516 }
2517
2518 this.ParseHelper.UnexpectedAttribute(element, attrib);
2515 break; 2519 break;
2516 } 2520 }
2517 } 2521 }
diff --git a/src/wix/WixToolset.Converters/WixConverter.cs b/src/wix/WixToolset.Converters/WixConverter.cs
index 37b99a95..941a5062 100644
--- a/src/wix/WixToolset.Converters/WixConverter.cs
+++ b/src/wix/WixToolset.Converters/WixConverter.cs
@@ -402,6 +402,7 @@ namespace WixToolset.Converters
402 // Start converting the nodes at the top. 402 // Start converting the nodes at the top.
403 this.ConvertNodes(document.Nodes(), 0); 403 this.ConvertNodes(document.Nodes(), 0);
404 this.RemoveUnusedNamespaces(document.Root); 404 this.RemoveUnusedNamespaces(document.Root);
405 this.MoveNamespacesToRoot(document.Root);
405 } 406 }
406 407
407 private void Format(XDocument document) 408 private void Format(XDocument document)
@@ -424,6 +425,7 @@ namespace WixToolset.Converters
424 // Start converting the nodes at the top. 425 // Start converting the nodes at the top.
425 this.ConvertNodes(document.Nodes(), 0); 426 this.ConvertNodes(document.Nodes(), 0);
426 this.RemoveUnusedNamespaces(document.Root); 427 this.RemoveUnusedNamespaces(document.Root);
428 this.MoveNamespacesToRoot(document.Root);
427 } 429 }
428 430
429 private bool TryOpenSourceFile(string sourceFile, out XDocument document) 431 private bool TryOpenSourceFile(string sourceFile, out XDocument document)
@@ -2253,6 +2255,50 @@ namespace WixToolset.Converters
2253 } 2255 }
2254 } 2256 }
2255 2257
2258 private void MoveNamespacesToRoot(XElement root)
2259 {
2260 var rootNamespaces = new HashSet<string>();
2261 var rootNamespacePrefixes = new HashSet<string>();
2262 var nonRootDeclarations = new List<XAttribute>();
2263
2264 VisitElement(root, x =>
2265 {
2266 if (x is XAttribute a && a.IsNamespaceDeclaration)
2267 {
2268 if (x.Parent == root)
2269 {
2270 rootNamespaces.Add(a.Value);
2271 rootNamespacePrefixes.Add(a.Name.LocalName);
2272 }
2273 else
2274 {
2275 nonRootDeclarations.Add(a);
2276 }
2277 }
2278
2279 return true;
2280 });
2281
2282 foreach (var declaration in nonRootDeclarations)
2283 {
2284 if (this.OnInformation(ConverterTestType.MoveNamespacesToRoot, declaration, "Namespace should be defined on the root. The '{0}' namespace was move to the root element.", declaration.Value))
2285 {
2286 if (!rootNamespaces.Contains(declaration.Value))
2287 {
2288 var prefix = GetNamespacePrefix(declaration, rootNamespacePrefixes);
2289
2290 var rootDeclaration = new XAttribute(XNamespace.Xmlns + prefix, declaration.Value);
2291 root.Add(rootDeclaration);
2292
2293 rootNamespaces.Add(rootDeclaration.Value);
2294 rootNamespacePrefixes.Add(rootDeclaration.Name.LocalName);
2295 }
2296
2297 declaration.Remove();
2298 }
2299 }
2300 }
2301
2256 private int ReportMessages(XDocument document, bool saved) 2302 private int ReportMessages(XDocument document, bool saved)
2257 { 2303 {
2258 var conversionCount = this.ConversionMessages.Count; 2304 var conversionCount = this.ConversionMessages.Count;
@@ -2457,6 +2503,83 @@ namespace WixToolset.Converters
2457 return result; 2503 return result;
2458 } 2504 }
2459 2505
2506 private static string GetNamespacePrefix(XAttribute declaration, HashSet<string> usedPrefixes)
2507 {
2508 var baseNamespace = String.Empty;
2509
2510 switch (declaration.Value)
2511 {
2512 case "http://wixtoolset.org/schemas/v4/wxs/bal":
2513 baseNamespace = "bal";
2514 break;
2515
2516 case "http://wixtoolset.org/schemas/v4/wxs/complus":
2517 baseNamespace = "complus";
2518 break;
2519
2520 case "http://wixtoolset.org/schemas/v4/wxs/dependency":
2521 baseNamespace = "dependency";
2522 break;
2523
2524 case "http://wixtoolset.org/schemas/v4/wxs/difxapp":
2525 baseNamespace = "difx";
2526 break;
2527
2528 case "http://wixtoolset.org/schemas/v4/wxs/directx":
2529 baseNamespace = "directx";
2530 break;
2531
2532 case "http://wixtoolset.org/schemas/v4/wxs/firewall":
2533 baseNamespace = "fw";
2534 break;
2535
2536 case "http://wixtoolset.org/schemas/v4/wxs/http":
2537 baseNamespace = "http";
2538 break;
2539
2540 case "http://wixtoolset.org/schemas/v4/wxs/iis":
2541 baseNamespace = "iis";
2542 break;
2543
2544 case "http://wixtoolset.org/schemas/v4/wxs/msmq":
2545 baseNamespace = "msmq";
2546 break;
2547
2548 case "http://wixtoolset.org/schemas/v4/wxs/netfx":
2549 baseNamespace = "netfx";
2550 break;
2551
2552 case "http://wixtoolset.org/schemas/v4/wxs/powershell":
2553 baseNamespace = "ps";
2554 break;
2555
2556 case "http://wixtoolset.org/schemas/v4/wxs/sql":
2557 baseNamespace = "sql";
2558 break;
2559
2560 case "http://wixtoolset.org/schemas/v4/wxs/ui":
2561 baseNamespace = "ui";
2562 break;
2563
2564 case "http://wixtoolset.org/schemas/v4/wxs/util":
2565 baseNamespace = "util";
2566 break;
2567
2568 case "http://wixtoolset.org/schemas/v4/wxs/vs":
2569 baseNamespace = "vs";
2570 break;
2571 }
2572
2573 var ns = baseNamespace;
2574
2575 for (var i = 1; usedPrefixes.Contains(ns); ++i)
2576 {
2577 ns = baseNamespace + i;
2578 }
2579
2580 return ns;
2581 }
2582
2460 private static string LowercaseFirstChar(string value) 2583 private static string LowercaseFirstChar(string value)
2461 { 2584 {
2462 if (!String.IsNullOrEmpty(value)) 2585 if (!String.IsNullOrEmpty(value))
@@ -2928,6 +3051,11 @@ namespace WixToolset.Converters
2928 /// The MsuPackage element contains obsolete '{0}' attribute. MSU packages are now always permanent because Windows no longer supports silently removing MSUs. The attribute will be removed. 3051 /// The MsuPackage element contains obsolete '{0}' attribute. MSU packages are now always permanent because Windows no longer supports silently removing MSUs. The attribute will be removed.
2929 /// </summary> 3052 /// </summary>
2930 MsuPackagePermanentObsolete, 3053 MsuPackagePermanentObsolete,
3054
3055 /// <summary>
3056 /// Namespace should be defined on the root. The '{0}' namespace was move to the root element.
3057 /// </summary>
3058 MoveNamespacesToRoot,
2931 } 3059 }
2932 } 3060 }
2933} 3061}
diff --git a/src/wix/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs b/src/wix/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs
index 3d3fde16..2c1179d7 100644
--- a/src/wix/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs
+++ b/src/wix/test/WixToolsetTest.Converters/FirewallExtensionFixture.cs
@@ -3,6 +3,7 @@
3namespace WixToolsetTest.Converters 3namespace WixToolsetTest.Converters
4{ 4{
5 using System; 5 using System;
6 using System.Linq;
6 using System.Xml.Linq; 7 using System.Xml.Linq;
7 using WixInternal.TestSupport; 8 using WixInternal.TestSupport;
8 using WixToolset.Converters; 9 using WixToolset.Converters;
@@ -43,5 +44,86 @@ namespace WixToolsetTest.Converters
43 var actualLines = UnformattedDocumentLines(document); 44 var actualLines = UnformattedDocumentLines(document);
44 WixAssert.CompareLineByLine(expected, actualLines); 45 WixAssert.CompareLineByLine(expected, actualLines);
45 } 46 }
47
48 [Fact]
49 public void FixNamespacePlacement()
50 {
51 var parse = String.Join(Environment.NewLine,
52 "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>",
53 " <Fragment>",
54 " <RemoteAddress xmlns='http://schemas.microsoft.com/wix/FirewallExtension'>",
55 " 127.0.0.1",
56 " </RemoteAddress>",
57 " </Fragment>",
58 "</Wix>");
59
60 var expected = new[]
61 {
62 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\" xmlns:fw=\"http://wixtoolset.org/schemas/v4/wxs/firewall\">",
63 " <Fragment>",
64 " <fw:RemoteAddress Value=\"127.0.0.1\" />",
65 " </Fragment>",
66 "</Wix>"
67 };
68
69 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
70
71 var messaging = new MockMessaging();
72 var converter = new WixConverter(messaging, 2, null, null);
73
74 var errors = converter.ConvertDocument(document);
75 WixAssert.CompareLineByLine(new[]
76 {
77 "[Converted] The namespace 'http://schemas.microsoft.com/wix/2006/wi' is out of date. It must be 'http://wixtoolset.org/schemas/v4/wxs'. (XmlnsValueWrong)",
78 "[Converted] The namespace 'http://schemas.microsoft.com/wix/FirewallExtension' is out of date. It must be 'http://wixtoolset.org/schemas/v4/wxs/firewall'. (XmlnsValueWrong)",
79 "[Converted] Using RemoteAddress element text is deprecated. Use the 'Value' attribute instead. (InnerTextDeprecated)",
80 "[Converted] Namespace should be defined on the root. The 'http://wixtoolset.org/schemas/v4/wxs/firewall' namespace was move to the root element. (MoveNamespacesToRoot)"
81 }, messaging.Messages.Select(m => m.ToString()).ToArray());
82 Assert.Equal(4, errors);
83
84 var actualLines = UnformattedDocumentLines(document);
85 WixAssert.CompareLineByLine(expected, actualLines);
86 }
87
88 [Fact]
89 public void FixNamespacePlacementWhenItExists()
90 {
91 //xmlns:abc='http://schemas.microsoft.com/wix/FirewallExtension'
92 var parse = String.Join(Environment.NewLine,
93 "<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>",
94 " <Fragment>",
95 " <RemoteAddress xmlns='http://schemas.microsoft.com/wix/FirewallExtension'>",
96 " 127.0.0.1",
97 " </RemoteAddress>",
98 " </Fragment>",
99 "</Wix>");
100
101 var expected = new[]
102 {
103 "<Wix xmlns=\"http://wixtoolset.org/schemas/v4/wxs\" xmlns:fw=\"http://wixtoolset.org/schemas/v4/wxs/firewall\">",
104 " <Fragment>",
105 " <fw:RemoteAddress Value=\"127.0.0.1\" />",
106 " </Fragment>",
107 "</Wix>"
108 };
109
110 var document = XDocument.Parse(parse, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
111
112 var messaging = new MockMessaging();
113 var converter = new WixConverter(messaging, 2, null, null);
114
115 var errors = converter.ConvertDocument(document);
116 WixAssert.CompareLineByLine(new[]
117 {
118 "[Converted] The namespace 'http://schemas.microsoft.com/wix/2006/wi' is out of date. It must be 'http://wixtoolset.org/schemas/v4/wxs'. (XmlnsValueWrong)",
119 "[Converted] The namespace 'http://schemas.microsoft.com/wix/FirewallExtension' is out of date. It must be 'http://wixtoolset.org/schemas/v4/wxs/firewall'. (XmlnsValueWrong)",
120 "[Converted] Using RemoteAddress element text is deprecated. Use the 'Value' attribute instead. (InnerTextDeprecated)",
121 "[Converted] Namespace should be defined on the root. The 'http://wixtoolset.org/schemas/v4/wxs/firewall' namespace was move to the root element. (MoveNamespacesToRoot)"
122 }, messaging.Messages.Select(m => m.ToString()).ToArray());
123 Assert.Equal(4, errors);
124
125 var actualLines = UnformattedDocumentLines(document);
126 WixAssert.CompareLineByLine(expected, actualLines);
127 }
46 } 128 }
47} 129}