@joebigelow / wix / commits / ca376995

Fix handling of long values and baseUri in path fields

Rob Mensching committed Dec 6, 2017 at 11:21 UTC ca376995792d2e2a1a7f39760989496702a8f603
9 files changed +132 -57
src/WixToolset.Data/Intermediate.cs
+31 -18
@@ -4,8 +4,9 @@ namespace WixToolset.Data
4 {
5 using System;
6 using System.Collections.Generic;
7 - using System.Linq;
7 using System.IO;
8 + using System.Linq;
9 + using System.Reflection;
10 using SimpleJson;
11
12 /// <summary>
@@ -99,48 +100,60 @@ namespace WixToolset.Data
100 {
101 using (var stream = File.OpenRead(path))
102 {
103 + var uri = new Uri(Path.GetFullPath(path));
104 var creator = new SimpleTupleDefinitionCreator();
103 - return Intermediate.Load(stream, path, creator, suppressVersionCheck);
105 + return Intermediate.Load(stream, uri, creator, suppressVersionCheck);
106 }
107 }
108
109 /// <summary>
110 /// Loads an intermediate from a stream.
111 /// </summary>
110 - /// <param name="stream">Stream to intermediate file.</param>
112 + /// <param name="assembly">Assembly with intermediate embedded in resource stream.</param>
113 + /// <param name="resourceName">Name of resource stream.</param>
114 /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
115 /// <returns>Returns the loaded intermediate.</returns>
113 - public static Intermediate Load(Stream stream, bool suppressVersionCheck = false)
116 + public static Intermediate Load(Assembly assembly, string resourceName, bool suppressVersionCheck = false)
117 {
118 var creator = new SimpleTupleDefinitionCreator();
116 - return Intermediate.Load(stream, creator, suppressVersionCheck);
119 + return Intermediate.Load(assembly, resourceName, creator, suppressVersionCheck);
120 }
121
122 /// <summary>
120 - /// Loads an intermediate from a path on disk.
123 + /// Loads an intermediate from a stream.
124 /// </summary>
122 - /// <param name="path">Path to intermediate file saved on disk.</param>
125 + /// <param name="assembly">Assembly with intermediate embedded in resource stream.</param>
126 + /// <param name="resourceName">Name of resource stream.</param>
127 /// <param name="creator">ITupleDefinitionCreator to use when reconstituting the intermediate.</param>
128 /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
129 /// <returns>Returns the loaded intermediate.</returns>
126 - public static Intermediate Load(string path, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
130 + public static Intermediate Load(Assembly assembly, string resourceName, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
131 {
128 - using (var stream = File.OpenRead(path))
132 + using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
133 {
130 - return Intermediate.Load(stream, path, creator, suppressVersionCheck);
134 + var uriBuilder = new UriBuilder(assembly.CodeBase);
135 + uriBuilder.Scheme = "embeddedresource";
136 + uriBuilder.Fragment = resourceName;
137 +
138 + return Intermediate.Load(resourceStream, uriBuilder.Uri, creator, suppressVersionCheck);
139 }
140 }
141
142 /// <summary>
143 /// Loads an intermediate from a path on disk.
144 /// </summary>
137 - /// <param name="stream">Stream to intermediate file.</param>
145 + /// <param name="path">Path to intermediate file saved on disk.</param>
146 /// <param name="creator">ITupleDefinitionCreator to use when reconstituting the intermediate.</param>
147 /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
148 /// <returns>Returns the loaded intermediate.</returns>
141 - public static Intermediate Load(Stream stream, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
149 + public static Intermediate Load(string path, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
150 {
143 - return Load(stream, "<unknown>", creator, suppressVersionCheck);
151 + using (var stream = File.OpenRead(path))
152 + {
153 + var uri = new Uri(Path.GetFullPath(path));
154 +
155 + return Intermediate.Load(stream, uri, creator, suppressVersionCheck);
156 + }
157 }
158
159 /// <summary>
@@ -206,11 +219,11 @@ namespace WixToolset.Data
219 /// Loads an intermediate from a path on disk.
220 /// </summary>
221 /// <param name="stream">Stream to intermediate file.</param>
209 - /// <param name="path">Path name of intermediate file.</param>
222 + /// <param name="baseUri">Path name of intermediate file.</param>
223 /// <param name="creator">ITupleDefinitionCreator to use when reconstituting the intermediate.</param>
224 /// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
225 /// <returns>Returns the loaded intermediate.</returns>
213 - internal static Intermediate Load(Stream stream, string path, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
226 + internal static Intermediate Load(Stream stream, Uri baseUri, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
227 {
228 JsonObject jsonObject;
229
@@ -218,7 +231,7 @@ namespace WixToolset.Data
231 {
232 if (FileFormat.WixIR != fs.FileFormat)
233 {
221 - throw new WixUnexpectedFileFormatException(path, FileFormat.WixIR, fs.FileFormat);
234 + throw new WixUnexpectedFileFormatException(baseUri.LocalPath, FileFormat.WixIR, fs.FileFormat);
235 }
236
237 var json = fs.GetData();
@@ -231,7 +244,7 @@ namespace WixToolset.Data
244
245 if (!Version.TryParse(versionJson, out var version) || !Intermediate.CurrentVersion.Equals(version))
246 {
234 - throw new WixException(WixDataErrors.VersionMismatch(SourceLineNumber.CreateFromUri(path), "intermediate", versionJson, Intermediate.CurrentVersion.ToString()));
247 + throw new WixException(WixDataErrors.VersionMismatch(SourceLineNumber.CreateFromUri(baseUri.AbsoluteUri), "intermediate", versionJson, Intermediate.CurrentVersion.ToString()));
248 }
249 }
250
@@ -253,7 +266,7 @@ namespace WixToolset.Data
266 var sectionsJson = jsonObject.GetValueOrDefault<JsonArray>("sections");
267 foreach (JsonObject sectionJson in sectionsJson)
268 {
256 - var section = IntermediateSection.Deserialize(creator, sectionJson);
269 + var section = IntermediateSection.Deserialize(creator, baseUri, sectionJson);
270 sections.Add(section);
271 }
272
src/WixToolset.Data/IntermediateField.cs
+3 -2
@@ -2,6 +2,7 @@
2
3 namespace WixToolset.Data
4 {
5 + using System;
6 using System.Diagnostics;
7 using SimpleJson;
8
@@ -50,13 +51,13 @@ namespace WixToolset.Data
51 return field.AsString();
52 }
53
53 - internal static IntermediateField Deserialize(IntermediateFieldDefinition definition, JsonObject jsonObject)
54 + internal static IntermediateField Deserialize(IntermediateFieldDefinition definition, Uri baseUri, JsonObject jsonObject)
55 {
56 var field = new IntermediateField(definition);
57
58 if (jsonObject != null)
59 {
59 - field.Value = IntermediateFieldValue.Deserialize(jsonObject);
60 + field.Value = IntermediateFieldValue.Deserialize(jsonObject, baseUri, definition.Type);
61 }
62
63 return field;
src/WixToolset.Data/IntermediateFieldDefinition.cs
+1
@@ -7,6 +7,7 @@ namespace WixToolset.Data
7 String,
8 Bool,
9 Number,
10 + LargeNumber,
11 Path,
12 }
13
src/WixToolset.Data/IntermediateFieldExtensions.cs
+34 -19
@@ -21,26 +21,15 @@ namespace WixToolset.Data
21 {
22 // Null is always allowed.
23 }
24 - else if (field.Type == IntermediateFieldType.Bool && !(value is bool))
24 + else if (field.Type == IntermediateFieldType.String && !(value is string))
25 {
26 if (value is int)
27 {
28 - data = ((int)value) != 0;
28 + data = value.ToString();
29 }
30 - else if (value is string str)
30 + else if (value is bool b)
31 {
32 - if (str.Equals("yes", StringComparison.OrdinalIgnoreCase) || str.Equals("true", StringComparison.OrdinalIgnoreCase))
33 - {
34 - data = true;
35 - }
36 - else if (str.Equals("no", StringComparison.OrdinalIgnoreCase) || str.Equals("false", StringComparison.OrdinalIgnoreCase))
37 - {
38 - data = false;
39 - }
40 - else
41 - {
42 - throw new ArgumentException(nameof(value));
43 - }
32 + data = b ? "true" : "false";
33 }
34 else
35 {
@@ -58,15 +47,26 @@ namespace WixToolset.Data
47 throw new ArgumentException(nameof(value));
48 }
49 }
61 - else if (field.Type == IntermediateFieldType.String && !(value is string))
50 + else if (field.Type == IntermediateFieldType.Bool && !(value is bool))
51 {
52 if (value is int)
53 {
65 - data = value.ToString();
54 + data = ((int)value) != 0;
55 }
67 - else if (value is bool b)
56 + else if (value is string str)
57 {
69 - data = b ? "true" : "false";
58 + if (str.Equals("yes", StringComparison.OrdinalIgnoreCase) || str.Equals("true", StringComparison.OrdinalIgnoreCase))
59 + {
60 + data = true;
61 + }
62 + else if (str.Equals("no", StringComparison.OrdinalIgnoreCase) || str.Equals("false", StringComparison.OrdinalIgnoreCase))
63 + {
64 + data = false;
65 + }
66 + else
67 + {
68 + throw new ArgumentException(nameof(value));
69 + }
70 }
71 else
72 {
@@ -84,6 +84,21 @@ namespace WixToolset.Data
84 throw new ArgumentException(nameof(value));
85 }
86 }
87 + else if (field.Type == IntermediateFieldType.LargeNumber && !(value is long))
88 + {
89 + if (value is string str && Int64.TryParse(str, out var number))
90 + {
91 + data = number;
92 + }
93 + else if (value is int i)
94 + {
95 + data = (long)i;
96 + }
97 + else
98 + {
99 + throw new ArgumentException(nameof(value));
100 + }
101 + }
102
103 field.Value = new IntermediateFieldValue
104 {
src/WixToolset.Data/IntermediateFieldValue.cs
+14 -13
@@ -45,7 +45,7 @@ namespace WixToolset.Data
45 return value.AsString();
46 }
47
48 - internal static IntermediateFieldValue Deserialize(JsonObject jsonObject)
48 + internal static IntermediateFieldValue Deserialize(JsonObject jsonObject, Uri baseUri, IntermediateFieldType type)
49 {
50 var context = jsonObject.GetValueOrDefault<string>("context");
51 if (!jsonObject.TryGetValue("data", out var data))
@@ -55,26 +55,30 @@ namespace WixToolset.Data
55
56 var value = data;
57
58 - if (data is JsonObject jsonData)
58 + if (data is string)
59 {
60 - Uri baseUri = null;
61 -
62 - if (jsonData.TryGetValue("baseUri", out var baseUriValue) && baseUriValue is string)
60 + }
61 + else if (data is long)
62 + {
63 + if (type == IntermediateFieldType.Number)
64 {
64 - baseUri = new Uri((string)baseUriValue);
65 + value = Convert.ToInt32(data);
66 }
67 + }
68 + else if (data is JsonObject jsonData)
69 + {
70 jsonData.TryGetValue("embeddedIndex", out var embeddedIndex);
71
72 value = new IntermediateFieldPathValue
73 {
70 - BaseUri = baseUri,
71 - EmbeddedFileIndex = (int?)embeddedIndex,
74 + BaseUri = (embeddedIndex == null) ? null : baseUri,
75 + EmbeddedFileIndex = (embeddedIndex == null) ? null : (int?)Convert.ToInt32(embeddedIndex),
76 Path = jsonData.GetValueOrDefault<string>("path"),
77 };
78 }
79
80 var previousValueJson = jsonObject.GetValueOrDefault<JsonObject>("prev");
77 - var previousValue = (previousValueJson == null) ? null : IntermediateFieldValue.Deserialize(previousValueJson);
81 + var previousValue = (previousValueJson == null) ? null : IntermediateFieldValue.Deserialize(previousValueJson, baseUri, type);
82
83 return new IntermediateFieldValue
84 {
@@ -97,10 +101,7 @@ namespace WixToolset.Data
101 {
102 var jsonData = new JsonObject();
103
100 - if (pathField.BaseUri != null)
101 - {
102 - jsonData.Add("baseUri", pathField.BaseUri.AbsoluteUri);
103 - }
104 + // pathField.BaseUri is set during load, not saved.
105
106 if (pathField.EmbeddedFileIndex.HasValue)
107 {
src/WixToolset.Data/IntermediateSection.cs
+2 -2
@@ -61,7 +61,7 @@ namespace WixToolset.Data
61 /// <summary>
62 /// Parse a section from the JSON data.
63 /// </summary>
64 - internal static IntermediateSection Deserialize(ITupleDefinitionCreator creator, JsonObject jsonObject)
64 + internal static IntermediateSection Deserialize(ITupleDefinitionCreator creator, Uri baseUri, JsonObject jsonObject)
65 {
66 var codepage = jsonObject.GetValueOrDefault("codepage", 0);
67 var id = jsonObject.GetValueOrDefault<string>("id");
@@ -83,7 +83,7 @@ namespace WixToolset.Data
83
84 foreach (JsonObject tupleJson in tuplesJson)
85 {
86 - var tuple = IntermediateTuple.Deserialize(creator, tupleJson);
86 + var tuple = IntermediateTuple.Deserialize(creator, baseUri, tupleJson);
87 section.Tuples.Add(tuple);
88 }
89
src/WixToolset.Data/IntermediateTuple.cs
+3 -2
@@ -2,6 +2,7 @@
2
3 namespace WixToolset.Data
4 {
5 + using System;
6 using SimpleJson;
7
8 public class IntermediateTuple
@@ -28,7 +29,7 @@ namespace WixToolset.Data
29
30 public IntermediateField this[int index] => this.Fields[index];
31
31 - internal static IntermediateTuple Deserialize(ITupleDefinitionCreator creator, JsonObject jsonObject)
32 + internal static IntermediateTuple Deserialize(ITupleDefinitionCreator creator, Uri baseUri, JsonObject jsonObject)
33 {
34 var definitionName = jsonObject.GetValueOrDefault<string>("type");
35 var idJson = jsonObject.GetValueOrDefault<JsonObject>("id");
@@ -45,7 +46,7 @@ namespace WixToolset.Data
46 {
47 if (tuple.Fields.Length > i && fieldsJson[i] is JsonObject fieldJson)
48 {
48 - tuple.Fields[i] = IntermediateField.Deserialize(tuple.Definition.FieldDefinitions[i], fieldJson);
49 + tuple.Fields[i] = IntermediateField.Deserialize(tuple.Definition.FieldDefinitions[i], baseUri, fieldJson);
50 }
51 }
52
src/WixToolset.Data/SourceLineNumber.cs
+1 -1
@@ -146,7 +146,7 @@ namespace WixToolset.Data
146 }
147
148 // make the local path look like a normal local path
149 - string localPath = new Uri(uri).LocalPath;
149 + var localPath = new Uri(uri).LocalPath;
150 localPath = localPath.TrimStart(Path.AltDirectorySeparatorChar).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
151
152 return new SourceLineNumber(localPath);
src/test/WixToolsetTest.Data/SerializeFixture.cs new
+43
@@ -0,0 +1,43 @@
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 WixToolsetTest.Data
4 +{
5 + using System;
6 + using System.IO;
7 + using System.Linq;
8 + using WixToolset.Data;
9 + using WixToolset.Data.Tuples;
10 + using Xunit;
11 +
12 + public class SerializeFixture
13 + {
14 + [Fact]
15 + public void CanSaveAndLoadIntermediate()
16 + {
17 + var sln = new SourceLineNumber("test.wxs", 1);
18 +
19 + var section = new IntermediateSection("test", SectionType.Product, 65001);
20 +
21 + section.Tuples.Add(new ComponentTuple(sln, new Identifier("TestComponent", AccessModifier.Public))
22 + {
23 + ComponentId = new Guid(1, 0, 0, new byte[8]).ToString("B"),
24 + Directory_ = "TestFolder",
25 + Attributes = 2,
26 + });
27 +
28 + var intermediate = new Intermediate("TestIntermediate", new[] { section }, null, null);
29 +
30 + var path = Path.GetTempFileName();
31 + intermediate.Save(path);
32 +
33 + var loaded = Intermediate.Load(path);
34 +
35 + var tuple = (ComponentTuple)loaded.Sections.Single().Tuples.Single();
36 +
37 + Assert.Equal("TestComponent", tuple.Id.Id);
38 + Assert.Equal(AccessModifier.Public, tuple.Id.Access);
39 + Assert.Equal("TestFolder", tuple.Directory_);
40 + Assert.Equal(2, tuple.Attributes);
41 + }
42 + }
43 +}