@joebigelow / wix / commits / 2427be20

Modernize FirewallCompiler and tuples.

Sean Hall committed Apr 9, 2020 at 09:01 UTC 2427be20a103957f204b753db45ee89ad636bb08
9 files changed +112 -92
src/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
+1 -1
@@ -20,7 +20,7 @@ namespace WixToolsetTest.Firewall
20 Assert.Equal(new[]
21 {
22 "WixFirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall",
23 - }, results.OrderBy(s => s).ToArray());
23 + }, results);
24 }
25
26 private static void Build(string[] args)
src/wixext/FirewallCompiler.cs
+24 -26
@@ -28,8 +28,8 @@ namespace WixToolset.Firewall
28 switch (parentElement.Name.LocalName)
29 {
30 case "File":
31 - string fileId = context["FileId"];
32 - string fileComponentId = context["ComponentId"];
31 + var fileId = context["FileId"];
32 + var fileComponentId = context["ComponentId"];
33
34 switch (element.Name.LocalName)
35 {
@@ -42,7 +42,7 @@ namespace WixToolset.Firewall
42 }
43 break;
44 case "Component":
45 - string componentId = context["ComponentId"];
45 + var componentId = context["ComponentId"];
46
47 switch (element.Name.LocalName)
48 {
@@ -68,22 +68,20 @@ namespace WixToolset.Firewall
68 /// <param name="fileId">The file identifier of the parent element (null if nested under Component).</param>
69 private void ParseFirewallExceptionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId)
70 {
71 - SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
71 + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
72 Identifier id = null;
73 string name = null;
74 int attributes = 0;
75 string file = null;
76 string program = null;
77 string port = null;
78 - string protocolValue = null;
78 int? protocol = null;
80 - string profileValue = null;
79 int? profile = null;
80 string scope = null;
81 string remoteAddresses = null;
82 string description = null;
83
86 - foreach (XAttribute attrib in element.Attributes())
84 + foreach (var attrib in element.Attributes())
85 {
86 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
87 {
@@ -125,7 +123,7 @@ namespace WixToolset.Firewall
123 port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
124 break;
125 case "Protocol":
128 - protocolValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
126 + var protocolValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
127 switch (protocolValue)
128 {
129 case "tcp":
@@ -155,7 +153,7 @@ namespace WixToolset.Firewall
153 }
154 break;
155 case "Profile":
158 - profileValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
156 + var profileValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
157 switch (profileValue)
158 {
159 case "domain":
@@ -190,11 +188,10 @@ namespace WixToolset.Firewall
188 }
189
190 // parse RemoteAddress children
193 - foreach (XElement child in element.Elements())
191 + foreach (var child in element.Elements())
192 {
193 if (this.Namespace == child.Name.Namespace)
194 {
197 - SourceLineNumber childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
195 switch (child.Name.LocalName)
196 {
197 case "RemoteAddress":
@@ -218,12 +215,12 @@ namespace WixToolset.Firewall
215 }
216 }
217
221 - // Id and Name are required
218 if (null == id)
219 {
224 - this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id"));
220 + id = this.ParseHelper.CreateIdentifier("fex", name, remoteAddresses, componentId);
221 }
222
223 + // Name is required
224 if (null == name)
225 {
226 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
@@ -255,14 +252,14 @@ namespace WixToolset.Firewall
252 fileId = file;
253 }
254
258 - var tuple = new WixFirewallExceptionTuple(sourceLineNumbers, id)
255 + var tuple = section.AddTuple(new WixFirewallExceptionTuple(sourceLineNumbers, id)
256 {
257 Name = name,
258 RemoteAddresses = remoteAddresses,
259 Profile = profile ?? FirewallConstants.NET_FW_PROFILE2_ALL,
260 ComponentRef = componentId,
261 Description = description,
265 - };
262 + });
263
264 if (!String.IsNullOrEmpty(port))
265 {
@@ -275,12 +272,15 @@ namespace WixToolset.Firewall
272 }
273 }
274
278 - tuple.Protocol = protocol.Value;
275 + if (protocol.HasValue)
276 + {
277 + tuple.Protocol = protocol.Value;
278 + }
279
280 if (!String.IsNullOrEmpty(fileId))
281 {
282 tuple.Program = $"[#{fileId}]";
283 - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "File", fileId);
283 + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, TupleDefinitions.File, fileId);
284 }
285 else if (!String.IsNullOrEmpty(program))
286 {
@@ -292,19 +292,17 @@ namespace WixToolset.Firewall
292 tuple.Attributes = attributes;
293 }
294
295 - section.Tuples.Add(tuple);
296 -
295 if (this.Context.Platform == Platform.ARM)
296 {
297 // Ensure ARM version of the CA is referenced
300 - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsInstall_ARM");
301 - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsUninstall_ARM");
298 + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, TupleDefinitions.CustomAction, "WixSchedFirewallExceptionsInstall_ARM");
299 + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, TupleDefinitions.CustomAction, "WixSchedFirewallExceptionsUninstall_ARM");
300 }
301 else
302 {
303 // All other supported platforms use x86
306 - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsInstall");
307 - this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsUninstall");
304 + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, TupleDefinitions.CustomAction, "WixSchedFirewallExceptionsInstall");
305 + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, TupleDefinitions.CustomAction, "WixSchedFirewallExceptionsUninstall");
306 }
307 }
308 }
@@ -315,10 +313,10 @@ namespace WixToolset.Firewall
313 /// <param name="element">The element to parse.</param>
314 private void ParseRemoteAddressElement(Intermediate intermediate, IntermediateSection section, XElement element, ref string remoteAddresses)
315 {
318 - SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
316 + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
317
318 // no attributes
321 - foreach (XAttribute attrib in element.Attributes())
319 + foreach (var attrib in element.Attributes())
320 {
321 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
322 {
@@ -332,7 +330,7 @@ namespace WixToolset.Firewall
330
331 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
332
335 - string address = this.ParseHelper.GetTrimmedInnerText(element);
333 + var address = this.ParseHelper.GetTrimmedInnerText(element);
334 if (String.IsNullOrEmpty(address))
335 {
336 this.Messaging.Write(FirewallErrors.IllegalEmptyRemoteAddress(sourceLineNumbers));
src/wixext/FirewallExtensionData.cs
+1 -2
@@ -4,7 +4,6 @@ namespace WixToolset.Firewall
4 {
5 using WixToolset.Data;
6 using WixToolset.Extensibility;
7 - using WixToolset.Firewall.Tuples;
7
8 public sealed class FirewallExtensionData : BaseExtensionData
9 {
@@ -12,7 +11,7 @@ namespace WixToolset.Firewall
11
12 public override bool TryGetTupleDefinitionByName(string name, out IntermediateTupleDefinition tupleDefinition)
13 {
15 - tupleDefinition = (name == FirewallTupleDefinitionNames.WixFirewallException) ? FirewallTupleDefinitions.WixFirewallException : null;
14 + tupleDefinition = FirewallTupleDefinitions.ByName(name);
15 return tupleDefinition != null;
16 }
17
src/wixext/FirewallTableDefinitions.cs new
+33
@@ -0,0 +1,33 @@
1 +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 +
3 +namespace WixToolset.Firewall
4 +{
5 + using WixToolset.Data.WindowsInstaller;
6 +
7 + public static class FirewallTableDefinitions
8 + {
9 + public static readonly TableDefinition WixFirewallException = new TableDefinition(
10 + "WixFirewallException",
11 + new[]
12 + {
13 + new ColumnDefinition("WixFirewallException", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "The primary key, a non-localized token.", modularizeType: ColumnModularizeType.Column),
14 + new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Localizable display name.", modularizeType: ColumnModularizeType.Property),
15 + new ColumnDefinition("RemoteAddresses", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Remote address to accept incoming connections from.", modularizeType: ColumnModularizeType.Property),
16 + new ColumnDefinition("Port", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 1, description: "Port number.", modularizeType: ColumnModularizeType.Property),
17 + new ColumnDefinition("Protocol", ColumnType.Number, 1, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 6, maxValue: 17, description: "Protocol (6=TCP; 17=UDP)."),
18 + new ColumnDefinition("Program", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Exception for a program (formatted path name).", modularizeType: ColumnModularizeType.Property),
19 + new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Vital=1"),
20 + new ColumnDefinition("Profile", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 1, maxValue: 2147483647, description: "Profile (1=domain; 2=private; 4=public; 2147483647=all)."),
21 + new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing component that controls the firewall configuration.", modularizeType: ColumnModularizeType.Column),
22 + new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in Windows Firewall manager for this firewall rule."),
23 + },
24 + tupleDefinitionName: FirewallTupleDefinitions.WixFirewallException.Name,
25 + tupleIdIsPrimaryKey: true
26 + );
27 +
28 + public static readonly TableDefinition[] All = new[]
29 + {
30 + WixFirewallException,
31 + };
32 + }
33 +}
src/wixext/FirewallWindowsInstallerBackendExtension.cs
+2 -17
@@ -1,30 +1,15 @@
1 -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
1 +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 namespace WixToolset.Firewall
4 {
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Xml;
8 - using WixToolset.Data;
8 using WixToolset.Data.WindowsInstaller;
9 using WixToolset.Extensibility;
10
11 public class FirewallWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension
12 {
14 - private static readonly TableDefinition[] Tables = LoadTables();
15 -
16 - public override IEnumerable<TableDefinition> TableDefinitions => Tables;
17 -
18 - public override bool TryAddTupleToOutput(IntermediateTuple tuple, WindowsInstallerData output) => this.BackendHelper.TryAddTupleToOutputMatchingTableDefinitions(tuple, output, this.TableDefinitionsForTuples, true);
19 -
20 - private static TableDefinition[] LoadTables()
21 - {
22 - using (var resourceStream = typeof(FirewallWindowsInstallerBackendBinderExtension).Assembly.GetManifestResourceStream("WixToolset.Firewall.tables.xml"))
23 - using (var reader = XmlReader.Create(resourceStream))
24 - {
25 - var tables = TableDefinitionCollection.Load(reader);
26 - return tables.ToArray();
27 - }
28 - }
13 + public override IEnumerable<TableDefinition> TableDefinitions => FirewallTableDefinitions.All;
14 }
15 }
src/wixext/Tuples/FirewallTupleDefinitions.cs
+26 -17
@@ -1,30 +1,39 @@
1 // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 -namespace WixToolset.Firewall.Tuples
3 +namespace WixToolset.Firewall
4 {
5 + using System;
6 using WixToolset.Data;
7
7 - public static class FirewallTupleDefinitionNames
8 + public enum FirewallTupleDefinitionType
9 {
9 - public static string WixFirewallException { get; } = "WixFirewallException";
10 + WixFirewallException,
11 }
12
13 public static partial class FirewallTupleDefinitions
14 {
14 - public static readonly IntermediateTupleDefinition WixFirewallException = new IntermediateTupleDefinition(
15 - FirewallTupleDefinitionNames.WixFirewallException,
16 - new[]
15 + public static readonly Version Version = new Version("4.0.0");
16 +
17 + public static IntermediateTupleDefinition ByName(string name)
18 + {
19 + if (!Enum.TryParse(name, out FirewallTupleDefinitionType type))
20 {
18 - new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Name), IntermediateFieldType.String),
19 - new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.RemoteAddresses), IntermediateFieldType.String),
20 - new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Port), IntermediateFieldType.String),
21 - new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Protocol), IntermediateFieldType.Number),
22 - new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Program), IntermediateFieldType.String),
23 - new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Attributes), IntermediateFieldType.Number),
24 - new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Profile), IntermediateFieldType.Number),
25 - new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.ComponentRef), IntermediateFieldType.String),
26 - new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Description), IntermediateFieldType.String),
27 - },
28 - typeof(WixFirewallExceptionTuple));
21 + return null;
22 + }
23 +
24 + return ByType(type);
25 + }
26 +
27 + public static IntermediateTupleDefinition ByType(FirewallTupleDefinitionType type)
28 + {
29 + switch (type)
30 + {
31 + case FirewallTupleDefinitionType.WixFirewallException:
32 + return FirewallTupleDefinitions.WixFirewallException;
33 +
34 + default:
35 + throw new ArgumentOutOfRangeException(nameof(type));
36 + }
37 + }
38 }
39 }
src/wixext/Tuples/WixFirewallExceptionTuple.cs
+25
@@ -1,5 +1,30 @@
1 // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 +namespace WixToolset.Firewall
4 +{
5 + using WixToolset.Data;
6 + using WixToolset.Firewall.Tuples;
7 +
8 + public static partial class FirewallTupleDefinitions
9 + {
10 + public static readonly IntermediateTupleDefinition WixFirewallException = new IntermediateTupleDefinition(
11 + FirewallTupleDefinitionType.WixFirewallException.ToString(),
12 + new[]
13 + {
14 + new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Name), IntermediateFieldType.String),
15 + new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.RemoteAddresses), IntermediateFieldType.String),
16 + new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Port), IntermediateFieldType.String),
17 + new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Protocol), IntermediateFieldType.Number),
18 + new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Program), IntermediateFieldType.String),
19 + new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Attributes), IntermediateFieldType.Number),
20 + new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Profile), IntermediateFieldType.Number),
21 + new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.ComponentRef), IntermediateFieldType.String),
22 + new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Description), IntermediateFieldType.String),
23 + },
24 + typeof(WixFirewallExceptionTuple));
25 + }
26 +}
27 +
28 namespace WixToolset.Firewall.Tuples
29 {
30 using WixToolset.Data;
src/wixext/WixToolset.Firewall.wixext.csproj
-1
@@ -14,7 +14,6 @@
14 <ItemGroup>
15 <Content Include="$(MSBuildThisFileName).targets" />
16 <Content Include="firewall.xsd" PackagePath="tools" />
17 - <EmbeddedResource Include="tables.xml" />
17 <EmbeddedResource Include="$(OutputPath)..\firewall.wixlib" />
18 </ItemGroup>
19
src/wixext/tables.xml deleted
-28
@@ -1,28 +0,0 @@
1 -<?xml version="1.0" encoding="utf-8"?>
2 -<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3 -
4 -
5 -<tableDefinitions xmlns="http://wixtoolset.org/schemas/v4/wi/tables">
6 - <tableDefinition name="WixFirewallException">
7 - <columnDefinition name="WixFirewallException" type="string" length="72" primaryKey="yes" modularize="column"
8 - category="identifier" description="The primary key, a non-localized token." />
9 - <columnDefinition name="Name" type="localized" length="255" nullable="yes" modularize="property"
10 - category="formatted" description="Localizable display name." />
11 - <columnDefinition name="RemoteAddresses" type="string" length="0" modularize="property"
12 - category="formatted" description="Remote address to accept incoming connections from." />
13 - <columnDefinition name="Port" type="string" length="0" modularize="property" nullable="yes"
14 - category="formatted" minValue="1" description="Port number." />
15 - <columnDefinition name="Protocol" type="number" length="1" nullable="yes"
16 - category="integer" minValue="6" maxValue="17" description="Protocol (6=TCP; 17=UDP)." />
17 - <columnDefinition name="Program" type="string" length="255" nullable="yes" modularize="property"
18 - category="formatted" description="Exception for a program (formatted path name)." />
19 - <columnDefinition name="Attributes" type="number" length="4" nullable="yes"
20 - description="Vital=1" />
21 - <columnDefinition name="Profile" type="number" length="4" nullable="no"
22 - category="integer" minValue="1" maxValue="2147483647" description="Profile (1=domain; 2=private; 4=public; 2147483647=all)." />
23 - <columnDefinition name="Component_" type="string" length="72" modularize="column"
24 - keyTable="Component" keyColumn="1" category="identifier" description="Foreign key into the Component table referencing component that controls the firewall configuration."/>
25 - <columnDefinition name="Description" type="string" length="255" nullable="yes"
26 - category="formatted" description="Description displayed in Windows Firewall manager for this firewall rule."/>
27 - </tableDefinition>
28 -</tableDefinitions>