Files
ucan/capability/policy/glob.go
2024-09-16 18:33:36 +02:00

80 lines
1.7 KiB
Go

package policy
// validateGlobPattern ensures the pattern conforms to the spec: only '*' and escaped '\*' are allowed.
func validateGlobPattern(pattern string) bool {
for i := 0; i < len(pattern); i++ {
if pattern[i] == '*' {
continue
}
if pattern[i] == '\\' && i+1 < len(pattern) && pattern[i+1] == '*' {
i++ // skip the escaped '*'
continue
}
if pattern[i] == '\\' && i+1 < len(pattern) {
i++ // skip the escaped character
continue
}
if pattern[i] == '\\' {
return false // invalid escape sequence
}
}
return true
}
// globMatch matches a string against a pattern with '*' wildcards, handling escaped '\*' literals.
func globMatch(pattern, str string) bool {
if !validateGlobPattern(pattern) {
return false
}
var i, j int // i is the index for the pattern, j is the index for the string
for i < len(pattern) && j < len(str) {
switch pattern[i] {
case '*':
// Skip consecutive '*' characters
for i < len(pattern) && pattern[i] == '*' {
i++
}
if i == len(pattern) {
return true
}
// Match the rest of the pattern
for j < len(str) {
if globMatch(pattern[i:], str[j:]) {
return true
}
j++
}
return false
case '\\':
// Handle escaped '*'
i++
if i < len(pattern) && pattern[i] == '*' {
if str[j] != '*' {
return false
}
i++
j++
} else {
if i >= len(pattern) || pattern[i] != str[j] {
return false
}
i++
j++
}
default:
if pattern[i] != str[j] {
return false
}
i++
j++
}
}
// Check for remaining characters in pattern
for i < len(pattern) && pattern[i] == '*' {
i++
}
return i == len(pattern) && j == len(str)
}