diff --git a/src/DemaConsulting.SpdxTool/Commands/FindPackage.cs b/src/DemaConsulting.SpdxTool/Commands/FindPackage.cs index e11ae6e..870014e 100644 --- a/src/DemaConsulting.SpdxTool/Commands/FindPackage.cs +++ b/src/DemaConsulting.SpdxTool/Commands/FindPackage.cs @@ -20,6 +20,7 @@ using DemaConsulting.SpdxModel; using DemaConsulting.SpdxTool.Spdx; +using DemaConsulting.SpdxTool.Utility; using YamlDotNet.Core; using YamlDotNet.RepresentationModel; @@ -216,23 +217,23 @@ public static SpdxPackage FindPackageByCriteria(string spdxFile, IReadOnlyDictio public static bool IsPackageMatch(SpdxPackage package, IReadOnlyDictionary criteria) { // Check the id - if (criteria.TryGetValue("id", out var id) && !package.Id.StartsWith(id)) + if (criteria.TryGetValue("id", out var id) && !Wildcard.IsMatch(package.Id, id)) return false; // Check the name - if (criteria.TryGetValue("name", out var name) && !package.Name.StartsWith(name)) + if (criteria.TryGetValue("name", out var name) && !Wildcard.IsMatch(package.Name, name)) return false; // Check the version - if (criteria.TryGetValue("version", out var version) && (package.Version == null || !package.Version.StartsWith(version))) + if (criteria.TryGetValue("version", out var version) && (package.Version == null || !Wildcard.IsMatch(package.Version, version))) return false; // Check the filename - if (criteria.TryGetValue("filename", out var filename) && (package.FileName == null || !package.FileName.StartsWith(filename))) + if (criteria.TryGetValue("filename", out var filename) && (package.FileName == null || !Wildcard.IsMatch(package.FileName, filename))) return false; // Check the download location - if (criteria.TryGetValue("download", out var download) && !package.DownloadLocation.StartsWith(download)) + if (criteria.TryGetValue("download", out var download) && !Wildcard.IsMatch(package.DownloadLocation, download)) return false; // Package matches all specified criteria diff --git a/src/DemaConsulting.SpdxTool/Utility/Wildcard.cs b/src/DemaConsulting.SpdxTool/Utility/Wildcard.cs new file mode 100644 index 0000000..1b6f996 --- /dev/null +++ b/src/DemaConsulting.SpdxTool/Utility/Wildcard.cs @@ -0,0 +1,56 @@ +// Copyright (c) 2024 DEMA Consulting +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System.Text.RegularExpressions; + +namespace DemaConsulting.SpdxTool.Utility; + +/// +/// Wildcard Match Class +/// +public static class Wildcard +{ + /// + /// Convert a wildcard pattern to a regular expression pattern + /// + /// Wildcard pattern + /// Regular expression pattern + private static string WildCardToRegex(string wildPattern) + { + return "^" + + Regex.Escape(wildPattern).Replace("\\*", ".*").Replace("\\?", ".") + + "$"; + } + + /// + /// Check for a wildcard match + /// + /// Input text + /// Wildcard pattern + /// True if input text matches wildcard + public static bool IsMatch(string input, string pattern) + { + return Regex.IsMatch( + input, + WildCardToRegex(pattern), + RegexOptions.IgnoreCase, + TimeSpan.FromMilliseconds(100)); + } +} \ No newline at end of file diff --git a/test/DemaConsulting.SpdxTool.Tests/TestWildcard.cs b/test/DemaConsulting.SpdxTool.Tests/TestWildcard.cs new file mode 100644 index 0000000..e0b04d3 --- /dev/null +++ b/test/DemaConsulting.SpdxTool.Tests/TestWildcard.cs @@ -0,0 +1,78 @@ +// Copyright (c) 2024 DEMA Consulting +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using DemaConsulting.SpdxTool.Utility; + +namespace DemaConsulting.SpdxTool.Tests; + +/// +/// Test for wildcard pattern matching +/// +[TestClass] +public class TestWildcard +{ + /// + /// Test for exact matching + /// + [TestMethod] + public void Wildcard_Exact() + { + Assert.IsTrue(Wildcard.IsMatch("Hello", "Hello")); + Assert.IsTrue(Wildcard.IsMatch("HELLO", "Hello")); + Assert.IsTrue(Wildcard.IsMatch("hello.WORLD", "Hello.World")); + Assert.IsFalse(Wildcard.IsMatch("Test", "42")); + Assert.IsFalse(Wildcard.IsMatch("Hello_World", "Hello.World")); + Assert.IsFalse(Wildcard.IsMatch("Hello", ".....")); + Assert.IsFalse(Wildcard.IsMatch("_Test", "Test")); + Assert.IsFalse(Wildcard.IsMatch("Test_", "Test")); + } + + /// + /// Test for matching with asterisks + /// + [TestMethod] + public void Wildcard_Asterisks() + { + Assert.IsTrue(Wildcard.IsMatch("Test.This.String", "Test.*.String")); + Assert.IsTrue(Wildcard.IsMatch("Test String", "*Test*")); + Assert.IsTrue(Wildcard.IsMatch("This is a test", "*Test*")); + Assert.IsTrue(Wildcard.IsMatch("This tests for a string", "*Test*")); + Assert.IsTrue(Wildcard.IsMatch("Test", "Test*")); + Assert.IsTrue(Wildcard.IsMatch("Testing", "Test*")); + Assert.IsTrue(Wildcard.IsMatch("Test", "*Test")); + Assert.IsTrue(Wildcard.IsMatch("Some Test", "*Test")); + Assert.IsFalse(Wildcard.IsMatch("Test", "*i*")); + Assert.IsFalse(Wildcard.IsMatch("Test", "*s")); + Assert.IsFalse(Wildcard.IsMatch("Test", "e*")); + } + + /// + /// Test for matching with question-marks + /// + [TestMethod] + public void Wildcard_QuestionMark() + { + Assert.IsTrue(Wildcard.IsMatch("Test", "Te?t")); + Assert.IsTrue(Wildcard.IsMatch("Test", "????")); + Assert.IsFalse(Wildcard.IsMatch("Test", "?Test")); + Assert.IsFalse(Wildcard.IsMatch("Test", "Test?")); + Assert.IsFalse(Wildcard.IsMatch("Test", "?")); + } +} \ No newline at end of file