diff --git a/models/auth/oauth2.go b/models/auth/oauth2.go index c5c6e91120f85..a3d28273d254f 100644 --- a/models/auth/oauth2.go +++ b/models/auth/oauth2.go @@ -56,7 +56,7 @@ func (app *OAuth2Application) PrimaryRedirectURI() string { // ContainsRedirectURI checks if redirectURI is allowed for app func (app *OAuth2Application) ContainsRedirectURI(redirectURI string) bool { - return util.IsStringInSlice(redirectURI, app.RedirectURIs, true) + return util.StringMatchesAnyPattern(redirectURI, app.RedirectURIs, true) } // Base32 characters, but lowercased. diff --git a/modules/util/compare.go b/modules/util/compare.go index 49891ef02496e..d7d79d8fb63c8 100644 --- a/modules/util/compare.go +++ b/modules/util/compare.go @@ -5,6 +5,7 @@ package util import ( + "regexp" "sort" "strings" ) @@ -60,6 +61,46 @@ func IsStringInSlice(target string, slice []string, insensitive ...bool) bool { return false } +// StringMatchesPattern checks whether the target string matches the wildcard pattern +func StringMatchesPattern(target, pattern string) bool { + // Compile the wildcards in the pattern to a regular expression + var compiled strings.Builder + for i, segment := range strings.Split(pattern, "*") { + if i > 0 { + compiled.WriteString(".*") + } + + compiled.WriteString(regexp.QuoteMeta(segment)) + } + + // Check whether the target matches the compiled pattern + result, _ := regexp.MatchString(compiled.String(), target) + return result +} + +// StringMatchesAnyPattern sequential searches if target matches any patterns in the slice +func StringMatchesAnyPattern(target string, patterns []string, insensitive ...bool) bool { + caseInsensitive := false + if len(insensitive) != 0 && insensitive[0] { + caseInsensitive = true + target = strings.ToLower(target) + } + + for _, pattern := range patterns { + if caseInsensitive { + if StringMatchesPattern(target, strings.ToLower(pattern)) { + return true + } + } else { + if StringMatchesPattern(target, pattern) { + return true + } + } + } + + return false +} + // IsInt64InSlice sequential searches if int64 exists in slice. func IsInt64InSlice(target int64, slice []int64) bool { for i := 0; i < len(slice); i++ { diff --git a/modules/util/compare_test.go b/modules/util/compare_test.go new file mode 100644 index 0000000000000..807398e75dc76 --- /dev/null +++ b/modules/util/compare_test.go @@ -0,0 +1,28 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package util + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestStringMatchesPattern(t *testing.T) { + // Make sure non-wildcard matching works + assert.True(t, StringMatchesPattern("fubar", "fubar")) + + // Make sure wildcard matching accepts + assert.True(t, StringMatchesPattern("A is not B", "A*B")) + assert.True(t, StringMatchesPattern("A is not B", "A*")) + + // Make sure wildcard matching rejects + assert.False(t, StringMatchesPattern("fubar", "A*B")) + assert.False(t, StringMatchesPattern("A is not b", "A*B")) + + // Make sure regexp specials are escaped + assert.False(t, StringMatchesPattern("A is not B", "[aA]*")) + assert.True(t, StringMatchesPattern("[aA] is not B", "[aA]*")) +}