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,
)