update dependencies

This commit is contained in:
dhax 2017-10-21 18:30:08 +02:00
parent fce1b99683
commit 397e9c0842
164 changed files with 5207 additions and 2213 deletions

View file

@ -4,8 +4,8 @@
// Package precis contains types and functions for the preparation,
// enforcement, and comparison of internationalized strings ("PRECIS") as
// defined in RFC 7564. It also contains several pre-defined profiles for
// passwords, nicknames, and usernames as defined in RFC 7613 and RFC 7700.
// defined in RFC 8264. It also contains several pre-defined profiles for
// passwords, nicknames, and usernames as defined in RFC 8265 and RFC 8266.
//
// BE ADVISED: This package is under construction and the API may change in
// backwards incompatible ways and without notice.

View file

@ -279,13 +279,16 @@ func TestBytes(t *testing.T) {
t.Errorf("got %+q (err: %v); want %+q (err: %v)", string(e), err, tc.output, tc.err)
}
})
// Test that calling Bytes with something that doesn't transform returns a
// copy.
orig := []byte("hello")
b, _ := NewFreeform().Bytes(orig)
if reflect.ValueOf(b).Pointer() == reflect.ValueOf(orig).Pointer() {
t.Error("original and result are the same slice; should be a copy")
}
t.Run("Copy", func(t *testing.T) {
// Test that calling Bytes with something that doesn't transform returns a
// copy.
orig := []byte("hello")
b, _ := NewFreeform().Bytes(orig)
if reflect.ValueOf(b).Pointer() == reflect.ValueOf(orig).Pointer() {
t.Error("original and result are the same slice; should be a copy")
}
})
}
func TestAppend(t *testing.T) {

View file

@ -23,24 +23,26 @@ func (t *nickAdditionalMapping) Reset() {
}
func (t *nickAdditionalMapping) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
// RFC 7700 §2.1. Rules
// RFC 8266 §2.1. Rules
//
// 2. Additional Mapping Rule: The additional mapping rule consists of
// the following sub-rules.
// the following sub-rules.
//
// 1. Any instances of non-ASCII space MUST be mapped to ASCII
// space (U+0020); a non-ASCII space is any Unicode code point
// having a general category of "Zs", naturally with the
// exception of U+0020.
// a. Map any instances of non-ASCII space to SPACE (U+0020); a
// non-ASCII space is any Unicode code point having a general
// category of "Zs", naturally with the exception of SPACE
// (U+0020). (The inclusion of only ASCII space prevents
// confusion with various non-ASCII space code points, many of
// which are difficult to reproduce across different input
// methods.)
//
// 2. Any instances of the ASCII space character at the beginning
// or end of a nickname MUST be removed (e.g., "stpeter " is
// mapped to "stpeter").
// b. Remove any instances of the ASCII space character at the
// beginning or end of a nickname (e.g., "stpeter " is mapped to
// "stpeter").
//
// 3. Interior sequences of more than one ASCII space character
// MUST be mapped to a single ASCII space character (e.g.,
// "St Peter" is mapped to "St Peter").
// c. Map interior sequences of more than one ASCII space character
// to a single ASCII space character (e.g., "St Peter" is
// mapped to "St Peter").
for nSrc < len(src) {
r, size := utf8.DecodeRune(src[nSrc:])
if size == 0 { // Incomplete UTF-8 encoding

View file

@ -28,6 +28,7 @@ type options struct {
width transform.SpanningTransformer
disallowEmpty bool
bidiRule bool
repeat bool
// Comparison options
ignorecase bool
@ -78,6 +79,9 @@ var (
bidiRule = func(o *options) {
o.bidiRule = true
}
repeat = func(o *options) {
o.repeat = true
}
)
// TODO: move this logic to package transform

View file

@ -60,26 +60,44 @@ 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)
}
ts = append(ts, p.options.norm)
if p.options.bidiRule {
ts = append(ts, bidirule.New())
}
ts = append(ts, &checker{p: p, allowed: p.Allowed()})
}
if p.options.cases != nil {
ts = append(ts, p.options.cases)
}
ts = append(ts, p.options.norm)
if p.options.bidiRule {
ts = append(ts, bidirule.New())
}
ts = append(ts, &checker{p: p, allowed: p.Allowed()})
// TODO: Add the disallow empty rule with a dummy transformer?
return &Transformer{transform.Chain(ts...)}
@ -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
}

View file

@ -103,9 +103,9 @@ var compareTestCases = []struct {
// After applying the Nickname profile, \u00a8 becomes \u0020\u0308,
// however because the nickname profile is not idempotent, applying it again
// to \u0020\u0308 results in \u0308. This behavior is "correct", even if it
// is unexpected.
{"\u00a8", "\u0020\u0308", false},
// to \u0020\u0308 results in \u0308.
{"\u00a8", "\u0020\u0308", true},
{"\u00a8", "\u0308", true},
{"\u0020\u0308", "\u0308", true},
}},
}

View file

@ -13,18 +13,17 @@ import (
)
var (
// Implements the Nickname profile specified in RFC 7700.
// The nickname profile is not idempotent and may need to be applied multiple
// times before being used for comparisons.
// Implements the Nickname profile specified in RFC 8266.
Nickname *Profile = nickname
// Implements the UsernameCaseMapped profile specified in RFC 7613.
// Implements the UsernameCaseMapped profile specified in RFC 8265.
UsernameCaseMapped *Profile = usernameCaseMap
// Implements the UsernameCasePreserved profile specified in RFC 7613.
// Implements the UsernameCasePreserved profile specified in RFC 8265.
UsernameCasePreserved *Profile = usernameNoCaseMap
// Implements the OpaqueString profile defined in RFC 7613 for passwords and other secure labels.
// Implements the OpaqueString profile defined in RFC 8265 for passwords and
// other secure labels.
OpaqueString *Profile = opaquestring
)
@ -37,6 +36,7 @@ var (
IgnoreCase,
Norm(norm.NFKC),
DisallowEmpty,
repeat,
),
class: freeform,
}