secure/precis: use toLower instead of case folding Change default case folding to the Unicode toLower operation as specified in draft-ietf-precis-7700bis-03 and draft-ietf-precis-7613bis-03. Also handle Greek final sigma correctly Change-Id: I8e9fec1fc51d38a1950f95be72e07fb80d9949e4 Reviewed-on: https://go-review.googlesource.com/30254 TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/secure/precis/enforce_test.go b/secure/precis/enforce_test.go index 15d7876..a2f2328 100644 --- a/secure/precis/enforce_test.go +++ b/secure/precis/enforce_test.go
@@ -162,6 +162,7 @@ {"foo", "foo", nil}, {"Foo Bar", "Foo Bar", nil}, {"foo bar", "foo bar", nil}, + {"\u03A3", "\u03A3", nil}, {"\u03C3", "\u03C3", nil}, // Greek final sigma is left as is (do not fold!) {"\u03C2", "\u03C2", nil}, @@ -194,11 +195,12 @@ // {UsernameCaseMapped, "", "", errDisallowedRune}, {"juliet@example.com", "juliet@example.com", nil}, {"fussball", "fussball", nil}, - {"fu\u00DFball", "fussball", nil}, + {"fu\u00DFball", "fu\u00DFball", nil}, {"\u03C0", "\u03C0", nil}, {"\u03A3", "\u03C3", nil}, {"\u03C3", "\u03C3", nil}, - {"\u03C2", "\u03C3", nil}, + // Greek final sigma is left as is (do not fold!) + {"\u03C2", "\u03C2", nil}, {"\u0049", "\u0069", nil}, {"\u0049", "\u0069", nil}, {"\u03D2", "", errDisallowedRune}, @@ -213,7 +215,7 @@ {"\n", "", bidirule.ErrInvalid}, {"\u26D6", "", bidirule.ErrInvalid}, {"\u26FF", "", bidirule.ErrInvalid}, - {"\uFB00", "ff", nil}, // Side effect of case folding. + {"\uFB00", "", errDisallowedRune}, {"\u1680", "", bidirule.ErrInvalid}, {" ", "", bidirule.ErrInvalid}, {" ", "", bidirule.ErrInvalid}, @@ -229,8 +231,6 @@ {"\u0052\u030C", "ř", nil}, {"\u1E61", "\u1E61", nil}, // LATIN SMALL LETTER S WITH DOT ABOVE - // U+1e9B: case folded. - {"ẛ", "\u1E61", nil}, // LATIN SMALL LETTER LONG S WITH DOT ABOVE // Confusable characters ARE allowed and should NOT be mapped. {"\u0410", "\u0430", nil}, // CYRILLIC CAPITAL LETTER A
diff --git a/secure/precis/options.go b/secure/precis/options.go index ec63783..4b71c6a 100644 --- a/secure/precis/options.go +++ b/secure/precis/options.go
@@ -6,6 +6,7 @@ import ( "golang.org/x/text/cases" + "golang.org/x/text/language" "golang.org/x/text/runes" "golang.org/x/text/transform" "golang.org/x/text/unicode/norm" @@ -97,6 +98,20 @@ } } +// The LowerCase option defines a Profile's case mapping rule. Options can be +// provided to determine the type of case folding used. +func LowerCase(opts ...cases.Option) Option { + return func(o *options) { + if len(opts) == 0 { + o.cases = cases.Lower(language.Und, cases.HandleFinalSigma(false)) + return + } + + opts = append([]cases.Option{cases.HandleFinalSigma(false)}, opts...) + o.cases = cases.Lower(language.Und, opts...) + } +} + // The Disallow option further restricts a Profile's allowed characters beyond // what is disallowed by the underlying string class. func Disallow(set runes.Set) Option {
diff --git a/secure/precis/profile.go b/secure/precis/profile.go index fd5c422..5fb74b8 100644 --- a/secure/precis/profile.go +++ b/secure/precis/profile.go
@@ -8,6 +8,8 @@ "errors" "unicode/utf8" + "golang.org/x/text/cases" + "golang.org/x/text/language" "golang.org/x/text/runes" "golang.org/x/text/secure/bidirule" "golang.org/x/text/transform" @@ -222,6 +224,10 @@ if p.options.ignorecase { a = width.Fold.String(a) b = width.Fold.String(a) + + caser := cases.Lower(language.Und, cases.HandleFinalSigma(false)) + a = caser.String(a) + b = caser.String(b) } return a == b
diff --git a/secure/precis/profiles.go b/secure/precis/profiles.go index ad50ae8..89089c2 100644 --- a/secure/precis/profiles.go +++ b/secure/precis/profiles.go
@@ -32,7 +32,7 @@ ) usernameCaseMap = NewIdentifier( FoldWidth, - FoldCase(), + LowerCase(), Norm(norm.NFC), BidiRule, )