summaryrefslogtreecommitdiffstats
path: root/vendor/golang.org/x/text/secure/precis/profile.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/text/secure/precis/profile.go')
-rw-r--r--vendor/golang.org/x/text/secure/precis/profile.go110
1 files changed, 67 insertions, 43 deletions
diff --git a/vendor/golang.org/x/text/secure/precis/profile.go b/vendor/golang.org/x/text/secure/precis/profile.go
index bf1025338..0419159b4 100644
--- a/vendor/golang.org/x/text/secure/precis/profile.go
+++ b/vendor/golang.org/x/text/secure/precis/profile.go
@@ -60,25 +60,43 @@ func (p *Profile) NewTransformer() *Transformer {
// These transforms are applied in the order defined in
// https://tools.ietf.org/html/rfc7564#section-7
- if p.options.foldWidth {
- ts = append(ts, width.Fold)
+ // RFC 8266 ยง2.1:
+ //
+ // Implementation experience has shown that applying the rules for the
+ // Nickname profile is not an idempotent procedure for all code points.
+ // Therefore, an implementation SHOULD apply the rules repeatedly until
+ // the output string is stable; if the output string does not stabilize
+ // after reapplying the rules three (3) additional times after the first
+ // application, the implementation SHOULD terminate application of the
+ // rules and reject the input string as invalid.
+ //
+ // There is no known string that will change indefinitely, so repeat 4 times
+ // and rely on the Span method to keep things relatively performant.
+ r := 1
+ if p.options.repeat {
+ r = 4
}
+ for ; r > 0; r-- {
+ if p.options.foldWidth {
+ ts = append(ts, width.Fold)
+ }
- for _, f := range p.options.additional {
- ts = append(ts, f())
- }
+ for _, f := range p.options.additional {
+ ts = append(ts, f())
+ }
- if p.options.cases != nil {
- ts = append(ts, p.options.cases)
- }
+ if p.options.cases != nil {
+ ts = append(ts, p.options.cases)
+ }
- ts = append(ts, p.options.norm)
+ ts = append(ts, p.options.norm)
- if p.options.bidiRule {
- ts = append(ts, bidirule.New())
- }
+ if p.options.bidiRule {
+ ts = append(ts, bidirule.New())
+ }
- ts = append(ts, &checker{p: p, allowed: p.Allowed()})
+ ts = append(ts, &checker{p: p, allowed: p.Allowed()})
+ }
// TODO: Add the disallow empty rule with a dummy transformer?
@@ -162,42 +180,48 @@ func (b *buffers) enforce(p *Profile, src []byte, comparing bool) (str []byte, e
}
// These transforms are applied in the order defined in
- // https://tools.ietf.org/html/rfc7564#section-7
+ // https://tools.ietf.org/html/rfc8264#section-7
- // TODO: allow different width transforms options.
- if p.options.foldWidth || (p.options.ignorecase && comparing) {
- b.apply(foldWidthT)
+ r := 1
+ if p.options.repeat {
+ r = 4
}
- for _, f := range p.options.additional {
- if err = b.apply(f()); err != nil {
+ for ; r > 0; r-- {
+ // TODO: allow different width transforms options.
+ if p.options.foldWidth || (p.options.ignorecase && comparing) {
+ b.apply(foldWidthT)
+ }
+ for _, f := range p.options.additional {
+ if err = b.apply(f()); err != nil {
+ return nil, err
+ }
+ }
+ if p.options.cases != nil {
+ b.apply(p.options.cases)
+ }
+ if comparing && p.options.ignorecase {
+ b.apply(lowerCaseT)
+ }
+ b.apply(p.norm)
+ if p.options.bidiRule && !bidirule.Valid(b.src) {
+ return nil, bidirule.ErrInvalid
+ }
+ c := checker{p: p}
+ if _, err := c.span(b.src, true); err != nil {
return nil, err
}
- }
- if p.options.cases != nil {
- b.apply(p.options.cases)
- }
- if comparing && p.options.ignorecase {
- b.apply(lowerCaseT)
- }
- b.apply(p.norm)
- if p.options.bidiRule && !bidirule.Valid(b.src) {
- return nil, bidirule.ErrInvalid
- }
- c := checker{p: p}
- if _, err := c.span(b.src, true); err != nil {
- return nil, err
- }
- if p.disallow != nil {
- for i := 0; i < len(b.src); {
- r, size := utf8.DecodeRune(b.src[i:])
- if p.disallow.Contains(r) {
- return nil, errDisallowedRune
+ if p.disallow != nil {
+ for i := 0; i < len(b.src); {
+ r, size := utf8.DecodeRune(b.src[i:])
+ if p.disallow.Contains(r) {
+ return nil, errDisallowedRune
+ }
+ i += size
}
- i += size
}
- }
- if p.options.disallowEmpty && len(b.src) == 0 {
- return nil, errEmptyString
+ if p.options.disallowEmpty && len(b.src) == 0 {
+ return nil, errEmptyString
+ }
}
return b.src, nil
}