Checking in vendor folder for ease of using go get.
This commit is contained in:
parent
7a1251853b
commit
cdb4b5a1d0
3554 changed files with 1270116 additions and 0 deletions
4
vendor/golang.org/x/text/internal/export/README
generated
vendored
Normal file
4
vendor/golang.org/x/text/internal/export/README
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
The export directory contains packages that are generated using the x/text
|
||||
infrastructure, but live elsewhere.
|
||||
At some point we can expose some of the infrastructure, but for now this
|
||||
is not done.
|
55
vendor/golang.org/x/text/internal/export/idna/common_test.go
generated
vendored
Normal file
55
vendor/golang.org/x/text/internal/export/idna/common_test.go
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package idna
|
||||
|
||||
// This file contains code that is common between the generation code and the
|
||||
// package's test code.
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"golang.org/x/text/internal/ucd"
|
||||
)
|
||||
|
||||
func catFromEntry(p *ucd.Parser) (cat category) {
|
||||
r := p.Rune(0)
|
||||
switch s := p.String(1); s {
|
||||
case "valid":
|
||||
cat = valid
|
||||
case "disallowed":
|
||||
cat = disallowed
|
||||
case "disallowed_STD3_valid":
|
||||
cat = disallowedSTD3Valid
|
||||
case "disallowed_STD3_mapped":
|
||||
cat = disallowedSTD3Mapped
|
||||
case "mapped":
|
||||
cat = mapped
|
||||
case "deviation":
|
||||
cat = deviation
|
||||
case "ignored":
|
||||
cat = ignored
|
||||
default:
|
||||
log.Fatalf("%U: Unknown category %q", r, s)
|
||||
}
|
||||
if s := p.String(3); s != "" {
|
||||
if cat != valid {
|
||||
log.Fatalf(`%U: %s defined for %q; want "valid"`, r, s, p.String(1))
|
||||
}
|
||||
switch s {
|
||||
case "NV8":
|
||||
cat = validNV8
|
||||
case "XV8":
|
||||
cat = validXV8
|
||||
default:
|
||||
log.Fatalf("%U: Unexpected exception %q", r, s)
|
||||
}
|
||||
}
|
||||
return cat
|
||||
}
|
||||
|
||||
var joinType = map[string]info{
|
||||
"L": joiningL,
|
||||
"D": joiningD,
|
||||
"T": joiningT,
|
||||
"R": joiningR,
|
||||
}
|
68
vendor/golang.org/x/text/internal/export/idna/example_test.go
generated
vendored
Normal file
68
vendor/golang.org/x/text/internal/export/idna/example_test.go
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package idna_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/text/internal/export/idna"
|
||||
)
|
||||
|
||||
func ExampleProfile() {
|
||||
// Raw Punycode has no restrictions and does no mappings.
|
||||
fmt.Println(idna.ToASCII(""))
|
||||
fmt.Println(idna.ToASCII("*.faß.com"))
|
||||
fmt.Println(idna.Punycode.ToASCII("*.faß.com"))
|
||||
|
||||
// Rewrite IDN for lookup. This (currently) uses transitional mappings to
|
||||
// find a balance between IDNA2003 and IDNA2008 compatibility.
|
||||
fmt.Println(idna.Lookup.ToASCII(""))
|
||||
fmt.Println(idna.Lookup.ToASCII("www.faß.com"))
|
||||
|
||||
// Convert an IDN to ASCII for registration purposes. This changes the
|
||||
// encoding, but reports an error if the input was illformed.
|
||||
fmt.Println(idna.Registration.ToASCII(""))
|
||||
fmt.Println(idna.Registration.ToASCII("www.faß.com"))
|
||||
|
||||
// Output:
|
||||
// <nil>
|
||||
// *.xn--fa-hia.com <nil>
|
||||
// *.xn--fa-hia.com <nil>
|
||||
// <nil>
|
||||
// www.fass.com <nil>
|
||||
// idna: invalid label ""
|
||||
// www.xn--fa-hia.com <nil>
|
||||
}
|
||||
|
||||
func ExampleNew() {
|
||||
var p *idna.Profile
|
||||
|
||||
// Raw Punycode has no restrictions and does no mappings.
|
||||
p = idna.New()
|
||||
fmt.Println(p.ToASCII("*.faß.com"))
|
||||
|
||||
// Do mappings. Note that star is not allowed in a DNS lookup.
|
||||
p = idna.New(
|
||||
idna.MapForLookup(),
|
||||
idna.Transitional(true)) // Map ß -> ss
|
||||
fmt.Println(p.ToASCII("*.faß.com"))
|
||||
|
||||
// Lookup for registration. Also does not allow '*'.
|
||||
p = idna.New(idna.ValidateForRegistration())
|
||||
fmt.Println(p.ToUnicode("*.faß.com"))
|
||||
|
||||
// Set up a profile maps for lookup, but allows wild cards.
|
||||
p = idna.New(
|
||||
idna.MapForLookup(),
|
||||
idna.Transitional(true), // Map ß -> ss
|
||||
idna.StrictDomainName(false)) // Set more permissive ASCII rules.
|
||||
fmt.Println(p.ToASCII("*.faß.com"))
|
||||
|
||||
// Output:
|
||||
// *.xn--fa-hia.com <nil>
|
||||
// *.fass.com idna: disallowed rune U+002A
|
||||
// *.faß.com idna: disallowed rune U+002A
|
||||
// *.fass.com <nil>
|
||||
}
|
276
vendor/golang.org/x/text/internal/export/idna/gen.go
generated
vendored
Normal file
276
vendor/golang.org/x/text/internal/export/idna/gen.go
generated
vendored
Normal file
|
@ -0,0 +1,276 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// This program generates the trie for idna operations. The Unicode casing
|
||||
// algorithm requires the lookup of various properties and mappings for each
|
||||
// rune. The table generated by this generator combines several of the most
|
||||
// frequently used of these into a single trie so that they can be accessed
|
||||
// with a single lookup.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/triegen"
|
||||
"golang.org/x/text/internal/ucd"
|
||||
"golang.org/x/text/unicode/bidi"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gen.Init()
|
||||
genTables()
|
||||
gen.Repackage("gen_trieval.go", "trieval.go", "idna")
|
||||
gen.Repackage("gen_common.go", "common_test.go", "idna")
|
||||
}
|
||||
|
||||
var runes = map[rune]info{}
|
||||
|
||||
func genTables() {
|
||||
t := triegen.NewTrie("idna")
|
||||
|
||||
ucd.Parse(gen.OpenUCDFile("DerivedNormalizationProps.txt"), func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
if p.String(1) == "NFC_QC" { // p.String(2) is "N" or "M"
|
||||
runes[r] = mayNeedNorm
|
||||
}
|
||||
})
|
||||
ucd.Parse(gen.OpenUCDFile("UnicodeData.txt"), func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
|
||||
const cccVirama = 9
|
||||
if p.Int(ucd.CanonicalCombiningClass) == cccVirama {
|
||||
runes[p.Rune(0)] = viramaModifier
|
||||
}
|
||||
switch {
|
||||
case unicode.In(r, unicode.Mark):
|
||||
runes[r] |= modifier | mayNeedNorm
|
||||
}
|
||||
// TODO: by using UnicodeData.txt we don't mark undefined codepoints
|
||||
// that are earmarked as RTL properly. However, an undefined cp will
|
||||
// always fail, so there is no need to store this info.
|
||||
switch p, _ := bidi.LookupRune(r); p.Class() {
|
||||
case bidi.R, bidi.AL, bidi.AN:
|
||||
if x := runes[r]; x != 0 && x != mayNeedNorm {
|
||||
log.Fatalf("%U: rune both modifier and RTL letter/number", r)
|
||||
}
|
||||
runes[r] = rtl
|
||||
}
|
||||
})
|
||||
|
||||
ucd.Parse(gen.OpenUCDFile("extracted/DerivedJoiningType.txt"), func(p *ucd.Parser) {
|
||||
switch v := p.String(1); v {
|
||||
case "L", "D", "T", "R":
|
||||
runes[p.Rune(0)] |= joinType[v] << joinShift
|
||||
}
|
||||
})
|
||||
|
||||
ucd.Parse(gen.OpenUnicodeFile("idna", "", "IdnaMappingTable.txt"), func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
|
||||
// The mappings table explicitly defines surrogates as invalid.
|
||||
if !utf8.ValidRune(r) {
|
||||
return
|
||||
}
|
||||
|
||||
cat := catFromEntry(p)
|
||||
isMapped := cat == mapped || cat == disallowedSTD3Mapped || cat == deviation
|
||||
if !isMapped {
|
||||
// Only include additional category information for non-mapped
|
||||
// runes. The additional information is only used after mapping and
|
||||
// the bits would clash with mapping information.
|
||||
// TODO: it would be possible to inline this data and avoid
|
||||
// additional lookups. This is quite tedious, though, so let's first
|
||||
// see if we need this.
|
||||
cat |= category(runes[r])
|
||||
}
|
||||
|
||||
s := string(p.Runes(2))
|
||||
if s != "" && !isMapped {
|
||||
log.Fatalf("%U: Mapping with non-mapping category %d", r, cat)
|
||||
}
|
||||
t.Insert(r, uint64(makeEntry(r, s))+uint64(cat))
|
||||
})
|
||||
|
||||
w := gen.NewCodeWriter()
|
||||
defer w.WriteVersionedGoFile("tables.go", "idna")
|
||||
|
||||
gen.WriteUnicodeVersion(w)
|
||||
|
||||
w.WriteVar("mappings", string(mappings))
|
||||
w.WriteVar("xorData", string(xorData))
|
||||
|
||||
sz, err := t.Gen(w, triegen.Compact(&normCompacter{}))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
w.Size += sz
|
||||
}
|
||||
|
||||
var (
|
||||
// mappings contains replacement strings for mapped runes, each prefixed
|
||||
// with a byte containing the length of the following string.
|
||||
mappings = []byte{}
|
||||
mapCache = map[string]int{}
|
||||
|
||||
// xorData is like mappings, except that it contains XOR data.
|
||||
// We split these two tables so that we don't get an overflow.
|
||||
xorData = []byte{}
|
||||
xorCache = map[string]int{}
|
||||
)
|
||||
|
||||
// makeEntry creates a trie entry.
|
||||
func makeEntry(r rune, mapped string) info {
|
||||
orig := string(r)
|
||||
|
||||
if len(orig) != len(mapped) {
|
||||
// Store the mapped value as is in the mappings table.
|
||||
index := len(mappings)
|
||||
if x, ok := mapCache[mapped]; ok {
|
||||
index = x
|
||||
} else {
|
||||
mapCache[mapped] = index
|
||||
mappings = append(mappings, byte(len(mapped)))
|
||||
mappings = append(mappings, mapped...)
|
||||
}
|
||||
return info(index) << indexShift
|
||||
}
|
||||
|
||||
// Create per-byte XOR mask.
|
||||
var b []byte
|
||||
for i := 0; i < len(orig); i++ {
|
||||
b = append(b, orig[i]^mapped[i])
|
||||
}
|
||||
|
||||
// Remove leading 0 bytes, but keep at least one byte.
|
||||
for ; len(b) > 1 && b[0] == 0; b = b[1:] {
|
||||
}
|
||||
|
||||
if len(b) == 1 {
|
||||
return xorBit | inlineXOR | info(b[0])<<indexShift
|
||||
}
|
||||
mapped = string(b)
|
||||
|
||||
// Store the mapped value as is in the mappings table.
|
||||
index := len(xorData)
|
||||
if x, ok := xorCache[mapped]; ok {
|
||||
index = x
|
||||
} else {
|
||||
xorCache[mapped] = index
|
||||
xorData = append(xorData, byte(len(mapped)))
|
||||
xorData = append(xorData, mapped...)
|
||||
}
|
||||
return xorBit | info(index)<<indexShift
|
||||
}
|
||||
|
||||
// The following code implements a triegen.Compacter that was originally
|
||||
// designed for normalization. The IDNA table has some similarities with the
|
||||
// norm table. Using this compacter, together with the XOR pattern approach,
|
||||
// reduces the table size by roughly 100K. It can probably be compressed further
|
||||
// by also including elements of the compacter used by cases, but for now it is
|
||||
// good enough.
|
||||
|
||||
const maxSparseEntries = 16
|
||||
|
||||
type normCompacter struct {
|
||||
sparseBlocks [][]uint64
|
||||
sparseOffset []uint16
|
||||
sparseCount int
|
||||
}
|
||||
|
||||
func mostFrequentStride(a []uint64) int {
|
||||
counts := make(map[int]int)
|
||||
var v int
|
||||
for _, x := range a {
|
||||
if stride := int(x) - v; v != 0 && stride >= 0 {
|
||||
counts[stride]++
|
||||
}
|
||||
v = int(x)
|
||||
}
|
||||
var maxs, maxc int
|
||||
for stride, cnt := range counts {
|
||||
if cnt > maxc || (cnt == maxc && stride < maxs) {
|
||||
maxs, maxc = stride, cnt
|
||||
}
|
||||
}
|
||||
return maxs
|
||||
}
|
||||
|
||||
func countSparseEntries(a []uint64) int {
|
||||
stride := mostFrequentStride(a)
|
||||
var v, count int
|
||||
for _, tv := range a {
|
||||
if int(tv)-v != stride {
|
||||
if tv != 0 {
|
||||
count++
|
||||
}
|
||||
}
|
||||
v = int(tv)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func (c *normCompacter) Size(v []uint64) (sz int, ok bool) {
|
||||
if n := countSparseEntries(v); n <= maxSparseEntries {
|
||||
return (n+1)*4 + 2, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (c *normCompacter) Store(v []uint64) uint32 {
|
||||
h := uint32(len(c.sparseOffset))
|
||||
c.sparseBlocks = append(c.sparseBlocks, v)
|
||||
c.sparseOffset = append(c.sparseOffset, uint16(c.sparseCount))
|
||||
c.sparseCount += countSparseEntries(v) + 1
|
||||
return h
|
||||
}
|
||||
|
||||
func (c *normCompacter) Handler() string {
|
||||
return "idnaSparse.lookup"
|
||||
}
|
||||
|
||||
func (c *normCompacter) Print(w io.Writer) (retErr error) {
|
||||
p := func(f string, x ...interface{}) {
|
||||
if _, err := fmt.Fprintf(w, f, x...); retErr == nil && err != nil {
|
||||
retErr = err
|
||||
}
|
||||
}
|
||||
|
||||
ls := len(c.sparseBlocks)
|
||||
p("// idnaSparseOffset: %d entries, %d bytes\n", ls, ls*2)
|
||||
p("var idnaSparseOffset = %#v\n\n", c.sparseOffset)
|
||||
|
||||
ns := c.sparseCount
|
||||
p("// idnaSparseValues: %d entries, %d bytes\n", ns, ns*4)
|
||||
p("var idnaSparseValues = [%d]valueRange {", ns)
|
||||
for i, b := range c.sparseBlocks {
|
||||
p("\n// Block %#x, offset %#x", i, c.sparseOffset[i])
|
||||
var v int
|
||||
stride := mostFrequentStride(b)
|
||||
n := countSparseEntries(b)
|
||||
p("\n{value:%#04x,lo:%#02x},", stride, uint8(n))
|
||||
for i, nv := range b {
|
||||
if int(nv)-v != stride {
|
||||
if v != 0 {
|
||||
p(",hi:%#02x},", 0x80+i-1)
|
||||
}
|
||||
if nv != 0 {
|
||||
p("\n{value:%#04x,lo:%#02x", nv, 0x80+i)
|
||||
}
|
||||
}
|
||||
v = int(nv)
|
||||
}
|
||||
if v != 0 {
|
||||
p(",hi:%#02x},", 0x80+len(b)-1)
|
||||
}
|
||||
}
|
||||
p("\n}\n\n")
|
||||
return
|
||||
}
|
93
vendor/golang.org/x/text/internal/export/idna/gen10.0.0_test.go
generated
vendored
Normal file
93
vendor/golang.org/x/text/internal/export/idna/gen10.0.0_test.go
generated
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.10
|
||||
|
||||
package idna
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/testtext"
|
||||
"golang.org/x/text/internal/ucd"
|
||||
)
|
||||
|
||||
func TestTables(t *testing.T) {
|
||||
testtext.SkipIfNotLong(t)
|
||||
|
||||
lookup := func(r rune) info {
|
||||
v, _ := trie.lookupString(string(r))
|
||||
return info(v)
|
||||
}
|
||||
|
||||
ucd.Parse(gen.OpenUnicodeFile("idna", "", "IdnaMappingTable.txt"), func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
x := lookup(r)
|
||||
if got, want := x.category(), catFromEntry(p); got != want {
|
||||
t.Errorf("%U:category: got %x; want %x", r, got, want)
|
||||
}
|
||||
|
||||
mapped := false
|
||||
switch p.String(1) {
|
||||
case "mapped", "disallowed_STD3_mapped", "deviation":
|
||||
mapped = true
|
||||
}
|
||||
if x.isMapped() != mapped {
|
||||
t.Errorf("%U:isMapped: got %v; want %v", r, x.isMapped(), mapped)
|
||||
}
|
||||
if !mapped {
|
||||
return
|
||||
}
|
||||
want := string(p.Runes(2))
|
||||
got := string(x.appendMapping(nil, string(r)))
|
||||
if got != want {
|
||||
t.Errorf("%U:mapping: got %+q; want %+q", r, got, want)
|
||||
}
|
||||
|
||||
if x.isMapped() {
|
||||
return
|
||||
}
|
||||
wantMark := unicode.In(r, unicode.Mark)
|
||||
gotMark := x.isModifier()
|
||||
if gotMark != wantMark {
|
||||
t.Errorf("IsMark(%U) = %v; want %v", r, gotMark, wantMark)
|
||||
}
|
||||
})
|
||||
|
||||
ucd.Parse(gen.OpenUCDFile("UnicodeData.txt"), func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
x := lookup(r)
|
||||
got := x.isViramaModifier()
|
||||
|
||||
const cccVirama = 9
|
||||
want := p.Int(ucd.CanonicalCombiningClass) == cccVirama
|
||||
if got != want {
|
||||
t.Errorf("IsVirama(%U) = %v; want %v", r, got, want)
|
||||
}
|
||||
|
||||
rtl := false
|
||||
switch p.String(ucd.BidiClass) {
|
||||
case "R", "AL", "AN":
|
||||
rtl = true
|
||||
}
|
||||
if got := x.isBidi("A"); got != rtl && !x.isMapped() {
|
||||
t.Errorf("IsBidi(%U) = %v; want %v", r, got, rtl)
|
||||
}
|
||||
})
|
||||
|
||||
ucd.Parse(gen.OpenUCDFile("extracted/DerivedJoiningType.txt"), func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
x := lookup(r)
|
||||
if x.isMapped() {
|
||||
return
|
||||
}
|
||||
got := x.joinType()
|
||||
want := joinType[p.String(1)]
|
||||
if got != want {
|
||||
t.Errorf("JoinType(%U) = %x; want %x", r, got, want)
|
||||
}
|
||||
})
|
||||
}
|
84
vendor/golang.org/x/text/internal/export/idna/gen9.0.0_test.go
generated
vendored
Normal file
84
vendor/golang.org/x/text/internal/export/idna/gen9.0.0_test.go
generated
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.10
|
||||
|
||||
package idna
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/testtext"
|
||||
"golang.org/x/text/internal/ucd"
|
||||
)
|
||||
|
||||
func TestTables(t *testing.T) {
|
||||
testtext.SkipIfNotLong(t)
|
||||
|
||||
lookup := func(r rune) info {
|
||||
v, _ := trie.lookupString(string(r))
|
||||
return info(v)
|
||||
}
|
||||
|
||||
ucd.Parse(gen.OpenUnicodeFile("idna", "", "IdnaMappingTable.txt"), func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
x := lookup(r)
|
||||
if got, want := x.category(), catFromEntry(p); got != want {
|
||||
t.Errorf("%U:category: got %x; want %x", r, got, want)
|
||||
}
|
||||
|
||||
mapped := false
|
||||
switch p.String(1) {
|
||||
case "mapped", "disallowed_STD3_mapped", "deviation":
|
||||
mapped = true
|
||||
}
|
||||
if x.isMapped() != mapped {
|
||||
t.Errorf("%U:isMapped: got %v; want %v", r, x.isMapped(), mapped)
|
||||
}
|
||||
if !mapped {
|
||||
return
|
||||
}
|
||||
want := string(p.Runes(2))
|
||||
got := string(x.appendMapping(nil, string(r)))
|
||||
if got != want {
|
||||
t.Errorf("%U:mapping: got %+q; want %+q", r, got, want)
|
||||
}
|
||||
|
||||
if x.isMapped() {
|
||||
return
|
||||
}
|
||||
wantMark := unicode.In(r, unicode.Mark)
|
||||
gotMark := x.isModifier()
|
||||
if gotMark != wantMark {
|
||||
t.Errorf("IsMark(%U) = %v; want %v", r, gotMark, wantMark)
|
||||
}
|
||||
})
|
||||
|
||||
ucd.Parse(gen.OpenUCDFile("UnicodeData.txt"), func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
x := lookup(r)
|
||||
got := x.isViramaModifier()
|
||||
|
||||
const cccVirama = 9
|
||||
want := p.Int(ucd.CanonicalCombiningClass) == cccVirama
|
||||
if got != want {
|
||||
t.Errorf("IsVirama(%U) = %v; want %v", r, got, want)
|
||||
}
|
||||
})
|
||||
|
||||
ucd.Parse(gen.OpenUCDFile("extracted/DerivedJoiningType.txt"), func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
x := lookup(r)
|
||||
if x.isMapped() {
|
||||
return
|
||||
}
|
||||
got := x.joinType()
|
||||
want := joinType[p.String(1)]
|
||||
if got != want {
|
||||
t.Errorf("JoinType(%U) = %x; want %x", r, got, want)
|
||||
}
|
||||
})
|
||||
}
|
59
vendor/golang.org/x/text/internal/export/idna/gen_common.go
generated
vendored
Normal file
59
vendor/golang.org/x/text/internal/export/idna/gen_common.go
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This file contains code that is common between the generation code and the
|
||||
// package's test code.
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"golang.org/x/text/internal/ucd"
|
||||
)
|
||||
|
||||
func catFromEntry(p *ucd.Parser) (cat category) {
|
||||
r := p.Rune(0)
|
||||
switch s := p.String(1); s {
|
||||
case "valid":
|
||||
cat = valid
|
||||
case "disallowed":
|
||||
cat = disallowed
|
||||
case "disallowed_STD3_valid":
|
||||
cat = disallowedSTD3Valid
|
||||
case "disallowed_STD3_mapped":
|
||||
cat = disallowedSTD3Mapped
|
||||
case "mapped":
|
||||
cat = mapped
|
||||
case "deviation":
|
||||
cat = deviation
|
||||
case "ignored":
|
||||
cat = ignored
|
||||
default:
|
||||
log.Fatalf("%U: Unknown category %q", r, s)
|
||||
}
|
||||
if s := p.String(3); s != "" {
|
||||
if cat != valid {
|
||||
log.Fatalf(`%U: %s defined for %q; want "valid"`, r, s, p.String(1))
|
||||
}
|
||||
switch s {
|
||||
case "NV8":
|
||||
cat = validNV8
|
||||
case "XV8":
|
||||
cat = validXV8
|
||||
default:
|
||||
log.Fatalf("%U: Unexpected exception %q", r, s)
|
||||
}
|
||||
}
|
||||
return cat
|
||||
}
|
||||
|
||||
var joinType = map[string]info{
|
||||
"L": joiningL,
|
||||
"D": joiningD,
|
||||
"T": joiningT,
|
||||
"R": joiningR,
|
||||
}
|
123
vendor/golang.org/x/text/internal/export/idna/gen_trieval.go
generated
vendored
Normal file
123
vendor/golang.org/x/text/internal/export/idna/gen_trieval.go
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This file contains definitions for interpreting the trie value of the idna
|
||||
// trie generated by "go run gen*.go". It is shared by both the generator
|
||||
// program and the resultant package. Sharing is achieved by the generator
|
||||
// copying gen_trieval.go to trieval.go and changing what's above this comment.
|
||||
|
||||
// info holds information from the IDNA mapping table for a single rune. It is
|
||||
// the value returned by a trie lookup. In most cases, all information fits in
|
||||
// a 16-bit value. For mappings, this value may contain an index into a slice
|
||||
// with the mapped string. Such mappings can consist of the actual mapped value
|
||||
// or an XOR pattern to be applied to the bytes of the UTF8 encoding of the
|
||||
// input rune. This technique is used by the cases packages and reduces the
|
||||
// table size significantly.
|
||||
//
|
||||
// The per-rune values have the following format:
|
||||
//
|
||||
// if mapped {
|
||||
// if inlinedXOR {
|
||||
// 15..13 inline XOR marker
|
||||
// 12..11 unused
|
||||
// 10..3 inline XOR mask
|
||||
// } else {
|
||||
// 15..3 index into xor or mapping table
|
||||
// }
|
||||
// } else {
|
||||
// 15..14 unused
|
||||
// 13 mayNeedNorm
|
||||
// 12..11 attributes
|
||||
// 10..8 joining type
|
||||
// 7..3 category type
|
||||
// }
|
||||
// 2 use xor pattern
|
||||
// 1..0 mapped category
|
||||
//
|
||||
// See the definitions below for a more detailed description of the various
|
||||
// bits.
|
||||
type info uint16
|
||||
|
||||
const (
|
||||
catSmallMask = 0x3
|
||||
catBigMask = 0xF8
|
||||
indexShift = 3
|
||||
xorBit = 0x4 // interpret the index as an xor pattern
|
||||
inlineXOR = 0xE000 // These bits are set if the XOR pattern is inlined.
|
||||
|
||||
joinShift = 8
|
||||
joinMask = 0x07
|
||||
|
||||
// Attributes
|
||||
attributesMask = 0x1800
|
||||
viramaModifier = 0x1800
|
||||
modifier = 0x1000
|
||||
rtl = 0x0800
|
||||
|
||||
mayNeedNorm = 0x2000
|
||||
)
|
||||
|
||||
// A category corresponds to a category defined in the IDNA mapping table.
|
||||
type category uint16
|
||||
|
||||
const (
|
||||
unknown category = 0 // not currently defined in unicode.
|
||||
mapped category = 1
|
||||
disallowedSTD3Mapped category = 2
|
||||
deviation category = 3
|
||||
)
|
||||
|
||||
const (
|
||||
valid category = 0x08
|
||||
validNV8 category = 0x18
|
||||
validXV8 category = 0x28
|
||||
disallowed category = 0x40
|
||||
disallowedSTD3Valid category = 0x80
|
||||
ignored category = 0xC0
|
||||
)
|
||||
|
||||
// join types and additional rune information
|
||||
const (
|
||||
joiningL = (iota + 1)
|
||||
joiningD
|
||||
joiningT
|
||||
joiningR
|
||||
|
||||
//the following types are derived during processing
|
||||
joinZWJ
|
||||
joinZWNJ
|
||||
joinVirama
|
||||
numJoinTypes
|
||||
)
|
||||
|
||||
func (c info) isMapped() bool {
|
||||
return c&0x3 != 0
|
||||
}
|
||||
|
||||
func (c info) category() category {
|
||||
small := c & catSmallMask
|
||||
if small != 0 {
|
||||
return category(small)
|
||||
}
|
||||
return category(c & catBigMask)
|
||||
}
|
||||
|
||||
func (c info) joinType() info {
|
||||
if c.isMapped() {
|
||||
return 0
|
||||
}
|
||||
return (c >> joinShift) & joinMask
|
||||
}
|
||||
|
||||
func (c info) isModifier() bool {
|
||||
return c&(modifier|catSmallMask) == modifier
|
||||
}
|
||||
|
||||
func (c info) isViramaModifier() bool {
|
||||
return c&(attributesMask|catSmallMask) == viramaModifier
|
||||
}
|
733
vendor/golang.org/x/text/internal/export/idna/idna10.0.0.go
generated
vendored
Normal file
733
vendor/golang.org/x/text/internal/export/idna/idna10.0.0.go
generated
vendored
Normal file
|
@ -0,0 +1,733 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.10
|
||||
//go:generate go run gen.go gen_trieval.go gen_common.go
|
||||
|
||||
// Package idna implements IDNA2008 using the compatibility processing
|
||||
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
||||
// deal with the transition from IDNA2003.
|
||||
//
|
||||
// IDNA2008 (Internationalized Domain Names for Applications), is defined in RFC
|
||||
// 5890, RFC 5891, RFC 5892, RFC 5893 and RFC 5894.
|
||||
// UTS #46 is defined in http://www.unicode.org/reports/tr46.
|
||||
// See http://unicode.org/cldr/utility/idna.jsp for a visualization of the
|
||||
// differences between these two standards.
|
||||
package idna // import "golang.org/x/text/internal/export/idna"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/secure/bidirule"
|
||||
"golang.org/x/text/unicode/bidi"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
// NOTE: Unlike common practice in Go APIs, the functions will return a
|
||||
// sanitized domain name in case of errors. Browsers sometimes use a partially
|
||||
// evaluated string as lookup.
|
||||
// TODO: the current error handling is, in my opinion, the least opinionated.
|
||||
// Other strategies are also viable, though:
|
||||
// Option 1) Return an empty string in case of error, but allow the user to
|
||||
// specify explicitly which errors to ignore.
|
||||
// Option 2) Return the partially evaluated string if it is itself a valid
|
||||
// string, otherwise return the empty string in case of error.
|
||||
// Option 3) Option 1 and 2.
|
||||
// Option 4) Always return an empty string for now and implement Option 1 as
|
||||
// needed, and document that the return string may not be empty in case of
|
||||
// error in the future.
|
||||
// I think Option 1 is best, but it is quite opinionated.
|
||||
|
||||
// ToASCII is a wrapper for Punycode.ToASCII.
|
||||
func ToASCII(s string) (string, error) {
|
||||
return Punycode.process(s, true)
|
||||
}
|
||||
|
||||
// ToUnicode is a wrapper for Punycode.ToUnicode.
|
||||
func ToUnicode(s string) (string, error) {
|
||||
return Punycode.process(s, false)
|
||||
}
|
||||
|
||||
// An Option configures a Profile at creation time.
|
||||
type Option func(*options)
|
||||
|
||||
// Transitional sets a Profile to use the Transitional mapping as defined in UTS
|
||||
// #46. This will cause, for example, "ß" to be mapped to "ss". Using the
|
||||
// transitional mapping provides a compromise between IDNA2003 and IDNA2008
|
||||
// compatibility. It is used by most browsers when resolving domain names. This
|
||||
// option is only meaningful if combined with MapForLookup.
|
||||
func Transitional(transitional bool) Option {
|
||||
return func(o *options) { o.transitional = true }
|
||||
}
|
||||
|
||||
// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
|
||||
// are longer than allowed by the RFC.
|
||||
func VerifyDNSLength(verify bool) Option {
|
||||
return func(o *options) { o.verifyDNSLength = verify }
|
||||
}
|
||||
|
||||
// RemoveLeadingDots removes leading label separators. Leading runes that map to
|
||||
// dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well.
|
||||
//
|
||||
// This is the behavior suggested by the UTS #46 and is adopted by some
|
||||
// browsers.
|
||||
func RemoveLeadingDots(remove bool) Option {
|
||||
return func(o *options) { o.removeLeadingDots = remove }
|
||||
}
|
||||
|
||||
// ValidateLabels sets whether to check the mandatory label validation criteria
|
||||
// as defined in Section 5.4 of RFC 5891. This includes testing for correct use
|
||||
// of hyphens ('-'), normalization, validity of runes, and the context rules.
|
||||
func ValidateLabels(enable bool) Option {
|
||||
return func(o *options) {
|
||||
// Don't override existing mappings, but set one that at least checks
|
||||
// normalization if it is not set.
|
||||
if o.mapping == nil && enable {
|
||||
o.mapping = normalize
|
||||
}
|
||||
o.trie = trie
|
||||
o.validateLabels = enable
|
||||
o.fromPuny = validateFromPunycode
|
||||
}
|
||||
}
|
||||
|
||||
// StrictDomainName limits the set of permissible ASCII characters to those
|
||||
// allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
|
||||
// hyphen). This is set by default for MapForLookup and ValidateForRegistration.
|
||||
//
|
||||
// This option is useful, for instance, for browsers that allow characters
|
||||
// outside this range, for example a '_' (U+005F LOW LINE). See
|
||||
// http://www.rfc-editor.org/std/std3.txt for more details This option
|
||||
// corresponds to the UseSTD3ASCIIRules option in UTS #46.
|
||||
func StrictDomainName(use bool) Option {
|
||||
return func(o *options) {
|
||||
o.trie = trie
|
||||
o.useSTD3Rules = use
|
||||
o.fromPuny = validateFromPunycode
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: the following options pull in tables. The tables should not be linked
|
||||
// in as long as the options are not used.
|
||||
|
||||
// BidiRule enables the Bidi rule as defined in RFC 5893. Any application
|
||||
// that relies on proper validation of labels should include this rule.
|
||||
func BidiRule() Option {
|
||||
return func(o *options) { o.bidirule = bidirule.ValidString }
|
||||
}
|
||||
|
||||
// ValidateForRegistration sets validation options to verify that a given IDN is
|
||||
// properly formatted for registration as defined by Section 4 of RFC 5891.
|
||||
func ValidateForRegistration() Option {
|
||||
return func(o *options) {
|
||||
o.mapping = validateRegistration
|
||||
StrictDomainName(true)(o)
|
||||
ValidateLabels(true)(o)
|
||||
VerifyDNSLength(true)(o)
|
||||
BidiRule()(o)
|
||||
}
|
||||
}
|
||||
|
||||
// MapForLookup sets validation and mapping options such that a given IDN is
|
||||
// transformed for domain name lookup according to the requirements set out in
|
||||
// Section 5 of RFC 5891. The mappings follow the recommendations of RFC 5894,
|
||||
// RFC 5895 and UTS 46. It does not add the Bidi Rule. Use the BidiRule option
|
||||
// to add this check.
|
||||
//
|
||||
// The mappings include normalization and mapping case, width and other
|
||||
// compatibility mappings.
|
||||
func MapForLookup() Option {
|
||||
return func(o *options) {
|
||||
o.mapping = validateAndMap
|
||||
StrictDomainName(true)(o)
|
||||
ValidateLabels(true)(o)
|
||||
}
|
||||
}
|
||||
|
||||
type options struct {
|
||||
transitional bool
|
||||
useSTD3Rules bool
|
||||
validateLabels bool
|
||||
verifyDNSLength bool
|
||||
removeLeadingDots bool
|
||||
|
||||
trie *idnaTrie
|
||||
|
||||
// fromPuny calls validation rules when converting A-labels to U-labels.
|
||||
fromPuny func(p *Profile, s string) error
|
||||
|
||||
// mapping implements a validation and mapping step as defined in RFC 5895
|
||||
// or UTS 46, tailored to, for example, domain registration or lookup.
|
||||
mapping func(p *Profile, s string) (mapped string, isBidi bool, err error)
|
||||
|
||||
// bidirule, if specified, checks whether s conforms to the Bidi Rule
|
||||
// defined in RFC 5893.
|
||||
bidirule func(s string) bool
|
||||
}
|
||||
|
||||
// A Profile defines the configuration of an IDNA mapper.
|
||||
type Profile struct {
|
||||
options
|
||||
}
|
||||
|
||||
func apply(o *options, opts []Option) {
|
||||
for _, f := range opts {
|
||||
f(o)
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a new Profile.
|
||||
//
|
||||
// With no options, the returned Profile is the most permissive and equals the
|
||||
// Punycode Profile. Options can be passed to further restrict the Profile. The
|
||||
// MapForLookup and ValidateForRegistration options set a collection of options,
|
||||
// for lookup and registration purposes respectively, which can be tailored by
|
||||
// adding more fine-grained options, where later options override earlier
|
||||
// options.
|
||||
func New(o ...Option) *Profile {
|
||||
p := &Profile{}
|
||||
apply(&p.options, o)
|
||||
return p
|
||||
}
|
||||
|
||||
// ToASCII converts a domain or domain label to its ASCII form. For example,
|
||||
// ToASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
|
||||
// ToASCII("golang") is "golang". If an error is encountered it will return
|
||||
// an error and a (partially) processed result.
|
||||
func (p *Profile) ToASCII(s string) (string, error) {
|
||||
return p.process(s, true)
|
||||
}
|
||||
|
||||
// ToUnicode converts a domain or domain label to its Unicode form. For example,
|
||||
// ToUnicode("xn--bcher-kva.example.com") is "bücher.example.com", and
|
||||
// ToUnicode("golang") is "golang". If an error is encountered it will return
|
||||
// an error and a (partially) processed result.
|
||||
func (p *Profile) ToUnicode(s string) (string, error) {
|
||||
pp := *p
|
||||
pp.transitional = false
|
||||
return pp.process(s, false)
|
||||
}
|
||||
|
||||
// String reports a string with a description of the profile for debugging
|
||||
// purposes. The string format may change with different versions.
|
||||
func (p *Profile) String() string {
|
||||
s := ""
|
||||
if p.transitional {
|
||||
s = "Transitional"
|
||||
} else {
|
||||
s = "NonTransitional"
|
||||
}
|
||||
if p.useSTD3Rules {
|
||||
s += ":UseSTD3Rules"
|
||||
}
|
||||
if p.validateLabels {
|
||||
s += ":ValidateLabels"
|
||||
}
|
||||
if p.verifyDNSLength {
|
||||
s += ":VerifyDNSLength"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
var (
|
||||
// Punycode is a Profile that does raw punycode processing with a minimum
|
||||
// of validation.
|
||||
Punycode *Profile = punycode
|
||||
|
||||
// Lookup is the recommended profile for looking up domain names, according
|
||||
// to Section 5 of RFC 5891. The exact configuration of this profile may
|
||||
// change over time.
|
||||
Lookup *Profile = lookup
|
||||
|
||||
// Display is the recommended profile for displaying domain names.
|
||||
// The configuration of this profile may change over time.
|
||||
Display *Profile = display
|
||||
|
||||
// Registration is the recommended profile for checking whether a given
|
||||
// IDN is valid for registration, according to Section 4 of RFC 5891.
|
||||
Registration *Profile = registration
|
||||
|
||||
punycode = &Profile{}
|
||||
lookup = &Profile{options{
|
||||
transitional: true,
|
||||
useSTD3Rules: true,
|
||||
validateLabels: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateAndMap,
|
||||
bidirule: bidirule.ValidString,
|
||||
}}
|
||||
display = &Profile{options{
|
||||
useSTD3Rules: true,
|
||||
validateLabels: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateAndMap,
|
||||
bidirule: bidirule.ValidString,
|
||||
}}
|
||||
registration = &Profile{options{
|
||||
useSTD3Rules: true,
|
||||
validateLabels: true,
|
||||
verifyDNSLength: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateRegistration,
|
||||
bidirule: bidirule.ValidString,
|
||||
}}
|
||||
|
||||
// TODO: profiles
|
||||
// Register: recommended for approving domain names: don't do any mappings
|
||||
// but rather reject on invalid input. Bundle or block deviation characters.
|
||||
)
|
||||
|
||||
type labelError struct{ label, code_ string }
|
||||
|
||||
func (e labelError) code() string { return e.code_ }
|
||||
func (e labelError) Error() string {
|
||||
return fmt.Sprintf("idna: invalid label %q", e.label)
|
||||
}
|
||||
|
||||
type runeError rune
|
||||
|
||||
func (e runeError) code() string { return "P1" }
|
||||
func (e runeError) Error() string {
|
||||
return fmt.Sprintf("idna: disallowed rune %U", e)
|
||||
}
|
||||
|
||||
// process implements the algorithm described in section 4 of UTS #46,
|
||||
// see http://www.unicode.org/reports/tr46.
|
||||
func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||
var err error
|
||||
var isBidi bool
|
||||
if p.mapping != nil {
|
||||
s, isBidi, err = p.mapping(p, s)
|
||||
}
|
||||
// Remove leading empty labels.
|
||||
if p.removeLeadingDots {
|
||||
for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
|
||||
}
|
||||
}
|
||||
// TODO: allow for a quick check of the tables data.
|
||||
// It seems like we should only create this error on ToASCII, but the
|
||||
// UTS 46 conformance tests suggests we should always check this.
|
||||
if err == nil && p.verifyDNSLength && s == "" {
|
||||
err = &labelError{s, "A4"}
|
||||
}
|
||||
labels := labelIter{orig: s}
|
||||
for ; !labels.done(); labels.next() {
|
||||
label := labels.label()
|
||||
if label == "" {
|
||||
// Empty labels are not okay. The label iterator skips the last
|
||||
// label if it is empty.
|
||||
if err == nil && p.verifyDNSLength {
|
||||
err = &labelError{s, "A4"}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(label, acePrefix) {
|
||||
u, err2 := decode(label[len(acePrefix):])
|
||||
if err2 != nil {
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
// Spec says keep the old label.
|
||||
continue
|
||||
}
|
||||
isBidi = isBidi || bidirule.DirectionString(u) != bidi.LeftToRight
|
||||
labels.set(u)
|
||||
if err == nil && p.validateLabels {
|
||||
err = p.fromPuny(p, u)
|
||||
}
|
||||
if err == nil {
|
||||
// This should be called on NonTransitional, according to the
|
||||
// spec, but that currently does not have any effect. Use the
|
||||
// original profile to preserve options.
|
||||
err = p.validateLabel(u)
|
||||
}
|
||||
} else if err == nil {
|
||||
err = p.validateLabel(label)
|
||||
}
|
||||
}
|
||||
if isBidi && p.bidirule != nil && err == nil {
|
||||
for labels.reset(); !labels.done(); labels.next() {
|
||||
if !p.bidirule(labels.label()) {
|
||||
err = &labelError{s, "B"}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if toASCII {
|
||||
for labels.reset(); !labels.done(); labels.next() {
|
||||
label := labels.label()
|
||||
if !ascii(label) {
|
||||
a, err2 := encode(acePrefix, label)
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
label = a
|
||||
labels.set(a)
|
||||
}
|
||||
n := len(label)
|
||||
if p.verifyDNSLength && err == nil && (n == 0 || n > 63) {
|
||||
err = &labelError{label, "A4"}
|
||||
}
|
||||
}
|
||||
}
|
||||
s = labels.result()
|
||||
if toASCII && p.verifyDNSLength && err == nil {
|
||||
// Compute the length of the domain name minus the root label and its dot.
|
||||
n := len(s)
|
||||
if n > 0 && s[n-1] == '.' {
|
||||
n--
|
||||
}
|
||||
if len(s) < 1 || n > 253 {
|
||||
err = &labelError{s, "A4"}
|
||||
}
|
||||
}
|
||||
return s, err
|
||||
}
|
||||
|
||||
func normalize(p *Profile, s string) (mapped string, isBidi bool, err error) {
|
||||
// TODO: consider first doing a quick check to see if any of these checks
|
||||
// need to be done. This will make it slower in the general case, but
|
||||
// faster in the common case.
|
||||
mapped = norm.NFC.String(s)
|
||||
isBidi = bidirule.DirectionString(mapped) == bidi.RightToLeft
|
||||
return mapped, isBidi, nil
|
||||
}
|
||||
|
||||
func validateRegistration(p *Profile, s string) (idem string, bidi bool, err error) {
|
||||
// TODO: filter need for normalization in loop below.
|
||||
if !norm.NFC.IsNormalString(s) {
|
||||
return s, false, &labelError{s, "V1"}
|
||||
}
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
if sz == 0 {
|
||||
return s, bidi, runeError(utf8.RuneError)
|
||||
}
|
||||
bidi = bidi || info(v).isBidi(s[i:])
|
||||
// Copy bytes not copied so far.
|
||||
switch p.simplify(info(v).category()) {
|
||||
// TODO: handle the NV8 defined in the Unicode idna data set to allow
|
||||
// for strict conformance to IDNA2008.
|
||||
case valid, deviation:
|
||||
case disallowed, mapped, unknown, ignored:
|
||||
r, _ := utf8.DecodeRuneInString(s[i:])
|
||||
return s, bidi, runeError(r)
|
||||
}
|
||||
i += sz
|
||||
}
|
||||
return s, bidi, nil
|
||||
}
|
||||
|
||||
func (c info) isBidi(s string) bool {
|
||||
if !c.isMapped() {
|
||||
return c&attributesMask == rtl
|
||||
}
|
||||
// TODO: also store bidi info for mapped data. This is possible, but a bit
|
||||
// cumbersome and not for the common case.
|
||||
p, _ := bidi.LookupString(s)
|
||||
switch p.Class() {
|
||||
case bidi.R, bidi.AL, bidi.AN:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func validateAndMap(p *Profile, s string) (vm string, bidi bool, err error) {
|
||||
var (
|
||||
b []byte
|
||||
k int
|
||||
)
|
||||
// combinedInfoBits contains the or-ed bits of all runes. We use this
|
||||
// to derive the mayNeedNorm bit later. This may trigger normalization
|
||||
// overeagerly, but it will not do so in the common case. The end result
|
||||
// is another 10% saving on BenchmarkProfile for the common case.
|
||||
var combinedInfoBits info
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
if sz == 0 {
|
||||
b = append(b, s[k:i]...)
|
||||
b = append(b, "\ufffd"...)
|
||||
k = len(s)
|
||||
if err == nil {
|
||||
err = runeError(utf8.RuneError)
|
||||
}
|
||||
break
|
||||
}
|
||||
combinedInfoBits |= info(v)
|
||||
bidi = bidi || info(v).isBidi(s[i:])
|
||||
start := i
|
||||
i += sz
|
||||
// Copy bytes not copied so far.
|
||||
switch p.simplify(info(v).category()) {
|
||||
case valid:
|
||||
continue
|
||||
case disallowed:
|
||||
if err == nil {
|
||||
r, _ := utf8.DecodeRuneInString(s[start:])
|
||||
err = runeError(r)
|
||||
}
|
||||
continue
|
||||
case mapped, deviation:
|
||||
b = append(b, s[k:start]...)
|
||||
b = info(v).appendMapping(b, s[start:i])
|
||||
case ignored:
|
||||
b = append(b, s[k:start]...)
|
||||
// drop the rune
|
||||
case unknown:
|
||||
b = append(b, s[k:start]...)
|
||||
b = append(b, "\ufffd"...)
|
||||
}
|
||||
k = i
|
||||
}
|
||||
if k == 0 {
|
||||
// No changes so far.
|
||||
if combinedInfoBits&mayNeedNorm != 0 {
|
||||
s = norm.NFC.String(s)
|
||||
}
|
||||
} else {
|
||||
b = append(b, s[k:]...)
|
||||
if norm.NFC.QuickSpan(b) != len(b) {
|
||||
b = norm.NFC.Bytes(b)
|
||||
}
|
||||
// TODO: the punycode converters require strings as input.
|
||||
s = string(b)
|
||||
}
|
||||
return s, bidi, err
|
||||
}
|
||||
|
||||
// A labelIter allows iterating over domain name labels.
|
||||
type labelIter struct {
|
||||
orig string
|
||||
slice []string
|
||||
curStart int
|
||||
curEnd int
|
||||
i int
|
||||
}
|
||||
|
||||
func (l *labelIter) reset() {
|
||||
l.curStart = 0
|
||||
l.curEnd = 0
|
||||
l.i = 0
|
||||
}
|
||||
|
||||
func (l *labelIter) done() bool {
|
||||
return l.curStart >= len(l.orig)
|
||||
}
|
||||
|
||||
func (l *labelIter) result() string {
|
||||
if l.slice != nil {
|
||||
return strings.Join(l.slice, ".")
|
||||
}
|
||||
return l.orig
|
||||
}
|
||||
|
||||
func (l *labelIter) label() string {
|
||||
if l.slice != nil {
|
||||
return l.slice[l.i]
|
||||
}
|
||||
p := strings.IndexByte(l.orig[l.curStart:], '.')
|
||||
l.curEnd = l.curStart + p
|
||||
if p == -1 {
|
||||
l.curEnd = len(l.orig)
|
||||
}
|
||||
return l.orig[l.curStart:l.curEnd]
|
||||
}
|
||||
|
||||
// next sets the value to the next label. It skips the last label if it is empty.
|
||||
func (l *labelIter) next() {
|
||||
l.i++
|
||||
if l.slice != nil {
|
||||
if l.i >= len(l.slice) || l.i == len(l.slice)-1 && l.slice[l.i] == "" {
|
||||
l.curStart = len(l.orig)
|
||||
}
|
||||
} else {
|
||||
l.curStart = l.curEnd + 1
|
||||
if l.curStart == len(l.orig)-1 && l.orig[l.curStart] == '.' {
|
||||
l.curStart = len(l.orig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *labelIter) set(s string) {
|
||||
if l.slice == nil {
|
||||
l.slice = strings.Split(l.orig, ".")
|
||||
}
|
||||
l.slice[l.i] = s
|
||||
}
|
||||
|
||||
// acePrefix is the ASCII Compatible Encoding prefix.
|
||||
const acePrefix = "xn--"
|
||||
|
||||
func (p *Profile) simplify(cat category) category {
|
||||
switch cat {
|
||||
case disallowedSTD3Mapped:
|
||||
if p.useSTD3Rules {
|
||||
cat = disallowed
|
||||
} else {
|
||||
cat = mapped
|
||||
}
|
||||
case disallowedSTD3Valid:
|
||||
if p.useSTD3Rules {
|
||||
cat = disallowed
|
||||
} else {
|
||||
cat = valid
|
||||
}
|
||||
case deviation:
|
||||
if !p.transitional {
|
||||
cat = valid
|
||||
}
|
||||
case validNV8, validXV8:
|
||||
// TODO: handle V2008
|
||||
cat = valid
|
||||
}
|
||||
return cat
|
||||
}
|
||||
|
||||
func validateFromPunycode(p *Profile, s string) error {
|
||||
if !norm.NFC.IsNormalString(s) {
|
||||
return &labelError{s, "V1"}
|
||||
}
|
||||
// TODO: detect whether string may have to be normalized in the following
|
||||
// loop.
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
if sz == 0 {
|
||||
return runeError(utf8.RuneError)
|
||||
}
|
||||
if c := p.simplify(info(v).category()); c != valid && c != deviation {
|
||||
return &labelError{s, "V6"}
|
||||
}
|
||||
i += sz
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
zwnj = "\u200c"
|
||||
zwj = "\u200d"
|
||||
)
|
||||
|
||||
type joinState int8
|
||||
|
||||
const (
|
||||
stateStart joinState = iota
|
||||
stateVirama
|
||||
stateBefore
|
||||
stateBeforeVirama
|
||||
stateAfter
|
||||
stateFAIL
|
||||
)
|
||||
|
||||
var joinStates = [][numJoinTypes]joinState{
|
||||
stateStart: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
joinZWNJ: stateFAIL,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateVirama,
|
||||
},
|
||||
stateVirama: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
},
|
||||
stateBefore: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
joiningT: stateBefore,
|
||||
joinZWNJ: stateAfter,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateBeforeVirama,
|
||||
},
|
||||
stateBeforeVirama: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
joiningT: stateBefore,
|
||||
},
|
||||
stateAfter: {
|
||||
joiningL: stateFAIL,
|
||||
joiningD: stateBefore,
|
||||
joiningT: stateAfter,
|
||||
joiningR: stateStart,
|
||||
joinZWNJ: stateFAIL,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateAfter, // no-op as we can't accept joiners here
|
||||
},
|
||||
stateFAIL: {
|
||||
0: stateFAIL,
|
||||
joiningL: stateFAIL,
|
||||
joiningD: stateFAIL,
|
||||
joiningT: stateFAIL,
|
||||
joiningR: stateFAIL,
|
||||
joinZWNJ: stateFAIL,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateFAIL,
|
||||
},
|
||||
}
|
||||
|
||||
// validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are
|
||||
// already implicitly satisfied by the overall implementation.
|
||||
func (p *Profile) validateLabel(s string) (err error) {
|
||||
if s == "" {
|
||||
if p.verifyDNSLength {
|
||||
return &labelError{s, "A4"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !p.validateLabels {
|
||||
return nil
|
||||
}
|
||||
trie := p.trie // p.validateLabels is only set if trie is set.
|
||||
if len(s) > 4 && s[2] == '-' && s[3] == '-' {
|
||||
return &labelError{s, "V2"}
|
||||
}
|
||||
if s[0] == '-' || s[len(s)-1] == '-' {
|
||||
return &labelError{s, "V3"}
|
||||
}
|
||||
// TODO: merge the use of this in the trie.
|
||||
v, sz := trie.lookupString(s)
|
||||
x := info(v)
|
||||
if x.isModifier() {
|
||||
return &labelError{s, "V5"}
|
||||
}
|
||||
// Quickly return in the absence of zero-width (non) joiners.
|
||||
if strings.Index(s, zwj) == -1 && strings.Index(s, zwnj) == -1 {
|
||||
return nil
|
||||
}
|
||||
st := stateStart
|
||||
for i := 0; ; {
|
||||
jt := x.joinType()
|
||||
if s[i:i+sz] == zwj {
|
||||
jt = joinZWJ
|
||||
} else if s[i:i+sz] == zwnj {
|
||||
jt = joinZWNJ
|
||||
}
|
||||
st = joinStates[st][jt]
|
||||
if x.isViramaModifier() {
|
||||
st = joinStates[st][joinVirama]
|
||||
}
|
||||
if i += sz; i == len(s) {
|
||||
break
|
||||
}
|
||||
v, sz = trie.lookupString(s[i:])
|
||||
x = info(v)
|
||||
}
|
||||
if st == stateFAIL || st == stateAfter {
|
||||
return &labelError{s, "C"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ascii(s string) bool {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] >= utf8.RuneSelf {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
140
vendor/golang.org/x/text/internal/export/idna/idna10.0.0_test.go
generated
vendored
Normal file
140
vendor/golang.org/x/text/internal/export/idna/idna10.0.0_test.go
generated
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build go1.10
|
||||
|
||||
package idna
|
||||
|
||||
import "testing"
|
||||
|
||||
// TestLabelErrors tests strings returned in case of error. All results should
|
||||
// be identical to the reference implementation and can be verified at
|
||||
// http://unicode.org/cldr/utility/idna.jsp. The reference implementation,
|
||||
// however, seems to not display Bidi and ContextJ errors.
|
||||
//
|
||||
// In some cases the behavior of browsers is added as a comment. In all cases,
|
||||
// whenever a resolve search returns an error here, Chrome will treat the input
|
||||
// string as a search string (including those for Bidi and Context J errors),
|
||||
// unless noted otherwise.
|
||||
func TestLabelErrors(t *testing.T) {
|
||||
encode := func(s string) string { s, _ = encode(acePrefix, s); return s }
|
||||
type kind struct {
|
||||
name string
|
||||
f func(string) (string, error)
|
||||
}
|
||||
punyA := kind{"PunycodeA", punycode.ToASCII}
|
||||
resolve := kind{"ResolveA", Lookup.ToASCII}
|
||||
display := kind{"ToUnicode", Display.ToUnicode}
|
||||
p := New(VerifyDNSLength(true), MapForLookup(), BidiRule())
|
||||
lengthU := kind{"CheckLengthU", p.ToUnicode}
|
||||
lengthA := kind{"CheckLengthA", p.ToASCII}
|
||||
p = New(MapForLookup(), StrictDomainName(false))
|
||||
std3 := kind{"STD3", p.ToASCII}
|
||||
|
||||
testCases := []struct {
|
||||
kind
|
||||
input string
|
||||
want string
|
||||
wantErr string
|
||||
}{
|
||||
{lengthU, "", "", "A4"}, // From UTS 46 conformance test.
|
||||
{lengthA, "", "", "A4"},
|
||||
|
||||
{lengthU, "xn--", "", "A4"},
|
||||
{lengthU, "foo.xn--", "foo.", "A4"}, // TODO: is dropping xn-- correct?
|
||||
{lengthU, "xn--.foo", ".foo", "A4"},
|
||||
{lengthU, "foo.xn--.bar", "foo..bar", "A4"},
|
||||
|
||||
{display, "xn--", "", ""},
|
||||
{display, "foo.xn--", "foo.", ""}, // TODO: is dropping xn-- correct?
|
||||
{display, "xn--.foo", ".foo", ""},
|
||||
{display, "foo.xn--.bar", "foo..bar", ""},
|
||||
|
||||
{lengthA, "a..b", "a..b", "A4"},
|
||||
{punyA, ".b", ".b", ""},
|
||||
// For backwards compatibility, the Punycode profile does not map runes.
|
||||
{punyA, "\u3002b", "xn--b-83t", ""},
|
||||
{punyA, "..b", "..b", ""},
|
||||
|
||||
{lengthA, ".b", ".b", "A4"},
|
||||
{lengthA, "\u3002b", ".b", "A4"},
|
||||
{lengthA, "..b", "..b", "A4"},
|
||||
{lengthA, "b..", "b..", ""},
|
||||
|
||||
// Sharpened Bidi rules for Unicode 10.0.0. Apply for ALL labels in ANY
|
||||
// of the labels is RTL.
|
||||
{lengthA, "\ufe05\u3002\u3002\U0002603e\u1ce0", "..xn--t6f5138v", "A4"},
|
||||
{lengthA, "FAX\u2a77\U0001d186\u3002\U0001e942\U000e0181\u180c", "", "B6"},
|
||||
|
||||
{resolve, "a..b", "a..b", ""},
|
||||
// Note that leading dots are not stripped. This is to be consistent
|
||||
// with the Punycode profile as well as the conformance test.
|
||||
{resolve, ".b", ".b", ""},
|
||||
{resolve, "\u3002b", ".b", ""},
|
||||
{resolve, "..b", "..b", ""},
|
||||
{resolve, "b..", "b..", ""},
|
||||
{resolve, "\xed", "", "P1"},
|
||||
|
||||
// Raw punycode
|
||||
{punyA, "", "", ""},
|
||||
{punyA, "*.foo.com", "*.foo.com", ""},
|
||||
{punyA, "Foo.com", "Foo.com", ""},
|
||||
|
||||
// STD3 rules
|
||||
{display, "*.foo.com", "*.foo.com", "P1"},
|
||||
{std3, "*.foo.com", "*.foo.com", ""},
|
||||
|
||||
// Don't map U+2490 (DIGIT NINE FULL STOP). This is the behavior of
|
||||
// Chrome, Safari, and IE. Firefox will first map ⒐ to 9. and return
|
||||
// lab9.be.
|
||||
{resolve, "lab⒐be", "xn--labbe-zh9b", "P1"}, // encode("lab⒐be")
|
||||
{display, "lab⒐be", "lab⒐be", "P1"},
|
||||
|
||||
{resolve, "plan⒐faß.de", "xn--planfass-c31e.de", "P1"}, // encode("plan⒐fass") + ".de"
|
||||
{display, "Plan⒐faß.de", "plan⒐faß.de", "P1"},
|
||||
|
||||
// Chrome 54.0 recognizes the error and treats this input verbatim as a
|
||||
// search string.
|
||||
// Safari 10.0 (non-conform spec) decomposes "⒈" and computes the
|
||||
// punycode on the result using transitional mapping.
|
||||
// Firefox 49.0.1 goes haywire on this string and prints a bunch of what
|
||||
// seems to be nested punycode encodings.
|
||||
{resolve, "日本⒈co.ßßß.de", "xn--co-wuw5954azlb.ssssss.de", "P1"},
|
||||
{display, "日本⒈co.ßßß.de", "日本⒈co.ßßß.de", "P1"},
|
||||
|
||||
{resolve, "a\u200Cb", "ab", ""},
|
||||
{display, "a\u200Cb", "a\u200Cb", "C"},
|
||||
|
||||
{resolve, encode("a\u200Cb"), encode("a\u200Cb"), "C"},
|
||||
{display, "a\u200Cb", "a\u200Cb", "C"},
|
||||
|
||||
{resolve, "grﻋﺮﺑﻲ.de", "xn--gr-gtd9a1b0g.de", "B"},
|
||||
{
|
||||
// Notice how the string gets transformed, even with an error.
|
||||
// Chrome will use the original string if it finds an error, so not
|
||||
// the transformed one.
|
||||
display,
|
||||
"gr\ufecb\ufeae\ufe91\ufef2.de",
|
||||
"gr\u0639\u0631\u0628\u064a.de",
|
||||
"B",
|
||||
},
|
||||
|
||||
{resolve, "\u0671.\u03c3\u07dc", "xn--qib.xn--4xa21s", "B"}, // ٱ.σߜ
|
||||
{display, "\u0671.\u03c3\u07dc", "\u0671.\u03c3\u07dc", "B"},
|
||||
|
||||
// normalize input
|
||||
{resolve, "a\u0323\u0322", "xn--jta191l", ""}, // ạ̢
|
||||
{display, "a\u0323\u0322", "\u1ea1\u0322", ""},
|
||||
|
||||
// Non-normalized strings are not normalized when they originate from
|
||||
// punycode. Despite the error, Chrome, Safari and Firefox will attempt
|
||||
// to look up the input punycode.
|
||||
{resolve, encode("a\u0323\u0322") + ".com", "xn--a-tdbc.com", "V1"},
|
||||
{display, encode("a\u0323\u0322") + ".com", "a\u0323\u0322.com", "V1"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
doTest(t, tc.f, tc.name, tc.input, tc.want, tc.wantErr)
|
||||
}
|
||||
}
|
681
vendor/golang.org/x/text/internal/export/idna/idna9.0.0.go
generated
vendored
Normal file
681
vendor/golang.org/x/text/internal/export/idna/idna9.0.0.go
generated
vendored
Normal file
|
@ -0,0 +1,681 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.10
|
||||
//go:generate go run gen.go gen_trieval.go gen_common.go
|
||||
|
||||
// Package idna implements IDNA2008 using the compatibility processing
|
||||
// defined by UTS (Unicode Technical Standard) #46, which defines a standard to
|
||||
// deal with the transition from IDNA2003.
|
||||
//
|
||||
// IDNA2008 (Internationalized Domain Names for Applications), is defined in RFC
|
||||
// 5890, RFC 5891, RFC 5892, RFC 5893 and RFC 5894.
|
||||
// UTS #46 is defined in http://www.unicode.org/reports/tr46.
|
||||
// See http://unicode.org/cldr/utility/idna.jsp for a visualization of the
|
||||
// differences between these two standards.
|
||||
package idna // import "golang.org/x/text/internal/export/idna"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/secure/bidirule"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
// NOTE: Unlike common practice in Go APIs, the functions will return a
|
||||
// sanitized domain name in case of errors. Browsers sometimes use a partially
|
||||
// evaluated string as lookup.
|
||||
// TODO: the current error handling is, in my opinion, the least opinionated.
|
||||
// Other strategies are also viable, though:
|
||||
// Option 1) Return an empty string in case of error, but allow the user to
|
||||
// specify explicitly which errors to ignore.
|
||||
// Option 2) Return the partially evaluated string if it is itself a valid
|
||||
// string, otherwise return the empty string in case of error.
|
||||
// Option 3) Option 1 and 2.
|
||||
// Option 4) Always return an empty string for now and implement Option 1 as
|
||||
// needed, and document that the return string may not be empty in case of
|
||||
// error in the future.
|
||||
// I think Option 1 is best, but it is quite opinionated.
|
||||
|
||||
// ToASCII is a wrapper for Punycode.ToASCII.
|
||||
func ToASCII(s string) (string, error) {
|
||||
return Punycode.process(s, true)
|
||||
}
|
||||
|
||||
// ToUnicode is a wrapper for Punycode.ToUnicode.
|
||||
func ToUnicode(s string) (string, error) {
|
||||
return Punycode.process(s, false)
|
||||
}
|
||||
|
||||
// An Option configures a Profile at creation time.
|
||||
type Option func(*options)
|
||||
|
||||
// Transitional sets a Profile to use the Transitional mapping as defined in UTS
|
||||
// #46. This will cause, for example, "ß" to be mapped to "ss". Using the
|
||||
// transitional mapping provides a compromise between IDNA2003 and IDNA2008
|
||||
// compatibility. It is used by most browsers when resolving domain names. This
|
||||
// option is only meaningful if combined with MapForLookup.
|
||||
func Transitional(transitional bool) Option {
|
||||
return func(o *options) { o.transitional = true }
|
||||
}
|
||||
|
||||
// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
|
||||
// are longer than allowed by the RFC.
|
||||
func VerifyDNSLength(verify bool) Option {
|
||||
return func(o *options) { o.verifyDNSLength = verify }
|
||||
}
|
||||
|
||||
// RemoveLeadingDots removes leading label separators. Leading runes that map to
|
||||
// dots, such as U+3002 IDEOGRAPHIC FULL STOP, are removed as well.
|
||||
//
|
||||
// This is the behavior suggested by the UTS #46 and is adopted by some
|
||||
// browsers.
|
||||
func RemoveLeadingDots(remove bool) Option {
|
||||
return func(o *options) { o.removeLeadingDots = remove }
|
||||
}
|
||||
|
||||
// ValidateLabels sets whether to check the mandatory label validation criteria
|
||||
// as defined in Section 5.4 of RFC 5891. This includes testing for correct use
|
||||
// of hyphens ('-'), normalization, validity of runes, and the context rules.
|
||||
func ValidateLabels(enable bool) Option {
|
||||
return func(o *options) {
|
||||
// Don't override existing mappings, but set one that at least checks
|
||||
// normalization if it is not set.
|
||||
if o.mapping == nil && enable {
|
||||
o.mapping = normalize
|
||||
}
|
||||
o.trie = trie
|
||||
o.validateLabels = enable
|
||||
o.fromPuny = validateFromPunycode
|
||||
}
|
||||
}
|
||||
|
||||
// StrictDomainName limits the set of permissable ASCII characters to those
|
||||
// allowed in domain names as defined in RFC 1034 (A-Z, a-z, 0-9 and the
|
||||
// hyphen). This is set by default for MapForLookup and ValidateForRegistration.
|
||||
//
|
||||
// This option is useful, for instance, for browsers that allow characters
|
||||
// outside this range, for example a '_' (U+005F LOW LINE). See
|
||||
// http://www.rfc-editor.org/std/std3.txt for more details This option
|
||||
// corresponds to the UseSTD3ASCIIRules option in UTS #46.
|
||||
func StrictDomainName(use bool) Option {
|
||||
return func(o *options) {
|
||||
o.trie = trie
|
||||
o.useSTD3Rules = use
|
||||
o.fromPuny = validateFromPunycode
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: the following options pull in tables. The tables should not be linked
|
||||
// in as long as the options are not used.
|
||||
|
||||
// BidiRule enables the Bidi rule as defined in RFC 5893. Any application
|
||||
// that relies on proper validation of labels should include this rule.
|
||||
func BidiRule() Option {
|
||||
return func(o *options) { o.bidirule = bidirule.ValidString }
|
||||
}
|
||||
|
||||
// ValidateForRegistration sets validation options to verify that a given IDN is
|
||||
// properly formatted for registration as defined by Section 4 of RFC 5891.
|
||||
func ValidateForRegistration() Option {
|
||||
return func(o *options) {
|
||||
o.mapping = validateRegistration
|
||||
StrictDomainName(true)(o)
|
||||
ValidateLabels(true)(o)
|
||||
VerifyDNSLength(true)(o)
|
||||
BidiRule()(o)
|
||||
}
|
||||
}
|
||||
|
||||
// MapForLookup sets validation and mapping options such that a given IDN is
|
||||
// transformed for domain name lookup according to the requirements set out in
|
||||
// Section 5 of RFC 5891. The mappings follow the recommendations of RFC 5894,
|
||||
// RFC 5895 and UTS 46. It does not add the Bidi Rule. Use the BidiRule option
|
||||
// to add this check.
|
||||
//
|
||||
// The mappings include normalization and mapping case, width and other
|
||||
// compatibility mappings.
|
||||
func MapForLookup() Option {
|
||||
return func(o *options) {
|
||||
o.mapping = validateAndMap
|
||||
StrictDomainName(true)(o)
|
||||
ValidateLabels(true)(o)
|
||||
RemoveLeadingDots(true)(o)
|
||||
}
|
||||
}
|
||||
|
||||
type options struct {
|
||||
transitional bool
|
||||
useSTD3Rules bool
|
||||
validateLabels bool
|
||||
verifyDNSLength bool
|
||||
removeLeadingDots bool
|
||||
|
||||
trie *idnaTrie
|
||||
|
||||
// fromPuny calls validation rules when converting A-labels to U-labels.
|
||||
fromPuny func(p *Profile, s string) error
|
||||
|
||||
// mapping implements a validation and mapping step as defined in RFC 5895
|
||||
// or UTS 46, tailored to, for example, domain registration or lookup.
|
||||
mapping func(p *Profile, s string) (string, error)
|
||||
|
||||
// bidirule, if specified, checks whether s conforms to the Bidi Rule
|
||||
// defined in RFC 5893.
|
||||
bidirule func(s string) bool
|
||||
}
|
||||
|
||||
// A Profile defines the configuration of a IDNA mapper.
|
||||
type Profile struct {
|
||||
options
|
||||
}
|
||||
|
||||
func apply(o *options, opts []Option) {
|
||||
for _, f := range opts {
|
||||
f(o)
|
||||
}
|
||||
}
|
||||
|
||||
// New creates a new Profile.
|
||||
//
|
||||
// With no options, the returned Profile is the most permissive and equals the
|
||||
// Punycode Profile. Options can be passed to further restrict the Profile. The
|
||||
// MapForLookup and ValidateForRegistration options set a collection of options,
|
||||
// for lookup and registration purposes respectively, which can be tailored by
|
||||
// adding more fine-grained options, where later options override earlier
|
||||
// options.
|
||||
func New(o ...Option) *Profile {
|
||||
p := &Profile{}
|
||||
apply(&p.options, o)
|
||||
return p
|
||||
}
|
||||
|
||||
// ToASCII converts a domain or domain label to its ASCII form. For example,
|
||||
// ToASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
|
||||
// ToASCII("golang") is "golang". If an error is encountered it will return
|
||||
// an error and a (partially) processed result.
|
||||
func (p *Profile) ToASCII(s string) (string, error) {
|
||||
return p.process(s, true)
|
||||
}
|
||||
|
||||
// ToUnicode converts a domain or domain label to its Unicode form. For example,
|
||||
// ToUnicode("xn--bcher-kva.example.com") is "bücher.example.com", and
|
||||
// ToUnicode("golang") is "golang". If an error is encountered it will return
|
||||
// an error and a (partially) processed result.
|
||||
func (p *Profile) ToUnicode(s string) (string, error) {
|
||||
pp := *p
|
||||
pp.transitional = false
|
||||
return pp.process(s, false)
|
||||
}
|
||||
|
||||
// String reports a string with a description of the profile for debugging
|
||||
// purposes. The string format may change with different versions.
|
||||
func (p *Profile) String() string {
|
||||
s := ""
|
||||
if p.transitional {
|
||||
s = "Transitional"
|
||||
} else {
|
||||
s = "NonTransitional"
|
||||
}
|
||||
if p.useSTD3Rules {
|
||||
s += ":UseSTD3Rules"
|
||||
}
|
||||
if p.validateLabels {
|
||||
s += ":ValidateLabels"
|
||||
}
|
||||
if p.verifyDNSLength {
|
||||
s += ":VerifyDNSLength"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
var (
|
||||
// Punycode is a Profile that does raw punycode processing with a minimum
|
||||
// of validation.
|
||||
Punycode *Profile = punycode
|
||||
|
||||
// Lookup is the recommended profile for looking up domain names, according
|
||||
// to Section 5 of RFC 5891. The exact configuration of this profile may
|
||||
// change over time.
|
||||
Lookup *Profile = lookup
|
||||
|
||||
// Display is the recommended profile for displaying domain names.
|
||||
// The configuration of this profile may change over time.
|
||||
Display *Profile = display
|
||||
|
||||
// Registration is the recommended profile for checking whether a given
|
||||
// IDN is valid for registration, according to Section 4 of RFC 5891.
|
||||
Registration *Profile = registration
|
||||
|
||||
punycode = &Profile{}
|
||||
lookup = &Profile{options{
|
||||
transitional: true,
|
||||
useSTD3Rules: true,
|
||||
validateLabels: true,
|
||||
removeLeadingDots: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateAndMap,
|
||||
bidirule: bidirule.ValidString,
|
||||
}}
|
||||
display = &Profile{options{
|
||||
useSTD3Rules: true,
|
||||
validateLabels: true,
|
||||
removeLeadingDots: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateAndMap,
|
||||
bidirule: bidirule.ValidString,
|
||||
}}
|
||||
registration = &Profile{options{
|
||||
useSTD3Rules: true,
|
||||
validateLabels: true,
|
||||
verifyDNSLength: true,
|
||||
trie: trie,
|
||||
fromPuny: validateFromPunycode,
|
||||
mapping: validateRegistration,
|
||||
bidirule: bidirule.ValidString,
|
||||
}}
|
||||
|
||||
// TODO: profiles
|
||||
// Register: recommended for approving domain names: don't do any mappings
|
||||
// but rather reject on invalid input. Bundle or block deviation characters.
|
||||
)
|
||||
|
||||
type labelError struct{ label, code_ string }
|
||||
|
||||
func (e labelError) code() string { return e.code_ }
|
||||
func (e labelError) Error() string {
|
||||
return fmt.Sprintf("idna: invalid label %q", e.label)
|
||||
}
|
||||
|
||||
type runeError rune
|
||||
|
||||
func (e runeError) code() string { return "P1" }
|
||||
func (e runeError) Error() string {
|
||||
return fmt.Sprintf("idna: disallowed rune %U", e)
|
||||
}
|
||||
|
||||
// process implements the algorithm described in section 4 of UTS #46,
|
||||
// see http://www.unicode.org/reports/tr46.
|
||||
func (p *Profile) process(s string, toASCII bool) (string, error) {
|
||||
var err error
|
||||
if p.mapping != nil {
|
||||
s, err = p.mapping(p, s)
|
||||
}
|
||||
// Remove leading empty labels.
|
||||
if p.removeLeadingDots {
|
||||
for ; len(s) > 0 && s[0] == '.'; s = s[1:] {
|
||||
}
|
||||
}
|
||||
// It seems like we should only create this error on ToASCII, but the
|
||||
// UTS 46 conformance tests suggests we should always check this.
|
||||
if err == nil && p.verifyDNSLength && s == "" {
|
||||
err = &labelError{s, "A4"}
|
||||
}
|
||||
labels := labelIter{orig: s}
|
||||
for ; !labels.done(); labels.next() {
|
||||
label := labels.label()
|
||||
if label == "" {
|
||||
// Empty labels are not okay. The label iterator skips the last
|
||||
// label if it is empty.
|
||||
if err == nil && p.verifyDNSLength {
|
||||
err = &labelError{s, "A4"}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(label, acePrefix) {
|
||||
u, err2 := decode(label[len(acePrefix):])
|
||||
if err2 != nil {
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
// Spec says keep the old label.
|
||||
continue
|
||||
}
|
||||
labels.set(u)
|
||||
if err == nil && p.validateLabels {
|
||||
err = p.fromPuny(p, u)
|
||||
}
|
||||
if err == nil {
|
||||
// This should be called on NonTransitional, according to the
|
||||
// spec, but that currently does not have any effect. Use the
|
||||
// original profile to preserve options.
|
||||
err = p.validateLabel(u)
|
||||
}
|
||||
} else if err == nil {
|
||||
err = p.validateLabel(label)
|
||||
}
|
||||
}
|
||||
if toASCII {
|
||||
for labels.reset(); !labels.done(); labels.next() {
|
||||
label := labels.label()
|
||||
if !ascii(label) {
|
||||
a, err2 := encode(acePrefix, label)
|
||||
if err == nil {
|
||||
err = err2
|
||||
}
|
||||
label = a
|
||||
labels.set(a)
|
||||
}
|
||||
n := len(label)
|
||||
if p.verifyDNSLength && err == nil && (n == 0 || n > 63) {
|
||||
err = &labelError{label, "A4"}
|
||||
}
|
||||
}
|
||||
}
|
||||
s = labels.result()
|
||||
if toASCII && p.verifyDNSLength && err == nil {
|
||||
// Compute the length of the domain name minus the root label and its dot.
|
||||
n := len(s)
|
||||
if n > 0 && s[n-1] == '.' {
|
||||
n--
|
||||
}
|
||||
if len(s) < 1 || n > 253 {
|
||||
err = &labelError{s, "A4"}
|
||||
}
|
||||
}
|
||||
return s, err
|
||||
}
|
||||
|
||||
func normalize(p *Profile, s string) (string, error) {
|
||||
return norm.NFC.String(s), nil
|
||||
}
|
||||
|
||||
func validateRegistration(p *Profile, s string) (string, error) {
|
||||
if !norm.NFC.IsNormalString(s) {
|
||||
return s, &labelError{s, "V1"}
|
||||
}
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
// Copy bytes not copied so far.
|
||||
switch p.simplify(info(v).category()) {
|
||||
// TODO: handle the NV8 defined in the Unicode idna data set to allow
|
||||
// for strict conformance to IDNA2008.
|
||||
case valid, deviation:
|
||||
case disallowed, mapped, unknown, ignored:
|
||||
r, _ := utf8.DecodeRuneInString(s[i:])
|
||||
return s, runeError(r)
|
||||
}
|
||||
i += sz
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func validateAndMap(p *Profile, s string) (string, error) {
|
||||
var (
|
||||
err error
|
||||
b []byte
|
||||
k int
|
||||
)
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
start := i
|
||||
i += sz
|
||||
// Copy bytes not copied so far.
|
||||
switch p.simplify(info(v).category()) {
|
||||
case valid:
|
||||
continue
|
||||
case disallowed:
|
||||
if err == nil {
|
||||
r, _ := utf8.DecodeRuneInString(s[start:])
|
||||
err = runeError(r)
|
||||
}
|
||||
continue
|
||||
case mapped, deviation:
|
||||
b = append(b, s[k:start]...)
|
||||
b = info(v).appendMapping(b, s[start:i])
|
||||
case ignored:
|
||||
b = append(b, s[k:start]...)
|
||||
// drop the rune
|
||||
case unknown:
|
||||
b = append(b, s[k:start]...)
|
||||
b = append(b, "\ufffd"...)
|
||||
}
|
||||
k = i
|
||||
}
|
||||
if k == 0 {
|
||||
// No changes so far.
|
||||
s = norm.NFC.String(s)
|
||||
} else {
|
||||
b = append(b, s[k:]...)
|
||||
if norm.NFC.QuickSpan(b) != len(b) {
|
||||
b = norm.NFC.Bytes(b)
|
||||
}
|
||||
// TODO: the punycode converters require strings as input.
|
||||
s = string(b)
|
||||
}
|
||||
return s, err
|
||||
}
|
||||
|
||||
// A labelIter allows iterating over domain name labels.
|
||||
type labelIter struct {
|
||||
orig string
|
||||
slice []string
|
||||
curStart int
|
||||
curEnd int
|
||||
i int
|
||||
}
|
||||
|
||||
func (l *labelIter) reset() {
|
||||
l.curStart = 0
|
||||
l.curEnd = 0
|
||||
l.i = 0
|
||||
}
|
||||
|
||||
func (l *labelIter) done() bool {
|
||||
return l.curStart >= len(l.orig)
|
||||
}
|
||||
|
||||
func (l *labelIter) result() string {
|
||||
if l.slice != nil {
|
||||
return strings.Join(l.slice, ".")
|
||||
}
|
||||
return l.orig
|
||||
}
|
||||
|
||||
func (l *labelIter) label() string {
|
||||
if l.slice != nil {
|
||||
return l.slice[l.i]
|
||||
}
|
||||
p := strings.IndexByte(l.orig[l.curStart:], '.')
|
||||
l.curEnd = l.curStart + p
|
||||
if p == -1 {
|
||||
l.curEnd = len(l.orig)
|
||||
}
|
||||
return l.orig[l.curStart:l.curEnd]
|
||||
}
|
||||
|
||||
// next sets the value to the next label. It skips the last label if it is empty.
|
||||
func (l *labelIter) next() {
|
||||
l.i++
|
||||
if l.slice != nil {
|
||||
if l.i >= len(l.slice) || l.i == len(l.slice)-1 && l.slice[l.i] == "" {
|
||||
l.curStart = len(l.orig)
|
||||
}
|
||||
} else {
|
||||
l.curStart = l.curEnd + 1
|
||||
if l.curStart == len(l.orig)-1 && l.orig[l.curStart] == '.' {
|
||||
l.curStart = len(l.orig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *labelIter) set(s string) {
|
||||
if l.slice == nil {
|
||||
l.slice = strings.Split(l.orig, ".")
|
||||
}
|
||||
l.slice[l.i] = s
|
||||
}
|
||||
|
||||
// acePrefix is the ASCII Compatible Encoding prefix.
|
||||
const acePrefix = "xn--"
|
||||
|
||||
func (p *Profile) simplify(cat category) category {
|
||||
switch cat {
|
||||
case disallowedSTD3Mapped:
|
||||
if p.useSTD3Rules {
|
||||
cat = disallowed
|
||||
} else {
|
||||
cat = mapped
|
||||
}
|
||||
case disallowedSTD3Valid:
|
||||
if p.useSTD3Rules {
|
||||
cat = disallowed
|
||||
} else {
|
||||
cat = valid
|
||||
}
|
||||
case deviation:
|
||||
if !p.transitional {
|
||||
cat = valid
|
||||
}
|
||||
case validNV8, validXV8:
|
||||
// TODO: handle V2008
|
||||
cat = valid
|
||||
}
|
||||
return cat
|
||||
}
|
||||
|
||||
func validateFromPunycode(p *Profile, s string) error {
|
||||
if !norm.NFC.IsNormalString(s) {
|
||||
return &labelError{s, "V1"}
|
||||
}
|
||||
for i := 0; i < len(s); {
|
||||
v, sz := trie.lookupString(s[i:])
|
||||
if c := p.simplify(info(v).category()); c != valid && c != deviation {
|
||||
return &labelError{s, "V6"}
|
||||
}
|
||||
i += sz
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
zwnj = "\u200c"
|
||||
zwj = "\u200d"
|
||||
)
|
||||
|
||||
type joinState int8
|
||||
|
||||
const (
|
||||
stateStart joinState = iota
|
||||
stateVirama
|
||||
stateBefore
|
||||
stateBeforeVirama
|
||||
stateAfter
|
||||
stateFAIL
|
||||
)
|
||||
|
||||
var joinStates = [][numJoinTypes]joinState{
|
||||
stateStart: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
joinZWNJ: stateFAIL,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateVirama,
|
||||
},
|
||||
stateVirama: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
},
|
||||
stateBefore: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
joiningT: stateBefore,
|
||||
joinZWNJ: stateAfter,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateBeforeVirama,
|
||||
},
|
||||
stateBeforeVirama: {
|
||||
joiningL: stateBefore,
|
||||
joiningD: stateBefore,
|
||||
joiningT: stateBefore,
|
||||
},
|
||||
stateAfter: {
|
||||
joiningL: stateFAIL,
|
||||
joiningD: stateBefore,
|
||||
joiningT: stateAfter,
|
||||
joiningR: stateStart,
|
||||
joinZWNJ: stateFAIL,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateAfter, // no-op as we can't accept joiners here
|
||||
},
|
||||
stateFAIL: {
|
||||
0: stateFAIL,
|
||||
joiningL: stateFAIL,
|
||||
joiningD: stateFAIL,
|
||||
joiningT: stateFAIL,
|
||||
joiningR: stateFAIL,
|
||||
joinZWNJ: stateFAIL,
|
||||
joinZWJ: stateFAIL,
|
||||
joinVirama: stateFAIL,
|
||||
},
|
||||
}
|
||||
|
||||
// validateLabel validates the criteria from Section 4.1. Item 1, 4, and 6 are
|
||||
// already implicitly satisfied by the overall implementation.
|
||||
func (p *Profile) validateLabel(s string) error {
|
||||
if s == "" {
|
||||
if p.verifyDNSLength {
|
||||
return &labelError{s, "A4"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if p.bidirule != nil && !p.bidirule(s) {
|
||||
return &labelError{s, "B"}
|
||||
}
|
||||
if !p.validateLabels {
|
||||
return nil
|
||||
}
|
||||
trie := p.trie // p.validateLabels is only set if trie is set.
|
||||
if len(s) > 4 && s[2] == '-' && s[3] == '-' {
|
||||
return &labelError{s, "V2"}
|
||||
}
|
||||
if s[0] == '-' || s[len(s)-1] == '-' {
|
||||
return &labelError{s, "V3"}
|
||||
}
|
||||
// TODO: merge the use of this in the trie.
|
||||
v, sz := trie.lookupString(s)
|
||||
x := info(v)
|
||||
if x.isModifier() {
|
||||
return &labelError{s, "V5"}
|
||||
}
|
||||
// Quickly return in the absence of zero-width (non) joiners.
|
||||
if strings.Index(s, zwj) == -1 && strings.Index(s, zwnj) == -1 {
|
||||
return nil
|
||||
}
|
||||
st := stateStart
|
||||
for i := 0; ; {
|
||||
jt := x.joinType()
|
||||
if s[i:i+sz] == zwj {
|
||||
jt = joinZWJ
|
||||
} else if s[i:i+sz] == zwnj {
|
||||
jt = joinZWNJ
|
||||
}
|
||||
st = joinStates[st][jt]
|
||||
if x.isViramaModifier() {
|
||||
st = joinStates[st][joinVirama]
|
||||
}
|
||||
if i += sz; i == len(s) {
|
||||
break
|
||||
}
|
||||
v, sz = trie.lookupString(s[i:])
|
||||
x = info(v)
|
||||
}
|
||||
if st == stateFAIL || st == stateAfter {
|
||||
return &labelError{s, "C"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ascii(s string) bool {
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] >= utf8.RuneSelf {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
136
vendor/golang.org/x/text/internal/export/idna/idna9.0.0_test.go
generated
vendored
Normal file
136
vendor/golang.org/x/text/internal/export/idna/idna9.0.0_test.go
generated
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !go1.10
|
||||
|
||||
package idna
|
||||
|
||||
import "testing"
|
||||
|
||||
// TestLabelErrors tests strings returned in case of error. All results should
|
||||
// be identical to the reference implementation and can be verified at
|
||||
// http://unicode.org/cldr/utility/idna.jsp. The reference implementation,
|
||||
// however, seems to not display Bidi and ContextJ errors.
|
||||
//
|
||||
// In some cases the behavior of browsers is added as a comment. In all cases,
|
||||
// whenever a resolve search returns an error here, Chrome will treat the input
|
||||
// string as a search string (including those for Bidi and Context J errors),
|
||||
// unless noted otherwise.
|
||||
func TestLabelErrors(t *testing.T) {
|
||||
encode := func(s string) string { s, _ = encode(acePrefix, s); return s }
|
||||
type kind struct {
|
||||
name string
|
||||
f func(string) (string, error)
|
||||
}
|
||||
punyA := kind{"PunycodeA", punycode.ToASCII}
|
||||
resolve := kind{"ResolveA", Lookup.ToASCII}
|
||||
display := kind{"ToUnicode", Display.ToUnicode}
|
||||
p := New(VerifyDNSLength(true), MapForLookup(), BidiRule())
|
||||
lengthU := kind{"CheckLengthU", p.ToUnicode}
|
||||
lengthA := kind{"CheckLengthA", p.ToASCII}
|
||||
p = New(MapForLookup(), StrictDomainName(false))
|
||||
std3 := kind{"STD3", p.ToASCII}
|
||||
|
||||
testCases := []struct {
|
||||
kind
|
||||
input string
|
||||
want string
|
||||
wantErr string
|
||||
}{
|
||||
{lengthU, "", "", "A4"}, // From UTS 46 conformance test.
|
||||
{lengthA, "", "", "A4"},
|
||||
|
||||
{lengthU, "xn--", "", "A4"},
|
||||
{lengthU, "foo.xn--", "foo.", "A4"}, // TODO: is dropping xn-- correct?
|
||||
{lengthU, "xn--.foo", ".foo", "A4"},
|
||||
{lengthU, "foo.xn--.bar", "foo..bar", "A4"},
|
||||
|
||||
{display, "xn--", "", ""},
|
||||
{display, "foo.xn--", "foo.", ""}, // TODO: is dropping xn-- correct?
|
||||
{display, "xn--.foo", ".foo", ""},
|
||||
{display, "foo.xn--.bar", "foo..bar", ""},
|
||||
|
||||
{lengthA, "a..b", "a..b", "A4"},
|
||||
{punyA, ".b", ".b", ""},
|
||||
// For backwards compatibility, the Punycode profile does not map runes.
|
||||
{punyA, "\u3002b", "xn--b-83t", ""},
|
||||
{punyA, "..b", "..b", ""},
|
||||
// Only strip leading empty labels for certain profiles. Stripping
|
||||
// leading empty labels here but not for "empty" punycode above seems
|
||||
// inconsistent, but seems to be applied by both the conformance test
|
||||
// and Chrome. So we turn it off by default, support it as an option,
|
||||
// and enable it in profiles where it seems commonplace.
|
||||
{lengthA, ".b", "b", ""},
|
||||
{lengthA, "\u3002b", "b", ""},
|
||||
{lengthA, "..b", "b", ""},
|
||||
{lengthA, "b..", "b..", ""},
|
||||
|
||||
{resolve, "a..b", "a..b", ""},
|
||||
{resolve, ".b", "b", ""},
|
||||
{resolve, "\u3002b", "b", ""},
|
||||
{resolve, "..b", "b", ""},
|
||||
{resolve, "b..", "b..", ""},
|
||||
|
||||
// Raw punycode
|
||||
{punyA, "", "", ""},
|
||||
{punyA, "*.foo.com", "*.foo.com", ""},
|
||||
{punyA, "Foo.com", "Foo.com", ""},
|
||||
|
||||
// STD3 rules
|
||||
{display, "*.foo.com", "*.foo.com", "P1"},
|
||||
{std3, "*.foo.com", "*.foo.com", ""},
|
||||
|
||||
// Don't map U+2490 (DIGIT NINE FULL STOP). This is the behavior of
|
||||
// Chrome, Safari, and IE. Firefox will first map ⒐ to 9. and return
|
||||
// lab9.be.
|
||||
{resolve, "lab⒐be", "xn--labbe-zh9b", "P1"}, // encode("lab⒐be")
|
||||
{display, "lab⒐be", "lab⒐be", "P1"},
|
||||
|
||||
{resolve, "plan⒐faß.de", "xn--planfass-c31e.de", "P1"}, // encode("plan⒐fass") + ".de"
|
||||
{display, "Plan⒐faß.de", "plan⒐faß.de", "P1"},
|
||||
|
||||
// Chrome 54.0 recognizes the error and treats this input verbatim as a
|
||||
// search string.
|
||||
// Safari 10.0 (non-conform spec) decomposes "⒈" and computes the
|
||||
// punycode on the result using transitional mapping.
|
||||
// Firefox 49.0.1 goes haywire on this string and prints a bunch of what
|
||||
// seems to be nested punycode encodings.
|
||||
{resolve, "日本⒈co.ßßß.de", "xn--co-wuw5954azlb.ssssss.de", "P1"},
|
||||
{display, "日本⒈co.ßßß.de", "日本⒈co.ßßß.de", "P1"},
|
||||
|
||||
{resolve, "a\u200Cb", "ab", ""},
|
||||
{display, "a\u200Cb", "a\u200Cb", "C"},
|
||||
|
||||
{resolve, encode("a\u200Cb"), encode("a\u200Cb"), "C"},
|
||||
{display, "a\u200Cb", "a\u200Cb", "C"},
|
||||
|
||||
{resolve, "grﻋﺮﺑﻲ.de", "xn--gr-gtd9a1b0g.de", "B"},
|
||||
{
|
||||
// Notice how the string gets transformed, even with an error.
|
||||
// Chrome will use the original string if it finds an error, so not
|
||||
// the transformed one.
|
||||
display,
|
||||
"gr\ufecb\ufeae\ufe91\ufef2.de",
|
||||
"gr\u0639\u0631\u0628\u064a.de",
|
||||
"B",
|
||||
},
|
||||
|
||||
{resolve, "\u0671.\u03c3\u07dc", "xn--qib.xn--4xa21s", "B"}, // ٱ.σߜ
|
||||
{display, "\u0671.\u03c3\u07dc", "\u0671.\u03c3\u07dc", "B"},
|
||||
|
||||
// normalize input
|
||||
{resolve, "a\u0323\u0322", "xn--jta191l", ""}, // ạ̢
|
||||
{display, "a\u0323\u0322", "\u1ea1\u0322", ""},
|
||||
|
||||
// Non-normalized strings are not normalized when they originate from
|
||||
// punycode. Despite the error, Chrome, Safari and Firefox will attempt
|
||||
// to look up the input punycode.
|
||||
{resolve, encode("a\u0323\u0322") + ".com", "xn--a-tdbc.com", "V1"},
|
||||
{display, encode("a\u0323\u0322") + ".com", "a\u0323\u0322.com", "V1"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
doTest(t, tc.f, tc.name, tc.input, tc.want, tc.wantErr)
|
||||
}
|
||||
}
|
178
vendor/golang.org/x/text/internal/export/idna/idna_test.go
generated
vendored
Normal file
178
vendor/golang.org/x/text/internal/export/idna/idna_test.go
generated
vendored
Normal file
|
@ -0,0 +1,178 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package idna
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/testtext"
|
||||
"golang.org/x/text/internal/ucd"
|
||||
)
|
||||
|
||||
func TestAllocToUnicode(t *testing.T) {
|
||||
avg := testtext.AllocsPerRun(1000, func() {
|
||||
ToUnicode("www.golang.org")
|
||||
})
|
||||
if avg > 0 {
|
||||
t.Errorf("got %f; want 0", avg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocToASCII(t *testing.T) {
|
||||
avg := testtext.AllocsPerRun(1000, func() {
|
||||
ToASCII("www.golang.org")
|
||||
})
|
||||
if avg > 0 {
|
||||
t.Errorf("got %f; want 0", avg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProfiles(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
want, got *Profile
|
||||
}{
|
||||
{"Punycode", punycode, New()},
|
||||
{"Registration", registration, New(ValidateForRegistration())},
|
||||
{"Registration", registration, New(
|
||||
ValidateForRegistration(),
|
||||
VerifyDNSLength(true),
|
||||
BidiRule(),
|
||||
)},
|
||||
{"Lookup", lookup, New(MapForLookup(), BidiRule(), Transitional(true))},
|
||||
{"Display", display, New(MapForLookup(), BidiRule())},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
// Functions are not comparable, but the printed version will include
|
||||
// their pointers.
|
||||
got := fmt.Sprintf("%#v", tc.got)
|
||||
want := fmt.Sprintf("%#v", tc.want)
|
||||
if got != want {
|
||||
t.Errorf("%s: \ngot %#v,\nwant %#v", tc.name, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// doTest performs a single test f(input) and verifies that the output matches
|
||||
// out and that the returned error is expected. The errors string contains
|
||||
// all allowed error codes as categorized in
|
||||
// http://www.unicode.org/Public/idna/9.0.0/IdnaTest.txt:
|
||||
// P: Processing
|
||||
// V: Validity
|
||||
// A: to ASCII
|
||||
// B: Bidi
|
||||
// C: Context J
|
||||
func doTest(t *testing.T, f func(string) (string, error), name, input, want, errors string) {
|
||||
errors = strings.Trim(errors, "[]")
|
||||
test := "ok"
|
||||
if errors != "" {
|
||||
test = "err:" + errors
|
||||
}
|
||||
// Replace some of the escape sequences to make it easier to single out
|
||||
// tests on the command name.
|
||||
in := strings.Trim(strconv.QuoteToASCII(input), `"`)
|
||||
in = strings.Replace(in, `\u`, "#", -1)
|
||||
in = strings.Replace(in, `\U`, "#", -1)
|
||||
name = fmt.Sprintf("%s/%s/%s", name, in, test)
|
||||
|
||||
testtext.Run(t, name, func(t *testing.T) {
|
||||
got, err := f(input)
|
||||
|
||||
if err != nil {
|
||||
code := err.(interface {
|
||||
code() string
|
||||
}).code()
|
||||
if strings.Index(errors, code) == -1 {
|
||||
t.Errorf("error %q not in set of expected errors {%v}", code, errors)
|
||||
}
|
||||
} else if errors != "" {
|
||||
t.Errorf("no errors; want error in {%v}", errors)
|
||||
}
|
||||
|
||||
if want != "" && got != want {
|
||||
t.Errorf(`string: got %+q; want %+q`, got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestConformance(t *testing.T) {
|
||||
testtext.SkipIfNotLong(t)
|
||||
|
||||
r := gen.OpenUnicodeFile("idna", "", "IdnaTest.txt")
|
||||
defer r.Close()
|
||||
|
||||
section := "main"
|
||||
started := false
|
||||
p := ucd.New(r, ucd.CommentHandler(func(s string) {
|
||||
if started {
|
||||
section = strings.ToLower(strings.Split(s, " ")[0])
|
||||
}
|
||||
}))
|
||||
transitional := New(Transitional(true), VerifyDNSLength(true), BidiRule(), MapForLookup())
|
||||
nonTransitional := New(VerifyDNSLength(true), BidiRule(), MapForLookup())
|
||||
for p.Next() {
|
||||
started = true
|
||||
|
||||
// What to test
|
||||
profiles := []*Profile{}
|
||||
switch p.String(0) {
|
||||
case "T":
|
||||
profiles = append(profiles, transitional)
|
||||
case "N":
|
||||
profiles = append(profiles, nonTransitional)
|
||||
case "B":
|
||||
profiles = append(profiles, transitional)
|
||||
profiles = append(profiles, nonTransitional)
|
||||
}
|
||||
|
||||
src := unescape(p.String(1))
|
||||
|
||||
wantToUnicode := unescape(p.String(2))
|
||||
if wantToUnicode == "" {
|
||||
wantToUnicode = src
|
||||
}
|
||||
wantToASCII := unescape(p.String(3))
|
||||
if wantToASCII == "" {
|
||||
wantToASCII = wantToUnicode
|
||||
}
|
||||
wantErrToUnicode := ""
|
||||
if strings.HasPrefix(wantToUnicode, "[") {
|
||||
wantErrToUnicode = wantToUnicode
|
||||
wantToUnicode = ""
|
||||
}
|
||||
wantErrToASCII := ""
|
||||
if strings.HasPrefix(wantToASCII, "[") {
|
||||
wantErrToASCII = wantToASCII
|
||||
wantToASCII = ""
|
||||
}
|
||||
|
||||
// TODO: also do IDNA tests.
|
||||
// invalidInIDNA2008 := p.String(4) == "NV8"
|
||||
|
||||
for _, p := range profiles {
|
||||
name := fmt.Sprintf("%s:%s", section, p)
|
||||
doTest(t, p.ToUnicode, name+":ToUnicode", src, wantToUnicode, wantErrToUnicode)
|
||||
doTest(t, p.ToASCII, name+":ToASCII", src, wantToASCII, wantErrToASCII)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func unescape(s string) string {
|
||||
s, err := strconv.Unquote(`"` + s + `"`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func BenchmarkProfile(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Lookup.ToASCII("www.yahoogle.com")
|
||||
}
|
||||
}
|
201
vendor/golang.org/x/text/internal/export/idna/punycode.go
generated
vendored
Normal file
201
vendor/golang.org/x/text/internal/export/idna/punycode.go
generated
vendored
Normal file
|
@ -0,0 +1,201 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package idna
|
||||
|
||||
// This file implements the Punycode algorithm from RFC 3492.
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// These parameter values are specified in section 5.
|
||||
//
|
||||
// All computation is done with int32s, so that overflow behavior is identical
|
||||
// regardless of whether int is 32-bit or 64-bit.
|
||||
const (
|
||||
base int32 = 36
|
||||
damp int32 = 700
|
||||
initialBias int32 = 72
|
||||
initialN int32 = 128
|
||||
skew int32 = 38
|
||||
tmax int32 = 26
|
||||
tmin int32 = 1
|
||||
)
|
||||
|
||||
func punyError(s string) error { return &labelError{s, "A3"} }
|
||||
|
||||
// decode decodes a string as specified in section 6.2.
|
||||
func decode(encoded string) (string, error) {
|
||||
if encoded == "" {
|
||||
return "", nil
|
||||
}
|
||||
pos := 1 + strings.LastIndex(encoded, "-")
|
||||
if pos == 1 {
|
||||
return "", punyError(encoded)
|
||||
}
|
||||
if pos == len(encoded) {
|
||||
return encoded[:len(encoded)-1], nil
|
||||
}
|
||||
output := make([]rune, 0, len(encoded))
|
||||
if pos != 0 {
|
||||
for _, r := range encoded[:pos-1] {
|
||||
output = append(output, r)
|
||||
}
|
||||
}
|
||||
i, n, bias := int32(0), initialN, initialBias
|
||||
for pos < len(encoded) {
|
||||
oldI, w := i, int32(1)
|
||||
for k := base; ; k += base {
|
||||
if pos == len(encoded) {
|
||||
return "", punyError(encoded)
|
||||
}
|
||||
digit, ok := decodeDigit(encoded[pos])
|
||||
if !ok {
|
||||
return "", punyError(encoded)
|
||||
}
|
||||
pos++
|
||||
i += digit * w
|
||||
if i < 0 {
|
||||
return "", punyError(encoded)
|
||||
}
|
||||
t := k - bias
|
||||
if t < tmin {
|
||||
t = tmin
|
||||
} else if t > tmax {
|
||||
t = tmax
|
||||
}
|
||||
if digit < t {
|
||||
break
|
||||
}
|
||||
w *= base - t
|
||||
if w >= math.MaxInt32/base {
|
||||
return "", punyError(encoded)
|
||||
}
|
||||
}
|
||||
x := int32(len(output) + 1)
|
||||
bias = adapt(i-oldI, x, oldI == 0)
|
||||
n += i / x
|
||||
i %= x
|
||||
if n > utf8.MaxRune || len(output) >= 1024 {
|
||||
return "", punyError(encoded)
|
||||
}
|
||||
output = append(output, 0)
|
||||
copy(output[i+1:], output[i:])
|
||||
output[i] = n
|
||||
i++
|
||||
}
|
||||
return string(output), nil
|
||||
}
|
||||
|
||||
// encode encodes a string as specified in section 6.3 and prepends prefix to
|
||||
// the result.
|
||||
//
|
||||
// The "while h < length(input)" line in the specification becomes "for
|
||||
// remaining != 0" in the Go code, because len(s) in Go is in bytes, not runes.
|
||||
func encode(prefix, s string) (string, error) {
|
||||
output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
|
||||
copy(output, prefix)
|
||||
delta, n, bias := int32(0), initialN, initialBias
|
||||
b, remaining := int32(0), int32(0)
|
||||
for _, r := range s {
|
||||
if r < 0x80 {
|
||||
b++
|
||||
output = append(output, byte(r))
|
||||
} else {
|
||||
remaining++
|
||||
}
|
||||
}
|
||||
h := b
|
||||
if b > 0 {
|
||||
output = append(output, '-')
|
||||
}
|
||||
for remaining != 0 {
|
||||
m := int32(0x7fffffff)
|
||||
for _, r := range s {
|
||||
if m > r && r >= n {
|
||||
m = r
|
||||
}
|
||||
}
|
||||
delta += (m - n) * (h + 1)
|
||||
if delta < 0 {
|
||||
return "", punyError(s)
|
||||
}
|
||||
n = m
|
||||
for _, r := range s {
|
||||
if r < n {
|
||||
delta++
|
||||
if delta < 0 {
|
||||
return "", punyError(s)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if r > n {
|
||||
continue
|
||||
}
|
||||
q := delta
|
||||
for k := base; ; k += base {
|
||||
t := k - bias
|
||||
if t < tmin {
|
||||
t = tmin
|
||||
} else if t > tmax {
|
||||
t = tmax
|
||||
}
|
||||
if q < t {
|
||||
break
|
||||
}
|
||||
output = append(output, encodeDigit(t+(q-t)%(base-t)))
|
||||
q = (q - t) / (base - t)
|
||||
}
|
||||
output = append(output, encodeDigit(q))
|
||||
bias = adapt(delta, h+1, h == b)
|
||||
delta = 0
|
||||
h++
|
||||
remaining--
|
||||
}
|
||||
delta++
|
||||
n++
|
||||
}
|
||||
return string(output), nil
|
||||
}
|
||||
|
||||
func decodeDigit(x byte) (digit int32, ok bool) {
|
||||
switch {
|
||||
case '0' <= x && x <= '9':
|
||||
return int32(x - ('0' - 26)), true
|
||||
case 'A' <= x && x <= 'Z':
|
||||
return int32(x - 'A'), true
|
||||
case 'a' <= x && x <= 'z':
|
||||
return int32(x - 'a'), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func encodeDigit(digit int32) byte {
|
||||
switch {
|
||||
case 0 <= digit && digit < 26:
|
||||
return byte(digit + 'a')
|
||||
case 26 <= digit && digit < 36:
|
||||
return byte(digit + ('0' - 26))
|
||||
}
|
||||
panic("idna: internal error in punycode encoding")
|
||||
}
|
||||
|
||||
// adapt is the bias adaptation function specified in section 6.1.
|
||||
func adapt(delta, numPoints int32, firstTime bool) int32 {
|
||||
if firstTime {
|
||||
delta /= damp
|
||||
} else {
|
||||
delta /= 2
|
||||
}
|
||||
delta += delta / numPoints
|
||||
k := int32(0)
|
||||
for delta > ((base-tmin)*tmax)/2 {
|
||||
delta /= base - tmin
|
||||
k += base
|
||||
}
|
||||
return k + (base-tmin+1)*delta/(delta+skew)
|
||||
}
|
198
vendor/golang.org/x/text/internal/export/idna/punycode_test.go
generated
vendored
Normal file
198
vendor/golang.org/x/text/internal/export/idna/punycode_test.go
generated
vendored
Normal file
|
@ -0,0 +1,198 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package idna
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var punycodeTestCases = [...]struct {
|
||||
s, encoded string
|
||||
}{
|
||||
{"", ""},
|
||||
{"-", "--"},
|
||||
{"-a", "-a-"},
|
||||
{"-a-", "-a--"},
|
||||
{"a", "a-"},
|
||||
{"a-", "a--"},
|
||||
{"a-b", "a-b-"},
|
||||
{"books", "books-"},
|
||||
{"bücher", "bcher-kva"},
|
||||
{"Hello世界", "Hello-ck1hg65u"},
|
||||
{"ü", "tda"},
|
||||
{"üý", "tdac"},
|
||||
|
||||
// The test cases below come from RFC 3492 section 7.1 with Errata 3026.
|
||||
{
|
||||
// (A) Arabic (Egyptian).
|
||||
"\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644" +
|
||||
"\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F",
|
||||
"egbpdaj6bu4bxfgehfvwxn",
|
||||
},
|
||||
{
|
||||
// (B) Chinese (simplified).
|
||||
"\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2D\u6587",
|
||||
"ihqwcrb4cv8a8dqg056pqjye",
|
||||
},
|
||||
{
|
||||
// (C) Chinese (traditional).
|
||||
"\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587",
|
||||
"ihqwctvzc91f659drss3x8bo0yb",
|
||||
},
|
||||
{
|
||||
// (D) Czech.
|
||||
"\u0050\u0072\u006F\u010D\u0070\u0072\u006F\u0073\u0074" +
|
||||
"\u011B\u006E\u0065\u006D\u006C\u0075\u0076\u00ED\u010D" +
|
||||
"\u0065\u0073\u006B\u0079",
|
||||
"Proprostnemluvesky-uyb24dma41a",
|
||||
},
|
||||
{
|
||||
// (E) Hebrew.
|
||||
"\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8" +
|
||||
"\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2" +
|
||||
"\u05D1\u05E8\u05D9\u05EA",
|
||||
"4dbcagdahymbxekheh6e0a7fei0b",
|
||||
},
|
||||
{
|
||||
// (F) Hindi (Devanagari).
|
||||
"\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D" +
|
||||
"\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939" +
|
||||
"\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947" +
|
||||
"\u0939\u0948\u0902",
|
||||
"i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd",
|
||||
},
|
||||
{
|
||||
// (G) Japanese (kanji and hiragana).
|
||||
"\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092" +
|
||||
"\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B",
|
||||
"n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa",
|
||||
},
|
||||
{
|
||||
// (H) Korean (Hangul syllables).
|
||||
"\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774" +
|
||||
"\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74" +
|
||||
"\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C",
|
||||
"989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5j" +
|
||||
"psd879ccm6fea98c",
|
||||
},
|
||||
{
|
||||
// (I) Russian (Cyrillic).
|
||||
"\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E" +
|
||||
"\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440" +
|
||||
"\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A" +
|
||||
"\u0438",
|
||||
"b1abfaaepdrnnbgefbadotcwatmq2g4l",
|
||||
},
|
||||
{
|
||||
// (J) Spanish.
|
||||
"\u0050\u006F\u0072\u0071\u0075\u00E9\u006E\u006F\u0070" +
|
||||
"\u0075\u0065\u0064\u0065\u006E\u0073\u0069\u006D\u0070" +
|
||||
"\u006C\u0065\u006D\u0065\u006E\u0074\u0065\u0068\u0061" +
|
||||
"\u0062\u006C\u0061\u0072\u0065\u006E\u0045\u0073\u0070" +
|
||||
"\u0061\u00F1\u006F\u006C",
|
||||
"PorqunopuedensimplementehablarenEspaol-fmd56a",
|
||||
},
|
||||
{
|
||||
// (K) Vietnamese.
|
||||
"\u0054\u1EA1\u0069\u0073\u0061\u006F\u0068\u1ECD\u006B" +
|
||||
"\u0068\u00F4\u006E\u0067\u0074\u0068\u1EC3\u0063\u0068" +
|
||||
"\u1EC9\u006E\u00F3\u0069\u0074\u0069\u1EBF\u006E\u0067" +
|
||||
"\u0056\u0069\u1EC7\u0074",
|
||||
"TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g",
|
||||
},
|
||||
{
|
||||
// (L) 3<nen>B<gumi><kinpachi><sensei>.
|
||||
"\u0033\u5E74\u0042\u7D44\u91D1\u516B\u5148\u751F",
|
||||
"3B-ww4c5e180e575a65lsy2b",
|
||||
},
|
||||
{
|
||||
// (M) <amuro><namie>-with-SUPER-MONKEYS.
|
||||
"\u5B89\u5BA4\u5948\u7F8E\u6075\u002D\u0077\u0069\u0074" +
|
||||
"\u0068\u002D\u0053\u0055\u0050\u0045\u0052\u002D\u004D" +
|
||||
"\u004F\u004E\u004B\u0045\u0059\u0053",
|
||||
"-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n",
|
||||
},
|
||||
{
|
||||
// (N) Hello-Another-Way-<sorezore><no><basho>.
|
||||
"\u0048\u0065\u006C\u006C\u006F\u002D\u0041\u006E\u006F" +
|
||||
"\u0074\u0068\u0065\u0072\u002D\u0057\u0061\u0079\u002D" +
|
||||
"\u305D\u308C\u305E\u308C\u306E\u5834\u6240",
|
||||
"Hello-Another-Way--fc4qua05auwb3674vfr0b",
|
||||
},
|
||||
{
|
||||
// (O) <hitotsu><yane><no><shita>2.
|
||||
"\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B\u0032",
|
||||
"2-u9tlzr9756bt3uc0v",
|
||||
},
|
||||
{
|
||||
// (P) Maji<de>Koi<suru>5<byou><mae>
|
||||
"\u004D\u0061\u006A\u0069\u3067\u004B\u006F\u0069\u3059" +
|
||||
"\u308B\u0035\u79D2\u524D",
|
||||
"MajiKoi5-783gue6qz075azm5e",
|
||||
},
|
||||
{
|
||||
// (Q) <pafii>de<runba>
|
||||
"\u30D1\u30D5\u30A3\u30FC\u0064\u0065\u30EB\u30F3\u30D0",
|
||||
"de-jg4avhby1noc0d",
|
||||
},
|
||||
{
|
||||
// (R) <sono><supiido><de>
|
||||
"\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067",
|
||||
"d9juau41awczczp",
|
||||
},
|
||||
{
|
||||
// (S) -> $1.00 <-
|
||||
"\u002D\u003E\u0020\u0024\u0031\u002E\u0030\u0030\u0020" +
|
||||
"\u003C\u002D",
|
||||
"-> $1.00 <--",
|
||||
},
|
||||
}
|
||||
|
||||
func TestPunycode(t *testing.T) {
|
||||
for _, tc := range punycodeTestCases {
|
||||
if got, err := decode(tc.encoded); err != nil {
|
||||
t.Errorf("decode(%q): %v", tc.encoded, err)
|
||||
} else if got != tc.s {
|
||||
t.Errorf("decode(%q): got %q, want %q", tc.encoded, got, tc.s)
|
||||
}
|
||||
|
||||
if got, err := encode("", tc.s); err != nil {
|
||||
t.Errorf(`encode("", %q): %v`, tc.s, err)
|
||||
} else if got != tc.encoded {
|
||||
t.Errorf(`encode("", %q): got %q, want %q`, tc.s, got, tc.encoded)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var punycodeErrorTestCases = [...]string{
|
||||
"decode -", // A sole '-' is invalid.
|
||||
"decode foo\x00bar", // '\x00' is not in [0-9A-Za-z].
|
||||
"decode foo#bar", // '#' is not in [0-9A-Za-z].
|
||||
"decode foo\u00A3bar", // '\u00A3' is not in [0-9A-Za-z].
|
||||
"decode 9", // "9a" decodes to codepoint \u00A3; "9" is truncated.
|
||||
"decode 99999a", // "99999a" decodes to codepoint \U0048A3C1, which is > \U0010FFFF.
|
||||
"decode 9999999999a", // "9999999999a" overflows the int32 calculation.
|
||||
|
||||
"encode " + strings.Repeat("x", 65536) + "\uff00", // int32 overflow.
|
||||
}
|
||||
|
||||
func TestPunycodeErrors(t *testing.T) {
|
||||
for _, tc := range punycodeErrorTestCases {
|
||||
var err error
|
||||
switch {
|
||||
case strings.HasPrefix(tc, "decode "):
|
||||
_, err = decode(tc[7:])
|
||||
case strings.HasPrefix(tc, "encode "):
|
||||
_, err = encode("", tc[7:])
|
||||
}
|
||||
if err == nil {
|
||||
if len(tc) > 256 {
|
||||
tc = tc[:100] + "..." + tc[len(tc)-100:]
|
||||
}
|
||||
t.Errorf("no error for %s", tc)
|
||||
}
|
||||
}
|
||||
}
|
4559
vendor/golang.org/x/text/internal/export/idna/tables10.0.0.go
generated
vendored
Normal file
4559
vendor/golang.org/x/text/internal/export/idna/tables10.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
4486
vendor/golang.org/x/text/internal/export/idna/tables9.0.0.go
generated
vendored
Normal file
4486
vendor/golang.org/x/text/internal/export/idna/tables9.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
70
vendor/golang.org/x/text/internal/export/idna/trie.go
generated
vendored
Normal file
70
vendor/golang.org/x/text/internal/export/idna/trie.go
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package idna
|
||||
|
||||
// appendMapping appends the mapping for the respective rune. isMapped must be
|
||||
// true. A mapping is a categorization of a rune as defined in UTS #46.
|
||||
func (c info) appendMapping(b []byte, s string) []byte {
|
||||
index := int(c >> indexShift)
|
||||
if c&xorBit == 0 {
|
||||
s := mappings[index:]
|
||||
return append(b, s[1:s[0]+1]...)
|
||||
}
|
||||
b = append(b, s...)
|
||||
if c&inlineXOR == inlineXOR {
|
||||
// TODO: support and handle two-byte inline masks
|
||||
b[len(b)-1] ^= byte(index)
|
||||
} else {
|
||||
for p := len(b) - int(xorData[index]); p < len(b); p++ {
|
||||
index++
|
||||
b[p] ^= xorData[index]
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// Sparse block handling code.
|
||||
|
||||
type valueRange struct {
|
||||
value uint16 // header: value:stride
|
||||
lo, hi byte // header: lo:n
|
||||
}
|
||||
|
||||
type sparseBlocks struct {
|
||||
values []valueRange
|
||||
offset []uint16
|
||||
}
|
||||
|
||||
var idnaSparse = sparseBlocks{
|
||||
values: idnaSparseValues[:],
|
||||
offset: idnaSparseOffset[:],
|
||||
}
|
||||
|
||||
// Don't use newIdnaTrie to avoid unconditional linking in of the table.
|
||||
var trie = &idnaTrie{}
|
||||
|
||||
// lookup determines the type of block n and looks up the value for b.
|
||||
// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
|
||||
// is a list of ranges with an accompanying value. Given a matching range r,
|
||||
// the value for b is by r.value + (b - r.lo) * stride.
|
||||
func (t *sparseBlocks) lookup(n uint32, b byte) uint16 {
|
||||
offset := t.offset[n]
|
||||
header := t.values[offset]
|
||||
lo := offset + 1
|
||||
hi := lo + uint16(header.lo)
|
||||
for lo < hi {
|
||||
m := lo + (hi-lo)/2
|
||||
r := t.values[m]
|
||||
if r.lo <= b && b <= r.hi {
|
||||
return r.value + uint16(b-r.lo)*header.value
|
||||
}
|
||||
if b < r.lo {
|
||||
hi = m
|
||||
} else {
|
||||
lo = m + 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
119
vendor/golang.org/x/text/internal/export/idna/trieval.go
generated
vendored
Normal file
119
vendor/golang.org/x/text/internal/export/idna/trieval.go
generated
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package idna
|
||||
|
||||
// This file contains definitions for interpreting the trie value of the idna
|
||||
// trie generated by "go run gen*.go". It is shared by both the generator
|
||||
// program and the resultant package. Sharing is achieved by the generator
|
||||
// copying gen_trieval.go to trieval.go and changing what's above this comment.
|
||||
|
||||
// info holds information from the IDNA mapping table for a single rune. It is
|
||||
// the value returned by a trie lookup. In most cases, all information fits in
|
||||
// a 16-bit value. For mappings, this value may contain an index into a slice
|
||||
// with the mapped string. Such mappings can consist of the actual mapped value
|
||||
// or an XOR pattern to be applied to the bytes of the UTF8 encoding of the
|
||||
// input rune. This technique is used by the cases packages and reduces the
|
||||
// table size significantly.
|
||||
//
|
||||
// The per-rune values have the following format:
|
||||
//
|
||||
// if mapped {
|
||||
// if inlinedXOR {
|
||||
// 15..13 inline XOR marker
|
||||
// 12..11 unused
|
||||
// 10..3 inline XOR mask
|
||||
// } else {
|
||||
// 15..3 index into xor or mapping table
|
||||
// }
|
||||
// } else {
|
||||
// 15..14 unused
|
||||
// 13 mayNeedNorm
|
||||
// 12..11 attributes
|
||||
// 10..8 joining type
|
||||
// 7..3 category type
|
||||
// }
|
||||
// 2 use xor pattern
|
||||
// 1..0 mapped category
|
||||
//
|
||||
// See the definitions below for a more detailed description of the various
|
||||
// bits.
|
||||
type info uint16
|
||||
|
||||
const (
|
||||
catSmallMask = 0x3
|
||||
catBigMask = 0xF8
|
||||
indexShift = 3
|
||||
xorBit = 0x4 // interpret the index as an xor pattern
|
||||
inlineXOR = 0xE000 // These bits are set if the XOR pattern is inlined.
|
||||
|
||||
joinShift = 8
|
||||
joinMask = 0x07
|
||||
|
||||
// Attributes
|
||||
attributesMask = 0x1800
|
||||
viramaModifier = 0x1800
|
||||
modifier = 0x1000
|
||||
rtl = 0x0800
|
||||
|
||||
mayNeedNorm = 0x2000
|
||||
)
|
||||
|
||||
// A category corresponds to a category defined in the IDNA mapping table.
|
||||
type category uint16
|
||||
|
||||
const (
|
||||
unknown category = 0 // not currently defined in unicode.
|
||||
mapped category = 1
|
||||
disallowedSTD3Mapped category = 2
|
||||
deviation category = 3
|
||||
)
|
||||
|
||||
const (
|
||||
valid category = 0x08
|
||||
validNV8 category = 0x18
|
||||
validXV8 category = 0x28
|
||||
disallowed category = 0x40
|
||||
disallowedSTD3Valid category = 0x80
|
||||
ignored category = 0xC0
|
||||
)
|
||||
|
||||
// join types and additional rune information
|
||||
const (
|
||||
joiningL = (iota + 1)
|
||||
joiningD
|
||||
joiningT
|
||||
joiningR
|
||||
|
||||
//the following types are derived during processing
|
||||
joinZWJ
|
||||
joinZWNJ
|
||||
joinVirama
|
||||
numJoinTypes
|
||||
)
|
||||
|
||||
func (c info) isMapped() bool {
|
||||
return c&0x3 != 0
|
||||
}
|
||||
|
||||
func (c info) category() category {
|
||||
small := c & catSmallMask
|
||||
if small != 0 {
|
||||
return category(small)
|
||||
}
|
||||
return category(c & catBigMask)
|
||||
}
|
||||
|
||||
func (c info) joinType() info {
|
||||
if c.isMapped() {
|
||||
return 0
|
||||
}
|
||||
return (c >> joinShift) & joinMask
|
||||
}
|
||||
|
||||
func (c info) isModifier() bool {
|
||||
return c&(modifier|catSmallMask) == modifier
|
||||
}
|
||||
|
||||
func (c info) isViramaModifier() bool {
|
||||
return c&(attributesMask|catSmallMask) == viramaModifier
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue