55using System . Collections . Generic ;
66using System . IO ;
77using System . Linq ;
8+ using Microsoft . Sbom . Api . Utils ;
89using Microsoft . Sbom . Common ;
910using Microsoft . Sbom . Common . Config ;
1011using Serilog ;
@@ -23,6 +24,7 @@ public class DownloadedRootPathFilter : IFilter<DownloadedRootPathFilter>
2324
2425 private bool skipValidation ;
2526 private HashSet < string > validPaths ;
27+ private List < string > patterns ;
2628
2729 public DownloadedRootPathFilter (
2830 IConfiguration configuration ,
@@ -37,12 +39,13 @@ public DownloadedRootPathFilter(
3739 }
3840
3941 /// <summary>
40- /// Returns true if filePath is present in root path filters.
42+ /// Returns true if filePath is present in root path filters or matches root path patterns .
4143 ///
4244 /// For example, say filePath is /root/parent1/parent2/child1/child2.txt, then if the root path
4345 /// filters contains /root/parent1/ or /root/parent1/parent2/ in it, this filePath with return true,
4446 /// but if the root path contains /root/parent3/, this filePath will return false.
4547 ///
48+ /// If patterns are specified, the filePath will be matched against glob-style patterns instead.
4649 /// </summary>
4750 /// <param name="filePath">The file path to validate.</param>
4851 public bool IsValid ( string filePath )
@@ -57,6 +60,48 @@ public bool IsValid(string filePath)
5760 return false ;
5861 }
5962
63+ // If patterns are configured, use pattern matching
64+ if ( patterns != null && patterns . Count > 0 )
65+ {
66+ return IsValidWithPatterns ( filePath ) ;
67+ }
68+
69+ // Fall back to legacy path prefix matching
70+ return IsValidWithPathPrefix ( filePath ) ;
71+ }
72+
73+ /// <summary>
74+ /// Validates file path using glob-style patterns.
75+ /// </summary>
76+ /// <param name="filePath">The file path to validate.</param>
77+ /// <returns>True if the path matches any pattern, false otherwise.</returns>
78+ private bool IsValidWithPatterns ( string filePath )
79+ {
80+ var buildDropPath = configuration . BuildDropPath ? . Value ;
81+
82+ foreach ( var pattern in patterns )
83+ {
84+ if ( PathPatternMatcher . IsMatch ( filePath , pattern , buildDropPath ) )
85+ {
86+ return true ;
87+ }
88+ }
89+
90+ return false ;
91+ }
92+
93+ /// <summary>
94+ /// Validates file path using the legacy path prefix approach.
95+ /// </summary>
96+ /// <param name="filePath">The file path to validate.</param>
97+ /// <returns>True if the path starts with any valid path prefix, false otherwise.</returns>
98+ private bool IsValidWithPathPrefix ( string filePath )
99+ {
100+ if ( validPaths == null || validPaths . Count == 0 )
101+ {
102+ return false ;
103+ }
104+
60105 var isValid = false ;
61106 var normalizedPath = new FileInfo ( filePath ) . FullName ;
62107
@@ -69,14 +114,33 @@ public bool IsValid(string filePath)
69114 }
70115
71116 /// <summary>
72- /// Initializes the root path filters list.
117+ /// Initializes the root path filters list or patterns .
73118 /// </summary>
74119 public void Init ( )
75120 {
76121 logger . Verbose ( "Adding root path filter valid paths" ) ;
77122 skipValidation = true ;
78123
79- if ( configuration . RootPathFilter != null && ! string . IsNullOrWhiteSpace ( configuration . RootPathFilter . Value ) )
124+ // Check for new pattern-based configuration first (takes precedence)
125+ if ( configuration . RootPathPatterns != null && ! string . IsNullOrWhiteSpace ( configuration . RootPathPatterns . Value ) )
126+ {
127+ skipValidation = false ;
128+ patterns = new List < string > ( ) ;
129+ var patternStrings = configuration . RootPathPatterns . Value . Split ( ';' ) ;
130+
131+ foreach ( var pattern in patternStrings )
132+ {
133+ var trimmedPattern = pattern . Trim ( ) ;
134+ if ( ! string . IsNullOrEmpty ( trimmedPattern ) )
135+ {
136+ patterns . Add ( trimmedPattern ) ;
137+ logger . Verbose ( $ "Added pattern { trimmedPattern } ") ;
138+ }
139+ }
140+ }
141+
142+ // Fall back to legacy path prefix configuration
143+ else if ( configuration . RootPathFilter != null && ! string . IsNullOrWhiteSpace ( configuration . RootPathFilter . Value ) )
80144 {
81145 skipValidation = false ;
82146 validPaths = new HashSet < string > ( ) ;
0 commit comments