diff --git a/AppInspector.RulesEngine/AbstractRuleSet.cs b/AppInspector.RulesEngine/AbstractRuleSet.cs index 7d25436..8e234e7 100644 --- a/AppInspector.RulesEngine/AbstractRuleSet.cs +++ b/AppInspector.RulesEngine/AbstractRuleSet.cs @@ -79,7 +79,7 @@ namespace Microsoft.ApplicationInspector.RulesEngine var modifiers = pattern.Modifiers?.ToList() ?? new List(); if (pattern.PatternType is PatternType.String or PatternType.Substring) { - clauses.Add(new OatSubstringIndexClause(scopes, useWordBoundaries: pattern.PatternType == PatternType.String, xPath: pattern.XPath, jsonPath:pattern.JsonPath) + clauses.Add(new OatSubstringIndexClause(scopes, useWordBoundaries: pattern.PatternType == PatternType.String, xPaths: pattern.XPaths, jsonPaths:pattern.JsonPaths) { Label = clauseNumber.ToString(CultureInfo.InvariantCulture),//important to pattern index identification Data = new List() { pattern.Pattern }, @@ -95,7 +95,7 @@ namespace Microsoft.ApplicationInspector.RulesEngine } else if (pattern.PatternType == PatternType.Regex) { - clauses.Add(new OatRegexWithIndexClause(scopes, null, pattern.XPath, pattern.JsonPath) + clauses.Add(new OatRegexWithIndexClause(scopes, null, pattern.XPaths, pattern.JsonPaths) { Label = clauseNumber.ToString(CultureInfo.InvariantCulture),//important to pattern index identification Data = new List() { pattern.Pattern }, @@ -112,7 +112,7 @@ namespace Microsoft.ApplicationInspector.RulesEngine } else if (pattern.PatternType == PatternType.RegexWord) { - clauses.Add(new OatRegexWithIndexClause(scopes, null, pattern.XPath, pattern.JsonPath) + clauses.Add(new OatRegexWithIndexClause(scopes, null, pattern.XPaths, pattern.JsonPaths) { Label = clauseNumber.ToString(CultureInfo.InvariantCulture),//important to pattern index identification Data = new List() { $"\\b({pattern.Pattern})\\b" }, diff --git a/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexClause.cs b/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexClause.cs index d17cf54..d7ac43f 100644 --- a/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexClause.cs +++ b/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexClause.cs @@ -6,17 +6,17 @@ namespace Microsoft.ApplicationInspector.RulesEngine.OatExtensions { public class OatRegexWithIndexClause : Clause { - public OatRegexWithIndexClause(PatternScope[] scopes, string? field = null, string? xPath = null, string? jsonPath = null) : base(Operation.Custom, field) + public OatRegexWithIndexClause(PatternScope[] scopes, string? field = null, string[]? xPaths = null, string[]? jsonPaths = null) : base(Operation.Custom, field) { Scopes = scopes; CustomOperation = "RegexWithIndex"; - XPath = xPath; - JsonPath = jsonPath; + XPaths = xPaths; + JsonPaths = jsonPaths; } - public string? JsonPath { get; } + public string[]? JsonPaths { get; } - public string? XPath { get; } + public string[]? XPaths { get; } public PatternScope[] Scopes { get; } } diff --git a/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexOperation.cs b/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexOperation.cs index a4443bb..18cfc29 100644 --- a/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexOperation.cs +++ b/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexOperation.cs @@ -91,33 +91,39 @@ namespace Microsoft.ApplicationInspector.RulesEngine.OatExtensions { if (StringToRegex(regexString, regexOpts) is { } regex) { - if (src.XPath is not null) + if (src.XPaths is not null) { - var targets = tc.GetStringFromXPath(src.XPath); - foreach (var target in targets) + foreach (var xmlPath in src.XPaths) { - var matches = GetMatches(regex, target.Item1, tc, clause, src.Scopes); - foreach (var match in matches) + var targets = tc.GetStringFromXPath(xmlPath); + foreach (var target in targets) { - match.Item2.Index += target.Item2.Index; - outmatches.Add(match); + var matches = GetMatches(regex, target.Item1, tc, clause, src.Scopes); + foreach (var match in matches) + { + match.Item2.Index += target.Item2.Index; + outmatches.Add(match); + } } } } - if (src.JsonPath is not null) + if (src.JsonPaths is not null) { - var targets = tc.GetStringFromJsonPath(src.JsonPath); - foreach (var target in targets) + foreach (var jsonPath in src.JsonPaths) { - var matches = GetMatches(regex, target.Item1, tc, clause, src.Scopes); - foreach (var match in matches) + var targets = tc.GetStringFromJsonPath(jsonPath); + foreach (var target in targets) { - match.Item2.Index += target.Item2.Index; - outmatches.Add(match); + var matches = GetMatches(regex, target.Item1, tc, clause, src.Scopes); + foreach (var match in matches) + { + match.Item2.Index += target.Item2.Index; + outmatches.Add(match); + } } } } - if (src.JsonPath is null && src.XPath is null) + if (src.JsonPaths is null && src.XPaths is null) { outmatches.AddRange(GetMatches(regex, tc.FullContent, tc, clause, src.Scopes)); } diff --git a/AppInspector.RulesEngine/OatExtensions/OatSubstringIndexClause.cs b/AppInspector.RulesEngine/OatExtensions/OatSubstringIndexClause.cs index 5e8921c..298f3c4 100644 --- a/AppInspector.RulesEngine/OatExtensions/OatSubstringIndexClause.cs +++ b/AppInspector.RulesEngine/OatExtensions/OatSubstringIndexClause.cs @@ -6,18 +6,18 @@ namespace Microsoft.ApplicationInspector.RulesEngine.OatExtensions { public class OatSubstringIndexClause : Clause { - public OatSubstringIndexClause(PatternScope[] scopes, string? field = null, bool useWordBoundaries = false, string? xPath = null, string? jsonPath = null) : base(Operation.Custom, field) + public OatSubstringIndexClause(PatternScope[] scopes, string? field = null, bool useWordBoundaries = false, string[]? xPaths = null, string[]? jsonPaths = null) : base(Operation.Custom, field) { Scopes = scopes; CustomOperation = "SubstringIndex"; UseWordBoundaries = useWordBoundaries; - XPath = xPath; - JsonPath = jsonPath; + XPaths = xPaths; + JsonPaths = jsonPaths; } - public string? JsonPath { get; } + public string[]? JsonPaths { get; } - public string? XPath { get; } + public string[]? XPaths { get; } public PatternScope[] Scopes { get; } diff --git a/AppInspector.RulesEngine/OatExtensions/OatSubstringIndexOperation.cs b/AppInspector.RulesEngine/OatExtensions/OatSubstringIndexOperation.cs index 1f3b428..3ffc7b7 100644 --- a/AppInspector.RulesEngine/OatExtensions/OatSubstringIndexOperation.cs +++ b/AppInspector.RulesEngine/OatExtensions/OatSubstringIndexOperation.cs @@ -63,33 +63,39 @@ namespace Microsoft.ApplicationInspector.RulesEngine.OatExtensions for (int i = 0; i < stringList.Count; i++) { - if (src.XPath is not null) + if (src.XPaths is not null) { - var targets = tc.GetStringFromXPath(src.XPath); - foreach (var target in targets) + foreach (var xmlPath in src.XPaths) { - var matches = GetMatches(target.Item1, stringList[i], comparisonType, tc, src); - foreach (var match in matches) + var targets = tc.GetStringFromXPath(xmlPath); + foreach (var target in targets) { - match.Index += target.Item2.Index; - outmatches.Add((i,match)); + var matches = GetMatches(target.Item1, stringList[i], comparisonType, tc, src); + foreach (var match in matches) + { + match.Index += target.Item2.Index; + outmatches.Add((i,match)); + } } } } - if (src.JsonPath is not null) + if (src.JsonPaths is not null) { - var targets = tc.GetStringFromJsonPath(src.JsonPath); - foreach (var target in targets) + foreach (var jsonPath in src.JsonPaths) { - var matches = GetMatches(target.Item1, stringList[i], comparisonType, tc, src); - foreach (var match in matches) + var targets = tc.GetStringFromJsonPath(jsonPath); + foreach (var target in targets) { - match.Index += target.Item2.Index; - outmatches.Add((i,match)); + var matches = GetMatches(target.Item1, stringList[i], comparisonType, tc, src); + foreach (var match in matches) + { + match.Index += target.Item2.Index; + outmatches.Add((i,match)); + } } } } - if (src.JsonPath is null && src.XPath is null) + if (src.JsonPaths is null && src.XPaths is null) { var matches = GetMatches(tc.FullContent, stringList[i], comparisonType, tc, src); outmatches.AddRange(matches.Select(x => (i, x))); diff --git a/AppInspector.RulesEngine/RulesVerifier.cs b/AppInspector.RulesEngine/RulesVerifier.cs index 781ddc0..f681dd8 100644 --- a/AppInspector.RulesEngine/RulesVerifier.cs +++ b/AppInspector.RulesEngine/RulesVerifier.cs @@ -155,29 +155,35 @@ namespace Microsoft.ApplicationInspector.RulesEngine } } - if (searchPattern.JsonPath is not null) + if (searchPattern.JsonPaths is not null) { - try + foreach (var jsonPath in searchPattern.JsonPaths) { - _ = JsonSelector.Parse(searchPattern.JsonPath); - } - catch (Exception e) - { - _logger?.LogError("The provided JsonPath '{JsonPath}' value was not valid in Rule {Id} : {message}", searchPattern.JsonPath, rule.Id, e.Message); - errors.Add(string.Format("The provided JsonPath '{0}' value was not valid in Rule {1} : {2}", searchPattern.JsonPath, rule.Id, e.Message)); + try + { + _ = JsonSelector.Parse(jsonPath); + } + catch (Exception e) + { + _logger?.LogError("The provided JsonPath '{JsonPath}' value was not valid in Rule {Id} : {message}", searchPattern.JsonPaths, rule.Id, e.Message); + errors.Add(string.Format("The provided JsonPath '{0}' value was not valid in Rule {1} : {2}", searchPattern.JsonPaths, rule.Id, e.Message)); + } } } - if (searchPattern.XPath is not null) + if (searchPattern.XPaths is not null) { - try + foreach (var xpath in searchPattern.XPaths) { - XPathExpression.Compile(searchPattern.XPath); - } - catch (Exception e) - { - _logger?.LogError("The provided XPath '{XPath}' value was not valid in Rule {Id} : {message}", searchPattern.XPath, rule.Id, e.Message); - errors.Add(string.Format("The provided XPath '{0}' value was not valid in Rule {1} : {2}", searchPattern.JsonPath, rule.Id, e.Message)); + try + { + XPathExpression.Compile(xpath); + } + catch (Exception e) + { + _logger?.LogError("The provided XPath '{XPath}' value was not valid in Rule {Id} : {message}", searchPattern.XPaths, rule.Id, e.Message); + errors.Add(string.Format("The provided XPath '{0}' value was not valid in Rule {1} : {2}", searchPattern.JsonPaths, rule.Id, e.Message)); + } } } } diff --git a/AppInspector.RulesEngine/SearchPattern.cs b/AppInspector.RulesEngine/SearchPattern.cs index 5eaa1f8..256d021 100644 --- a/AppInspector.RulesEngine/SearchPattern.cs +++ b/AppInspector.RulesEngine/SearchPattern.cs @@ -48,14 +48,14 @@ namespace Microsoft.ApplicationInspector.RulesEngine /// If set, attempt to parse the file as XML and if that is possible, /// before running the pattern, select down to the XPath provided /// - [JsonProperty(PropertyName ="xpath")] - public string? XPath { get; set; } - + [JsonProperty(PropertyName ="xpaths")] + public string[]? XPaths { get; set; } + /// /// If set, attempt to parse the file as JSON and if that is possible, /// before running the pattern, select down to the JsonPath provided /// - [JsonProperty(PropertyName ="jsonpath")] - public string? JsonPath { get; set; } + [JsonProperty(PropertyName = "jsonpaths")] + public string[]? JsonPaths { get; set; } } } \ No newline at end of file diff --git a/AppInspector.Tests/RuleProcessor/RegexWithIndexTests.cs b/AppInspector.Tests/RuleProcessor/RegexWithIndexTests.cs index 3e392db..d1cc9a2 100644 --- a/AppInspector.Tests/RuleProcessor/RegexWithIndexTests.cs +++ b/AppInspector.Tests/RuleProcessor/RegexWithIndexTests.cs @@ -196,8 +196,8 @@ namespace AppInspector.Tests.RuleProcessor ""scopes"": [ ""code"" ], - ""jsonpath"" : ""$.books[*].title"", - ""xpath"" : ""/bookstore/book/title"" + ""jsonpaths"" : [""$.books[*].title""], + ""xpaths"" : [""/bookstore/book/title""] } ], ""_comment"": """" @@ -221,7 +221,7 @@ namespace AppInspector.Tests.RuleProcessor ""scopes"": [ ""code"" ], - ""jsonpath"" : ""$.books[*].title"" + ""jsonpaths"" : [""$.books[*].title""] } ], ""_comment"": """" @@ -245,7 +245,7 @@ namespace AppInspector.Tests.RuleProcessor ""scopes"": [ ""code"" ], - ""xpath"" : ""/bookstore/book/title"" + ""xpaths"" : [""/bookstore/book/title""] } ], ""_comment"": """" diff --git a/AppInspector.Tests/RuleProcessor/SubstringWithIndexTests.cs b/AppInspector.Tests/RuleProcessor/SubstringWithIndexTests.cs index 7900605..89f8bf4 100644 --- a/AppInspector.Tests/RuleProcessor/SubstringWithIndexTests.cs +++ b/AppInspector.Tests/RuleProcessor/SubstringWithIndexTests.cs @@ -70,8 +70,8 @@ namespace AppInspector.Tests.RuleProcessor ""scopes"": [ ""code"" ], - ""jsonpath"" : ""$.books[*].title"", - ""xpath"" : ""/bookstore/book/title"" + ""jsonpaths"" : [""$.books[*].title""], + ""xpaths"" : [""/bookstore/book/title""] } ], ""_comment"": """" @@ -95,7 +95,7 @@ namespace AppInspector.Tests.RuleProcessor ""scopes"": [ ""code"" ], - ""jsonpath"" : ""$.books[*].title"" + ""jsonpaths"" : [""$.books[*].title""] } ], ""_comment"": """" @@ -119,7 +119,7 @@ namespace AppInspector.Tests.RuleProcessor ""scopes"": [ ""code"" ], - ""xpath"" : ""/bookstore/book/title"" + ""xpaths"" : [""/bookstore/book/title""] } ], ""_comment"": """"