aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/Converter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/Converter.cs')
-rw-r--r--src/WixToolset.Core/Converter.cs614
1 files changed, 614 insertions, 0 deletions
diff --git a/src/WixToolset.Core/Converter.cs b/src/WixToolset.Core/Converter.cs
new file mode 100644
index 00000000..6ae2f984
--- /dev/null
+++ b/src/WixToolset.Core/Converter.cs
@@ -0,0 +1,614 @@
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
3namespace WixToolset
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 using System.IO;
9 using System.Linq;
10 using System.Xml;
11 using System.Xml.Linq;
12 using WixToolset.Data;
13
14 /// <summary>
15 /// WiX source code converter.
16 /// </summary>
17 public class Converter
18 {
19 private const string XDocumentNewLine = "\n"; // XDocument normlizes "\r\n" to just "\n".
20 private static readonly XNamespace WixNamespace = "http://wixtoolset.org/schemas/v4/wxs";
21
22 private static readonly XName FileElementName = WixNamespace + "File";
23 private static readonly XName ExePackageElementName = WixNamespace + "ExePackage";
24 private static readonly XName MsiPackageElementName = WixNamespace + "MsiPackage";
25 private static readonly XName MspPackageElementName = WixNamespace + "MspPackage";
26 private static readonly XName MsuPackageElementName = WixNamespace + "MsuPackage";
27 private static readonly XName PayloadElementName = WixNamespace + "Payload";
28 private static readonly XName WixElementWithoutNamespaceName = XNamespace.None + "Wix";
29
30 private static readonly Dictionary<string, XNamespace> OldToNewNamespaceMapping = new Dictionary<string, XNamespace>()
31 {
32 { "http://schemas.microsoft.com/wix/BalExtension", "http://wixtoolset.org/schemas/v4/wxs/bal" },
33 { "http://schemas.microsoft.com/wix/ComPlusExtension", "http://wixtoolset.org/schemas/v4/wxs/complus" },
34 { "http://schemas.microsoft.com/wix/DependencyExtension", "http://wixtoolset.org/schemas/v4/wxs/dependency" },
35 { "http://schemas.microsoft.com/wix/DifxAppExtension", "http://wixtoolset.org/schemas/v4/wxs/difxapp" },
36 { "http://schemas.microsoft.com/wix/FirewallExtension", "http://wixtoolset.org/schemas/v4/wxs/firewall" },
37 { "http://schemas.microsoft.com/wix/GamingExtension", "http://wixtoolset.org/schemas/v4/wxs/gaming" },
38 { "http://schemas.microsoft.com/wix/IIsExtension", "http://wixtoolset.org/schemas/v4/wxs/iis" },
39 { "http://schemas.microsoft.com/wix/MsmqExtension", "http://wixtoolset.org/schemas/v4/wxs/msmq" },
40 { "http://schemas.microsoft.com/wix/NetFxExtension", "http://wixtoolset.org/schemas/v4/wxs/netfx" },
41 { "http://schemas.microsoft.com/wix/PSExtension", "http://wixtoolset.org/schemas/v4/wxs/powershell" },
42 { "http://schemas.microsoft.com/wix/SqlExtension", "http://wixtoolset.org/schemas/v4/wxs/sql" },
43 { "http://schemas.microsoft.com/wix/TagExtension", "http://wixtoolset.org/schemas/v4/wxs/tag" },
44 { "http://schemas.microsoft.com/wix/UtilExtension", "http://wixtoolset.org/schemas/v4/wxs/util" },
45 { "http://schemas.microsoft.com/wix/VSExtension", "http://wixtoolset.org/schemas/v4/wxs/vs" },
46 { "http://wixtoolset.org/schemas/thmutil/2010", "http://wixtoolset.org/schemas/v4/thmutil" },
47 { "http://schemas.microsoft.com/wix/2009/Lux", "http://wixtoolset.org/schemas/v4/lux" },
48 { "http://schemas.microsoft.com/wix/2006/wi", "http://wixtoolset.org/schemas/v4/wxs" },
49 { "http://schemas.microsoft.com/wix/2006/localization", "http://wixtoolset.org/schemas/v4/wxl" },
50 { "http://schemas.microsoft.com/wix/2006/libraries", "http://wixtoolset.org/schemas/v4/wixlib" },
51 { "http://schemas.microsoft.com/wix/2006/objects", "http://wixtoolset.org/schemas/v4/wixobj" },
52 { "http://schemas.microsoft.com/wix/2006/outputs", "http://wixtoolset.org/schemas/v4/wixout" },
53 { "http://schemas.microsoft.com/wix/2007/pdbs", "http://wixtoolset.org/schemas/v4/wixpdb" },
54 { "http://schemas.microsoft.com/wix/2003/04/actions", "http://wixtoolset.org/schemas/v4/wi/actions" },
55 { "http://schemas.microsoft.com/wix/2006/tables", "http://wixtoolset.org/schemas/v4/wi/tables" },
56 { "http://schemas.microsoft.com/wix/2006/WixUnit", "http://wixtoolset.org/schemas/v4/wixunit" },
57 };
58
59 private Dictionary<XName, Action<XElement>> ConvertElementMapping;
60
61 /// <summary>
62 /// Instantiate a new Converter class.
63 /// </summary>
64 /// <param name="indentationAmount">Indentation value to use when validating leading whitespace.</param>
65 /// <param name="errorsAsWarnings">Test errors to display as warnings.</param>
66 /// <param name="ignoreErrors">Test errors to ignore.</param>
67 public Converter(int indentationAmount, IEnumerable<string> errorsAsWarnings = null, IEnumerable<string> ignoreErrors = null)
68 {
69 this.ConvertElementMapping = new Dictionary<XName, Action<XElement>>()
70 {
71 { FileElementName, this.ConvertFileElement },
72 { ExePackageElementName, this.ConvertSuppressSignatureValidation },
73 { MsiPackageElementName, this.ConvertSuppressSignatureValidation },
74 { MspPackageElementName, this.ConvertSuppressSignatureValidation },
75 { MsuPackageElementName, this.ConvertSuppressSignatureValidation },
76 { PayloadElementName, this.ConvertSuppressSignatureValidation },
77 { WixElementWithoutNamespaceName, this.ConvertWixElementWithoutNamespace },
78 };
79
80 this.IndentationAmount = indentationAmount;
81
82 this.ErrorsAsWarnings = new HashSet<ConverterTestType>(this.YieldConverterTypes(errorsAsWarnings));
83
84 this.IgnoreErrors = new HashSet<ConverterTestType>(this.YieldConverterTypes(ignoreErrors));
85 }
86
87 private int Errors { get; set; }
88
89 private HashSet<ConverterTestType> ErrorsAsWarnings { get; set; }
90
91 private HashSet<ConverterTestType> IgnoreErrors { get; set; }
92
93 private int IndentationAmount { get; set; }
94
95 private string SourceFile { get; set; }
96
97 /// <summary>
98 /// Convert a file.
99 /// </summary>
100 /// <param name="sourceFile">The file to convert.</param>
101 /// <param name="saveConvertedFile">Option to save the converted errors that are found.</param>
102 /// <returns>The number of errors found.</returns>
103 public int ConvertFile(string sourceFile, bool saveConvertedFile)
104 {
105 XDocument document;
106
107 // Set the instance info.
108 this.Errors = 0;
109 this.SourceFile = sourceFile;
110
111 try
112 {
113 document = XDocument.Load(this.SourceFile, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo);
114 }
115 catch (XmlException e)
116 {
117 this.OnError(ConverterTestType.XmlException, (XObject)null, "The xml is invalid. Detail: '{0}'", e.Message);
118
119 return this.Errors;
120 }
121
122 this.ConvertDocument(document);
123
124 // Fix errors if requested and necessary.
125 if (saveConvertedFile && 0 < this.Errors)
126 {
127 try
128 {
129 using (StreamWriter writer = File.CreateText(this.SourceFile))
130 {
131 document.Save(writer, SaveOptions.DisableFormatting | SaveOptions.OmitDuplicateNamespaces);
132 }
133 }
134 catch (UnauthorizedAccessException)
135 {
136 this.OnError(ConverterTestType.UnauthorizedAccessException, (XObject)null, "Could not write to file.");
137 }
138 }
139
140 return this.Errors;
141 }
142
143 /// <summary>
144 /// Convert a document.
145 /// </summary>
146 /// <param name="document">The document to convert.</param>
147 /// <returns>The number of errors found.</returns>
148 public int ConvertDocument(XDocument document)
149 {
150 XDeclaration declaration = document.Declaration;
151
152 // Convert the declaration.
153 if (null != declaration)
154 {
155 if (!String.Equals("utf-8", declaration.Encoding, StringComparison.OrdinalIgnoreCase))
156 {
157 if (this.OnError(ConverterTestType.DeclarationEncodingWrong, document.Root, "The XML declaration encoding is not properly set to 'utf-8'."))
158 {
159 declaration.Encoding = "utf-8";
160 }
161 }
162 }
163 else // missing declaration
164 {
165 if (this.OnError(ConverterTestType.DeclarationMissing, (XNode)null, "This file is missing an XML declaration on the first line."))
166 {
167 document.Declaration = new XDeclaration("1.0", "utf-8", null);
168 document.Root.AddBeforeSelf(new XText(XDocumentNewLine));
169 }
170 }
171
172 // Start converting the nodes at the top.
173 this.ConvertNode(document.Root, 0);
174
175 return this.Errors;
176 }
177
178 /// <summary>
179 /// Convert a single xml node.
180 /// </summary>
181 /// <param name="node">The node to convert.</param>
182 /// <param name="level">The depth level of the node.</param>
183 /// <returns>The converted node.</returns>
184 private void ConvertNode(XNode node, int level)
185 {
186 // Convert this node's whitespace.
187 if ((XmlNodeType.Comment == node.NodeType && 0 > ((XComment)node).Value.IndexOf(XDocumentNewLine, StringComparison.Ordinal)) ||
188 XmlNodeType.CDATA == node.NodeType || XmlNodeType.Element == node.NodeType || XmlNodeType.ProcessingInstruction == node.NodeType)
189 {
190 this.ConvertWhitespace(node, level);
191 }
192
193 // Convert this node if it is an element.
194 XElement element = node as XElement;
195
196 if (null != element)
197 {
198 this.ConvertElement(element);
199
200 // Convert all children of this element.
201 IEnumerable<XNode> children = element.Nodes().ToList();
202
203 foreach (XNode child in children)
204 {
205 this.ConvertNode(child, level + 1);
206 }
207 }
208 }
209
210 private void ConvertElement(XElement element)
211 {
212 // Gather any deprecated namespaces, then update this element tree based on those deprecations.
213 Dictionary<XNamespace, XNamespace> deprecatedToUpdatedNamespaces = new Dictionary<XNamespace, XNamespace>();
214
215 foreach (XAttribute declaration in element.Attributes().Where(a => a.IsNamespaceDeclaration))
216 {
217 XNamespace ns;
218
219 if (Converter.OldToNewNamespaceMapping.TryGetValue(declaration.Value, out ns))
220 {
221 if (this.OnError(ConverterTestType.XmlnsValueWrong, declaration, "The namespace '{0}' is out of date. It must be '{1}'.", declaration.Value, ns.NamespaceName))
222 {
223 deprecatedToUpdatedNamespaces.Add(declaration.Value, ns);
224 }
225 }
226 }
227
228 if (deprecatedToUpdatedNamespaces.Any())
229 {
230 Converter.UpdateElementsWithDeprecatedNamespaces(element.DescendantsAndSelf(), deprecatedToUpdatedNamespaces);
231 }
232
233 // Convert the node in much greater detail.
234 Action<XElement> convert;
235
236 if (this.ConvertElementMapping.TryGetValue(element.Name, out convert))
237 {
238 convert(element);
239 }
240 }
241
242 private void ConvertFileElement(XElement element)
243 {
244 if (null == element.Attribute("Id"))
245 {
246 XAttribute attribute = element.Attribute("Name");
247
248 if (null == attribute)
249 {
250 attribute = element.Attribute("Source");
251 }
252
253 if (null != attribute)
254 {
255 string name = Path.GetFileName(attribute.Value);
256
257 if (this.OnError(ConverterTestType.AssignAnonymousFileId, element, "The file id is being updated to '{0}' to ensure it remains the same as the default", name))
258 {
259 IEnumerable<XAttribute> attributes = element.Attributes().ToList();
260 element.RemoveAttributes();
261 element.Add(new XAttribute("Id", Common.GetIdentifierFromName(name)));
262 element.Add(attributes);
263 }
264 }
265 }
266 }
267
268 private void ConvertSuppressSignatureValidation(XElement element)
269 {
270 XAttribute suppressSignatureValidation = element.Attribute("SuppressSignatureValidation");
271
272 if (null != suppressSignatureValidation)
273 {
274 if (this.OnError(ConverterTestType.SuppressSignatureValidationDeprecated, element, "The chain package element contains deprecated '{0}' attribute. Use the 'EnableSignatureValidation' instead.", suppressSignatureValidation))
275 {
276 if ("no" == suppressSignatureValidation.Value)
277 {
278 element.Add(new XAttribute("EnableSignatureValidation", "yes"));
279 }
280 }
281
282 suppressSignatureValidation.Remove();
283 }
284 }
285
286 /// <summary>
287 /// Converts a Wix element.
288 /// </summary>
289 /// <param name="element">The Wix element to convert.</param>
290 /// <returns>The converted element.</returns>
291 private void ConvertWixElementWithoutNamespace(XElement element)
292 {
293 if (this.OnError(ConverterTestType.XmlnsMissing, element, "The xmlns attribute is missing. It must be present with a value of '{0}'.", WixNamespace.NamespaceName))
294 {
295 element.Name = WixNamespace.GetName(element.Name.LocalName);
296
297 element.Add(new XAttribute("xmlns", WixNamespace.NamespaceName)); // set the default namespace.
298
299 foreach (XElement elementWithoutNamespace in element.Elements().Where(e => XNamespace.None == e.Name.Namespace))
300 {
301 elementWithoutNamespace.Name = WixNamespace.GetName(elementWithoutNamespace.Name.LocalName);
302 }
303 }
304 }
305
306 /// <summary>
307 /// Convert the whitespace adjacent to a node.
308 /// </summary>
309 /// <param name="node">The node to convert.</param>
310 /// <param name="level">The depth level of the node.</param>
311 private void ConvertWhitespace(XNode node, int level)
312 {
313 // Fix the whitespace before this node.
314 XText whitespace = node.PreviousNode as XText;
315
316 if (null != whitespace)
317 {
318 if (XmlNodeType.CDATA == node.NodeType)
319 {
320 if (this.OnError(ConverterTestType.WhitespacePrecedingCDATAWrong, node, "There should be no whitespace preceding a CDATA node."))
321 {
322 whitespace.Remove();
323 }
324 }
325 else
326 {
327 if (!Converter.IsLegalWhitespace(this.IndentationAmount, level, whitespace.Value))
328 {
329 if (this.OnError(ConverterTestType.WhitespacePrecedingNodeWrong, node, "The whitespace preceding this node is incorrect."))
330 {
331 Converter.FixWhitespace(this.IndentationAmount, level, whitespace);
332 }
333 }
334 }
335 }
336
337 // Fix the whitespace after CDATA nodes.
338 XCData cdata = node as XCData;
339
340 if (null != cdata)
341 {
342 whitespace = cdata.NextNode as XText;
343
344 if (null != whitespace)
345 {
346 if (this.OnError(ConverterTestType.WhitespaceFollowingCDATAWrong, node, "There should be no whitespace following a CDATA node."))
347 {
348 whitespace.Remove();
349 }
350 }
351 }
352 else
353 {
354 // Fix the whitespace inside and after this node (except for Error which may contain just whitespace).
355 XElement element = node as XElement;
356
357 if (null != element && "Error" != element.Name.LocalName)
358 {
359 if (!element.HasElements && !element.IsEmpty && String.IsNullOrEmpty(element.Value.Trim()))
360 {
361 if (this.OnError(ConverterTestType.NotEmptyElement, element, "This should be an empty element since it contains nothing but whitespace."))
362 {
363 element.RemoveNodes();
364 }
365 }
366
367 whitespace = node.NextNode as XText;
368
369 if (null != whitespace)
370 {
371 if (!Converter.IsLegalWhitespace(this.IndentationAmount, level - 1, whitespace.Value))
372 {
373 if (this.OnError(ConverterTestType.WhitespacePrecedingEndElementWrong, whitespace, "The whitespace preceding this end element is incorrect."))
374 {
375 Converter.FixWhitespace(this.IndentationAmount, level - 1, whitespace);
376 }
377 }
378 }
379 }
380 }
381 }
382
383 private IEnumerable<ConverterTestType> YieldConverterTypes(IEnumerable<string> types)
384 {
385 if (null != types)
386 {
387 foreach (string type in types)
388 {
389 ConverterTestType itt;
390
391 if (Enum.TryParse<ConverterTestType>(type, true, out itt))
392 {
393 yield return itt;
394 }
395 else // not a known ConverterTestType
396 {
397 this.OnError(ConverterTestType.ConverterTestTypeUnknown, (XObject)null, "Unknown error type: '{0}'.", type);
398 }
399 }
400 }
401 }
402
403 private static void UpdateElementsWithDeprecatedNamespaces(IEnumerable<XElement> elements, Dictionary<XNamespace, XNamespace> deprecatedToUpdatedNamespaces)
404 {
405 foreach (XElement element in elements)
406 {
407 XNamespace ns;
408
409 if (deprecatedToUpdatedNamespaces.TryGetValue(element.Name.Namespace, out ns))
410 {
411 element.Name = ns.GetName(element.Name.LocalName);
412 }
413
414 // Remove all the attributes and add them back to with their namespace updated (as necessary).
415 IEnumerable<XAttribute> attributes = element.Attributes().ToList();
416 element.RemoveAttributes();
417
418 foreach (XAttribute attribute in attributes)
419 {
420 XAttribute convertedAttribute = attribute;
421
422 if (attribute.IsNamespaceDeclaration)
423 {
424 if (deprecatedToUpdatedNamespaces.TryGetValue(attribute.Value, out ns))
425 {
426 convertedAttribute = ("xmlns" == attribute.Name.LocalName) ? new XAttribute(attribute.Name.LocalName, ns.NamespaceName) : new XAttribute(XNamespace.Xmlns + attribute.Name.LocalName, ns.NamespaceName);
427 }
428 }
429 else if (deprecatedToUpdatedNamespaces.TryGetValue(attribute.Name.Namespace, out ns))
430 {
431 convertedAttribute = new XAttribute(ns.GetName(attribute.Name.LocalName), attribute.Value);
432 }
433
434 element.Add(convertedAttribute);
435 }
436 }
437 }
438
439 /// <summary>
440 /// Determine if the whitespace preceding a node is appropriate for its depth level.
441 /// </summary>
442 /// <param name="indentationAmount">Indentation value to use when validating leading whitespace.</param>
443 /// <param name="level">The depth level that should match this whitespace.</param>
444 /// <param name="whitespace">The whitespace to validate.</param>
445 /// <returns>true if the whitespace is legal; false otherwise.</returns>
446 private static bool IsLegalWhitespace(int indentationAmount, int level, string whitespace)
447 {
448 // strip off leading newlines; there can be an arbitrary number of these
449 while (whitespace.StartsWith(XDocumentNewLine, StringComparison.Ordinal))
450 {
451 whitespace = whitespace.Substring(XDocumentNewLine.Length);
452 }
453
454 // check the length
455 if (whitespace.Length != level * indentationAmount)
456 {
457 return false;
458 }
459
460 // check the spaces
461 foreach (char character in whitespace)
462 {
463 if (' ' != character)
464 {
465 return false;
466 }
467 }
468
469 return true;
470 }
471
472 /// <summary>
473 /// Fix the whitespace in a Whitespace node.
474 /// </summary>
475 /// <param name="indentationAmount">Indentation value to use when validating leading whitespace.</param>
476 /// <param name="level">The depth level of the desired whitespace.</param>
477 /// <param name="whitespace">The whitespace node to fix.</param>
478 private static void FixWhitespace(int indentationAmount, int level, XText whitespace)
479 {
480 int newLineCount = 0;
481
482 for (int i = 0; i + 1 < whitespace.Value.Length; ++i)
483 {
484 if (XDocumentNewLine == whitespace.Value.Substring(i, 2))
485 {
486 ++i; // skip an extra character
487 ++newLineCount;
488 }
489 }
490
491 if (0 == newLineCount)
492 {
493 newLineCount = 1;
494 }
495
496 // reset the whitespace value
497 whitespace.Value = String.Empty;
498
499 // add the correct number of newlines
500 for (int i = 0; i < newLineCount; ++i)
501 {
502 whitespace.Value = String.Concat(whitespace.Value, XDocumentNewLine);
503 }
504
505 // add the correct number of spaces based on configured indentation amount
506 whitespace.Value = String.Concat(whitespace.Value, new string(' ', level * indentationAmount));
507 }
508
509 /// <summary>
510 /// Output an error message to the console.
511 /// </summary>
512 /// <param name="converterTestType">The type of converter test.</param>
513 /// <param name="node">The node that caused the error.</param>
514 /// <param name="message">Detailed error message.</param>
515 /// <param name="args">Additional formatted string arguments.</param>
516 /// <returns>Returns true indicating that action should be taken on this error, and false if it should be ignored.</returns>
517 private bool OnError(ConverterTestType converterTestType, XObject node, string message, params object[] args)
518 {
519 if (this.IgnoreErrors.Contains(converterTestType)) // ignore the error
520 {
521 return false;
522 }
523
524 // Increase the error count.
525 this.Errors++;
526
527 SourceLineNumber sourceLine = (null == node) ? new SourceLineNumber(this.SourceFile ?? "wixcop.exe") : new SourceLineNumber(this.SourceFile, ((IXmlLineInfo)node).LineNumber);
528 bool warning = this.ErrorsAsWarnings.Contains(converterTestType);
529 string display = String.Format(CultureInfo.CurrentCulture, message, args);
530
531 WixGenericMessageEventArgs ea = new WixGenericMessageEventArgs(sourceLine, (int)converterTestType, warning ? MessageLevel.Warning : MessageLevel.Error, "{0} ({1})", display, converterTestType.ToString());
532
533 Messaging.Instance.OnMessage(ea);
534
535 return true;
536 }
537
538 /// <summary>
539 /// Converter test types. These are used to condition error messages down to warnings.
540 /// </summary>
541 private enum ConverterTestType
542 {
543 /// <summary>
544 /// Internal-only: displayed when a string cannot be converted to an ConverterTestType.
545 /// </summary>
546 ConverterTestTypeUnknown,
547
548 /// <summary>
549 /// Displayed when an XML loading exception has occurred.
550 /// </summary>
551 XmlException,
552
553 /// <summary>
554 /// Displayed when a file cannot be accessed; typically when trying to save back a fixed file.
555 /// </summary>
556 UnauthorizedAccessException,
557
558 /// <summary>
559 /// Displayed when the encoding attribute in the XML declaration is not 'UTF-8'.
560 /// </summary>
561 DeclarationEncodingWrong,
562
563 /// <summary>
564 /// Displayed when the XML declaration is missing from the source file.
565 /// </summary>
566 DeclarationMissing,
567
568 /// <summary>
569 /// Displayed when the whitespace preceding a CDATA node is wrong.
570 /// </summary>
571 WhitespacePrecedingCDATAWrong,
572
573 /// <summary>
574 /// Displayed when the whitespace preceding a node is wrong.
575 /// </summary>
576 WhitespacePrecedingNodeWrong,
577
578 /// <summary>
579 /// Displayed when an element is not empty as it should be.
580 /// </summary>
581 NotEmptyElement,
582
583 /// <summary>
584 /// Displayed when the whitespace following a CDATA node is wrong.
585 /// </summary>
586 WhitespaceFollowingCDATAWrong,
587
588 /// <summary>
589 /// Displayed when the whitespace preceding an end element is wrong.
590 /// </summary>
591 WhitespacePrecedingEndElementWrong,
592
593 /// <summary>
594 /// Displayed when the xmlns attribute is missing from the document element.
595 /// </summary>
596 XmlnsMissing,
597
598 /// <summary>
599 /// Displayed when the xmlns attribute on the document element is wrong.
600 /// </summary>
601 XmlnsValueWrong,
602
603 /// <summary>
604 /// Assign an identifier to a File element when on Id attribute is specified.
605 /// </summary>
606 AssignAnonymousFileId,
607
608 /// <summary>
609 /// SuppressSignatureValidation attribute is deprecated and replaced with EnableSignatureValidation.
610 /// </summary>
611 SuppressSignatureValidationDeprecated,
612 }
613 }
614}