aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor
diff options
context:
space:
mode:
authorRadek Simko <radek.simko@gmail.com>2017-08-14 16:10:17 +0200
committerGitHub <noreply@github.com>2017-08-14 16:10:17 +0200
commit00a66330be57dc8d7f987b4235d65d372f6b471f (patch)
tree864f925049d422033dd25a73bafce32b361c8827 /vendor
parentb6a7c48445fdb87dcae46906aa7e9349209d8bb5 (diff)
parentc680a8e1622ed0f18751d9d167c836ee24f5e897 (diff)
downloadterraform-provider-statuscake-00a66330be57dc8d7f987b4235d65d372f6b471f.tar.gz
terraform-provider-statuscake-00a66330be57dc8d7f987b4235d65d372f6b471f.tar.zst
terraform-provider-statuscake-00a66330be57dc8d7f987b4235d65d372f6b471f.zip
Merge pull request #3 from terraform-providers/vendor-tf-0.10
vendor: github.com/hashicorp/terraform/...@v0.10.0
Diffstat (limited to 'vendor')
-rw-r--r--vendor/github.com/blang/semver/LICENSE22
-rw-r--r--vendor/github.com/blang/semver/README.md194
-rw-r--r--vendor/github.com/blang/semver/json.go23
-rw-r--r--vendor/github.com/blang/semver/package.json17
-rw-r--r--vendor/github.com/blang/semver/range.go416
-rw-r--r--vendor/github.com/blang/semver/semver.go418
-rw-r--r--vendor/github.com/blang/semver/sort.go28
-rw-r--r--vendor/github.com/blang/semver/sql.go30
-rw-r--r--vendor/github.com/hashicorp/go-cleanhttp/LICENSE363
-rw-r--r--vendor/github.com/hashicorp/go-cleanhttp/README.md30
-rw-r--r--vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go56
-rw-r--r--vendor/github.com/hashicorp/go-cleanhttp/doc.go20
-rw-r--r--vendor/github.com/hashicorp/terraform/config/config.go42
-rw-r--r--vendor/github.com/hashicorp/terraform/config/interpolate_funcs.go17
-rw-r--r--vendor/github.com/hashicorp/terraform/config/loader.go6
-rw-r--r--vendor/github.com/hashicorp/terraform/config/loader_hcl.go28
-rw-r--r--vendor/github.com/hashicorp/terraform/config/module/tree.go19
-rw-r--r--vendor/github.com/hashicorp/terraform/config/providers.go103
-rw-r--r--vendor/github.com/hashicorp/terraform/flatmap/expand.go7
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/resource/id.go33
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/resource/testing.go44
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/schema/provider.go17
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go52
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/schema/resource.go23
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/schema/schema.go14
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/shadow/closer.go21
-rw-r--r--vendor/github.com/hashicorp/terraform/helper/shadow/value.go8
-rw-r--r--vendor/github.com/hashicorp/terraform/moduledeps/dependencies.go43
-rw-r--r--vendor/github.com/hashicorp/terraform/moduledeps/doc.go7
-rw-r--r--vendor/github.com/hashicorp/terraform/moduledeps/module.go204
-rw-r--r--vendor/github.com/hashicorp/terraform/moduledeps/provider.go30
-rw-r--r--vendor/github.com/hashicorp/terraform/plugin/client.go24
-rw-r--r--vendor/github.com/hashicorp/terraform/plugin/discovery/error.go30
-rw-r--r--vendor/github.com/hashicorp/terraform/plugin/discovery/find.go168
-rw-r--r--vendor/github.com/hashicorp/terraform/plugin/discovery/get.go424
-rw-r--r--vendor/github.com/hashicorp/terraform/plugin/discovery/meta.go41
-rw-r--r--vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go195
-rw-r--r--vendor/github.com/hashicorp/terraform/plugin/discovery/requirements.go105
-rw-r--r--vendor/github.com/hashicorp/terraform/plugin/discovery/signature.go53
-rw-r--r--vendor/github.com/hashicorp/terraform/plugin/discovery/version.go72
-rw-r--r--vendor/github.com/hashicorp/terraform/plugin/discovery/version_set.go84
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/context.go32
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/diff.go6
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/eval_diff.go36
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/graph_builder_plan.go10
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/graph_builder_refresh.go10
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/interpolate.go8
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/module_dependencies.go156
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go95
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/plan.go51
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/resource_address.go176
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/resource_provider.go81
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/state.go66
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/test_failure9
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/transform_resource_refresh_plannable.go55
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/transform_targets.go13
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/util.go20
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/version.go4
-rw-r--r--vendor/golang.org/x/crypto/cast5/cast5.go526
-rw-r--r--vendor/golang.org/x/crypto/openpgp/armor/armor.go219
-rw-r--r--vendor/golang.org/x/crypto/openpgp/armor/encode.go160
-rw-r--r--vendor/golang.org/x/crypto/openpgp/canonical_text.go59
-rw-r--r--vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go122
-rw-r--r--vendor/golang.org/x/crypto/openpgp/errors/errors.go72
-rw-r--r--vendor/golang.org/x/crypto/openpgp/keys.go637
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/compressed.go123
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/config.go91
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go199
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/literal.go89
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/ocfb.go143
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go73
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/opaque.go162
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/packet.go537
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/private_key.go380
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/public_key.go748
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go279
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/reader.go76
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/signature.go731
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go146
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go155
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go290
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/userattribute.go91
-rw-r--r--vendor/golang.org/x/crypto/openpgp/packet/userid.go160
-rw-r--r--vendor/golang.org/x/crypto/openpgp/read.go442
-rw-r--r--vendor/golang.org/x/crypto/openpgp/s2k/s2k.go273
-rw-r--r--vendor/golang.org/x/crypto/openpgp/write.go378
-rw-r--r--vendor/golang.org/x/net/LICENSE27
-rw-r--r--vendor/golang.org/x/net/PATENTS22
-rw-r--r--vendor/golang.org/x/net/html/atom/atom.go78
-rw-r--r--vendor/golang.org/x/net/html/atom/table.go713
-rw-r--r--vendor/golang.org/x/net/html/const.go102
-rw-r--r--vendor/golang.org/x/net/html/doc.go106
-rw-r--r--vendor/golang.org/x/net/html/doctype.go156
-rw-r--r--vendor/golang.org/x/net/html/entity.go2253
-rw-r--r--vendor/golang.org/x/net/html/escape.go258
-rw-r--r--vendor/golang.org/x/net/html/foreign.go226
-rw-r--r--vendor/golang.org/x/net/html/node.go193
-rw-r--r--vendor/golang.org/x/net/html/parse.go2094
-rw-r--r--vendor/golang.org/x/net/html/render.go271
-rw-r--r--vendor/golang.org/x/net/html/token.go1219
-rw-r--r--vendor/vendor.json210
101 files changed, 19379 insertions, 269 deletions
diff --git a/vendor/github.com/blang/semver/LICENSE b/vendor/github.com/blang/semver/LICENSE
new file mode 100644
index 0000000..5ba5c86
--- /dev/null
+++ b/vendor/github.com/blang/semver/LICENSE
@@ -0,0 +1,22 @@
1The MIT License
2
3Copyright (c) 2014 Benedikt Lang <github at benediktlang.de>
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
22
diff --git a/vendor/github.com/blang/semver/README.md b/vendor/github.com/blang/semver/README.md
new file mode 100644
index 0000000..08b2e4a
--- /dev/null
+++ b/vendor/github.com/blang/semver/README.md
@@ -0,0 +1,194 @@
1semver for golang [![Build Status](https://travis-ci.org/blang/semver.svg?branch=master)](https://travis-ci.org/blang/semver) [![GoDoc](https://godoc.org/github.com/blang/semver?status.png)](https://godoc.org/github.com/blang/semver) [![Coverage Status](https://img.shields.io/coveralls/blang/semver.svg)](https://coveralls.io/r/blang/semver?branch=master)
2======
3
4semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`.
5
6Usage
7-----
8```bash
9$ go get github.com/blang/semver
10```
11Note: Always vendor your dependencies or fix on a specific version tag.
12
13```go
14import github.com/blang/semver
15v1, err := semver.Make("1.0.0-beta")
16v2, err := semver.Make("2.0.0-beta")
17v1.Compare(v2)
18```
19
20Also check the [GoDocs](http://godoc.org/github.com/blang/semver).
21
22Why should I use this lib?
23-----
24
25- Fully spec compatible
26- No reflection
27- No regex
28- Fully tested (Coverage >99%)
29- Readable parsing/validation errors
30- Fast (See [Benchmarks](#benchmarks))
31- Only Stdlib
32- Uses values instead of pointers
33- Many features, see below
34
35
36Features
37-----
38
39- Parsing and validation at all levels
40- Comparator-like comparisons
41- Compare Helper Methods
42- InPlace manipulation
43- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1`
44- Wildcards `>=1.x`, `<=2.5.x`
45- Sortable (implements sort.Interface)
46- database/sql compatible (sql.Scanner/Valuer)
47- encoding/json compatible (json.Marshaler/Unmarshaler)
48
49Ranges
50------
51
52A `Range` is a set of conditions which specify which versions satisfy the range.
53
54A condition is composed of an operator and a version. The supported operators are:
55
56- `<1.0.0` Less than `1.0.0`
57- `<=1.0.0` Less than or equal to `1.0.0`
58- `>1.0.0` Greater than `1.0.0`
59- `>=1.0.0` Greater than or equal to `1.0.0`
60- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0`
61- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`.
62
63Note that spaces between the operator and the version will be gracefully tolerated.
64
65A `Range` can link multiple `Ranges` separated by space:
66
67Ranges can be linked by logical AND:
68
69 - `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0`
70 - `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2`
71
72Ranges can also be linked by logical OR:
73
74 - `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x`
75
76AND has a higher precedence than OR. It's not possible to use brackets.
77
78Ranges can be combined by both AND and OR
79
80 - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
81
82Range usage:
83
84```
85v, err := semver.Parse("1.2.3")
86range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0")
87if range(v) {
88 //valid
89}
90
91```
92
93Example
94-----
95
96Have a look at full examples in [examples/main.go](examples/main.go)
97
98```go
99import github.com/blang/semver
100
101v, err := semver.Make("0.0.1-alpha.preview+123.github")
102fmt.Printf("Major: %d\n", v.Major)
103fmt.Printf("Minor: %d\n", v.Minor)
104fmt.Printf("Patch: %d\n", v.Patch)
105fmt.Printf("Pre: %s\n", v.Pre)
106fmt.Printf("Build: %s\n", v.Build)
107
108// Prerelease versions array
109if len(v.Pre) > 0 {
110 fmt.Println("Prerelease versions:")
111 for i, pre := range v.Pre {
112 fmt.Printf("%d: %q\n", i, pre)
113 }
114}
115
116// Build meta data array
117if len(v.Build) > 0 {
118 fmt.Println("Build meta data:")
119 for i, build := range v.Build {
120 fmt.Printf("%d: %q\n", i, build)
121 }
122}
123
124v001, err := semver.Make("0.0.1")
125// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE
126v001.GT(v) == true
127v.LT(v001) == true
128v.GTE(v) == true
129v.LTE(v) == true
130
131// Or use v.Compare(v2) for comparisons (-1, 0, 1):
132v001.Compare(v) == 1
133v.Compare(v001) == -1
134v.Compare(v) == 0
135
136// Manipulate Version in place:
137v.Pre[0], err = semver.NewPRVersion("beta")
138if err != nil {
139 fmt.Printf("Error parsing pre release version: %q", err)
140}
141
142fmt.Println("\nValidate versions:")
143v.Build[0] = "?"
144
145err = v.Validate()
146if err != nil {
147 fmt.Printf("Validation failed: %s\n", err)
148}
149```
150
151
152Benchmarks
153-----
154
155 BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op
156 BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op
157 BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op
158 BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op
159 BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op
160 BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op
161 BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op
162 BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op
163 BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op
164 BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op
165 BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op
166 BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op
167 BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op
168 BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op
169 BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op
170 BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op
171 BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op
172 BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op
173 BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op
174 BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op
175
176See benchmark cases at [semver_test.go](semver_test.go)
177
178
179Motivation
180-----
181
182I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like.
183
184
185Contribution
186-----
187
188Feel free to make a pull request. For bigger changes create a issue first to discuss about it.
189
190
191License
192-----
193
194See [LICENSE](LICENSE) file.
diff --git a/vendor/github.com/blang/semver/json.go b/vendor/github.com/blang/semver/json.go
new file mode 100644
index 0000000..a74bf7c
--- /dev/null
+++ b/vendor/github.com/blang/semver/json.go
@@ -0,0 +1,23 @@
1package semver
2
3import (
4 "encoding/json"
5)
6
7// MarshalJSON implements the encoding/json.Marshaler interface.
8func (v Version) MarshalJSON() ([]byte, error) {
9 return json.Marshal(v.String())
10}
11
12// UnmarshalJSON implements the encoding/json.Unmarshaler interface.
13func (v *Version) UnmarshalJSON(data []byte) (err error) {
14 var versionString string
15
16 if err = json.Unmarshal(data, &versionString); err != nil {
17 return
18 }
19
20 *v, err = Parse(versionString)
21
22 return
23}
diff --git a/vendor/github.com/blang/semver/package.json b/vendor/github.com/blang/semver/package.json
new file mode 100644
index 0000000..1cf8ebd
--- /dev/null
+++ b/vendor/github.com/blang/semver/package.json
@@ -0,0 +1,17 @@
1{
2 "author": "blang",
3 "bugs": {
4 "URL": "https://github.com/blang/semver/issues",
5 "url": "https://github.com/blang/semver/issues"
6 },
7 "gx": {
8 "dvcsimport": "github.com/blang/semver"
9 },
10 "gxVersion": "0.10.0",
11 "language": "go",
12 "license": "MIT",
13 "name": "semver",
14 "releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
15 "version": "3.5.1"
16}
17
diff --git a/vendor/github.com/blang/semver/range.go b/vendor/github.com/blang/semver/range.go
new file mode 100644
index 0000000..fca406d
--- /dev/null
+++ b/vendor/github.com/blang/semver/range.go
@@ -0,0 +1,416 @@
1package semver
2
3import (
4 "fmt"
5 "strconv"
6 "strings"
7 "unicode"
8)
9
10type wildcardType int
11
12const (
13 noneWildcard wildcardType = iota
14 majorWildcard wildcardType = 1
15 minorWildcard wildcardType = 2
16 patchWildcard wildcardType = 3
17)
18
19func wildcardTypefromInt(i int) wildcardType {
20 switch i {
21 case 1:
22 return majorWildcard
23 case 2:
24 return minorWildcard
25 case 3:
26 return patchWildcard
27 default:
28 return noneWildcard
29 }
30}
31
32type comparator func(Version, Version) bool
33
34var (
35 compEQ comparator = func(v1 Version, v2 Version) bool {
36 return v1.Compare(v2) == 0
37 }
38 compNE = func(v1 Version, v2 Version) bool {
39 return v1.Compare(v2) != 0
40 }
41 compGT = func(v1 Version, v2 Version) bool {
42 return v1.Compare(v2) == 1
43 }
44 compGE = func(v1 Version, v2 Version) bool {
45 return v1.Compare(v2) >= 0
46 }
47 compLT = func(v1 Version, v2 Version) bool {
48 return v1.Compare(v2) == -1
49 }
50 compLE = func(v1 Version, v2 Version) bool {
51 return v1.Compare(v2) <= 0
52 }
53)
54
55type versionRange struct {
56 v Version
57 c comparator
58}
59
60// rangeFunc creates a Range from the given versionRange.
61func (vr *versionRange) rangeFunc() Range {
62 return Range(func(v Version) bool {
63 return vr.c(v, vr.v)
64 })
65}
66
67// Range represents a range of versions.
68// A Range can be used to check if a Version satisfies it:
69//
70// range, err := semver.ParseRange(">1.0.0 <2.0.0")
71// range(semver.MustParse("1.1.1") // returns true
72type Range func(Version) bool
73
74// OR combines the existing Range with another Range using logical OR.
75func (rf Range) OR(f Range) Range {
76 return Range(func(v Version) bool {
77 return rf(v) || f(v)
78 })
79}
80
81// AND combines the existing Range with another Range using logical AND.
82func (rf Range) AND(f Range) Range {
83 return Range(func(v Version) bool {
84 return rf(v) && f(v)
85 })
86}
87
88// ParseRange parses a range and returns a Range.
89// If the range could not be parsed an error is returned.
90//
91// Valid ranges are:
92// - "<1.0.0"
93// - "<=1.0.0"
94// - ">1.0.0"
95// - ">=1.0.0"
96// - "1.0.0", "=1.0.0", "==1.0.0"
97// - "!1.0.0", "!=1.0.0"
98//
99// A Range can consist of multiple ranges separated by space:
100// Ranges can be linked by logical AND:
101// - ">1.0.0 <2.0.0" would match between both ranges, so "1.1.1" and "1.8.7" but not "1.0.0" or "2.0.0"
102// - ">1.0.0 <3.0.0 !2.0.3-beta.2" would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2
103//
104// Ranges can also be linked by logical OR:
105// - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x"
106//
107// AND has a higher precedence than OR. It's not possible to use brackets.
108//
109// Ranges can be combined by both AND and OR
110//
111// - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
112func ParseRange(s string) (Range, error) {
113 parts := splitAndTrim(s)
114 orParts, err := splitORParts(parts)
115 if err != nil {
116 return nil, err
117 }
118 expandedParts, err := expandWildcardVersion(orParts)
119 if err != nil {
120 return nil, err
121 }
122 var orFn Range
123 for _, p := range expandedParts {
124 var andFn Range
125 for _, ap := range p {
126 opStr, vStr, err := splitComparatorVersion(ap)
127 if err != nil {
128 return nil, err
129 }
130 vr, err := buildVersionRange(opStr, vStr)
131 if err != nil {
132 return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err)
133 }
134 rf := vr.rangeFunc()
135
136 // Set function
137 if andFn == nil {
138 andFn = rf
139 } else { // Combine with existing function
140 andFn = andFn.AND(rf)
141 }
142 }
143 if orFn == nil {
144 orFn = andFn
145 } else {
146 orFn = orFn.OR(andFn)
147 }
148
149 }
150 return orFn, nil
151}
152
153// splitORParts splits the already cleaned parts by '||'.
154// Checks for invalid positions of the operator and returns an
155// error if found.
156func splitORParts(parts []string) ([][]string, error) {
157 var ORparts [][]string
158 last := 0
159 for i, p := range parts {
160 if p == "||" {
161 if i == 0 {
162 return nil, fmt.Errorf("First element in range is '||'")
163 }
164 ORparts = append(ORparts, parts[last:i])
165 last = i + 1
166 }
167 }
168 if last == len(parts) {
169 return nil, fmt.Errorf("Last element in range is '||'")
170 }
171 ORparts = append(ORparts, parts[last:])
172 return ORparts, nil
173}
174
175// buildVersionRange takes a slice of 2: operator and version
176// and builds a versionRange, otherwise an error.
177func buildVersionRange(opStr, vStr string) (*versionRange, error) {
178 c := parseComparator(opStr)
179 if c == nil {
180 return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, ""))
181 }
182 v, err := Parse(vStr)
183 if err != nil {
184 return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err)
185 }
186
187 return &versionRange{
188 v: v,
189 c: c,
190 }, nil
191
192}
193
194// inArray checks if a byte is contained in an array of bytes
195func inArray(s byte, list []byte) bool {
196 for _, el := range list {
197 if el == s {
198 return true
199 }
200 }
201 return false
202}
203
204// splitAndTrim splits a range string by spaces and cleans whitespaces
205func splitAndTrim(s string) (result []string) {
206 last := 0
207 var lastChar byte
208 excludeFromSplit := []byte{'>', '<', '='}
209 for i := 0; i < len(s); i++ {
210 if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) {
211 if last < i-1 {
212 result = append(result, s[last:i])
213 }
214 last = i + 1
215 } else if s[i] != ' ' {
216 lastChar = s[i]
217 }
218 }
219 if last < len(s)-1 {
220 result = append(result, s[last:])
221 }
222
223 for i, v := range result {
224 result[i] = strings.Replace(v, " ", "", -1)
225 }
226
227 // parts := strings.Split(s, " ")
228 // for _, x := range parts {
229 // if s := strings.TrimSpace(x); len(s) != 0 {
230 // result = append(result, s)
231 // }
232 // }
233 return
234}
235
236// splitComparatorVersion splits the comparator from the version.
237// Input must be free of leading or trailing spaces.
238func splitComparatorVersion(s string) (string, string, error) {
239 i := strings.IndexFunc(s, unicode.IsDigit)
240 if i == -1 {
241 return "", "", fmt.Errorf("Could not get version from string: %q", s)
242 }
243 return strings.TrimSpace(s[0:i]), s[i:], nil
244}
245
246// getWildcardType will return the type of wildcard that the
247// passed version contains
248func getWildcardType(vStr string) wildcardType {
249 parts := strings.Split(vStr, ".")
250 nparts := len(parts)
251 wildcard := parts[nparts-1]
252
253 possibleWildcardType := wildcardTypefromInt(nparts)
254 if wildcard == "x" {
255 return possibleWildcardType
256 }
257
258 return noneWildcard
259}
260
261// createVersionFromWildcard will convert a wildcard version
262// into a regular version, replacing 'x's with '0's, handling
263// special cases like '1.x.x' and '1.x'
264func createVersionFromWildcard(vStr string) string {
265 // handle 1.x.x
266 vStr2 := strings.Replace(vStr, ".x.x", ".x", 1)
267 vStr2 = strings.Replace(vStr2, ".x", ".0", 1)
268 parts := strings.Split(vStr2, ".")
269
270 // handle 1.x
271 if len(parts) == 2 {
272 return vStr2 + ".0"
273 }
274
275 return vStr2
276}
277
278// incrementMajorVersion will increment the major version
279// of the passed version
280func incrementMajorVersion(vStr string) (string, error) {
281 parts := strings.Split(vStr, ".")
282 i, err := strconv.Atoi(parts[0])
283 if err != nil {
284 return "", err
285 }
286 parts[0] = strconv.Itoa(i + 1)
287
288 return strings.Join(parts, "."), nil
289}
290
291// incrementMajorVersion will increment the minor version
292// of the passed version
293func incrementMinorVersion(vStr string) (string, error) {
294 parts := strings.Split(vStr, ".")
295 i, err := strconv.Atoi(parts[1])
296 if err != nil {
297 return "", err
298 }
299 parts[1] = strconv.Itoa(i + 1)
300
301 return strings.Join(parts, "."), nil
302}
303
304// expandWildcardVersion will expand wildcards inside versions
305// following these rules:
306//
307// * when dealing with patch wildcards:
308// >= 1.2.x will become >= 1.2.0
309// <= 1.2.x will become < 1.3.0
310// > 1.2.x will become >= 1.3.0
311// < 1.2.x will become < 1.2.0
312// != 1.2.x will become < 1.2.0 >= 1.3.0
313//
314// * when dealing with minor wildcards:
315// >= 1.x will become >= 1.0.0
316// <= 1.x will become < 2.0.0
317// > 1.x will become >= 2.0.0
318// < 1.0 will become < 1.0.0
319// != 1.x will become < 1.0.0 >= 2.0.0
320//
321// * when dealing with wildcards without
322// version operator:
323// 1.2.x will become >= 1.2.0 < 1.3.0
324// 1.x will become >= 1.0.0 < 2.0.0
325func expandWildcardVersion(parts [][]string) ([][]string, error) {
326 var expandedParts [][]string
327 for _, p := range parts {
328 var newParts []string
329 for _, ap := range p {
330 if strings.Index(ap, "x") != -1 {
331 opStr, vStr, err := splitComparatorVersion(ap)
332 if err != nil {
333 return nil, err
334 }
335
336 versionWildcardType := getWildcardType(vStr)
337 flatVersion := createVersionFromWildcard(vStr)
338
339 var resultOperator string
340 var shouldIncrementVersion bool
341 switch opStr {
342 case ">":
343 resultOperator = ">="
344 shouldIncrementVersion = true
345 case ">=":
346 resultOperator = ">="
347 case "<":
348 resultOperator = "<"
349 case "<=":
350 resultOperator = "<"
351 shouldIncrementVersion = true
352 case "", "=", "==":
353 newParts = append(newParts, ">="+flatVersion)
354 resultOperator = "<"
355 shouldIncrementVersion = true
356 case "!=", "!":
357 newParts = append(newParts, "<"+flatVersion)
358 resultOperator = ">="
359 shouldIncrementVersion = true
360 }
361
362 var resultVersion string
363 if shouldIncrementVersion {
364 switch versionWildcardType {
365 case patchWildcard:
366 resultVersion, _ = incrementMinorVersion(flatVersion)
367 case minorWildcard:
368 resultVersion, _ = incrementMajorVersion(flatVersion)
369 }
370 } else {
371 resultVersion = flatVersion
372 }
373
374 ap = resultOperator + resultVersion
375 }
376 newParts = append(newParts, ap)
377 }
378 expandedParts = append(expandedParts, newParts)
379 }
380
381 return expandedParts, nil
382}
383
384func parseComparator(s string) comparator {
385 switch s {
386 case "==":
387 fallthrough
388 case "":
389 fallthrough
390 case "=":
391 return compEQ
392 case ">":
393 return compGT
394 case ">=":
395 return compGE
396 case "<":
397 return compLT
398 case "<=":
399 return compLE
400 case "!":
401 fallthrough
402 case "!=":
403 return compNE
404 }
405
406 return nil
407}
408
409// MustParseRange is like ParseRange but panics if the range cannot be parsed.
410func MustParseRange(s string) Range {
411 r, err := ParseRange(s)
412 if err != nil {
413 panic(`semver: ParseRange(` + s + `): ` + err.Error())
414 }
415 return r
416}
diff --git a/vendor/github.com/blang/semver/semver.go b/vendor/github.com/blang/semver/semver.go
new file mode 100644
index 0000000..8ee0842
--- /dev/null
+++ b/vendor/github.com/blang/semver/semver.go
@@ -0,0 +1,418 @@
1package semver
2
3import (
4 "errors"
5 "fmt"
6 "strconv"
7 "strings"
8)
9
10const (
11 numbers string = "0123456789"
12 alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"
13 alphanum = alphas + numbers
14)
15
16// SpecVersion is the latest fully supported spec version of semver
17var SpecVersion = Version{
18 Major: 2,
19 Minor: 0,
20 Patch: 0,
21}
22
23// Version represents a semver compatible version
24type Version struct {
25 Major uint64
26 Minor uint64
27 Patch uint64
28 Pre []PRVersion
29 Build []string //No Precendence
30}
31
32// Version to string
33func (v Version) String() string {
34 b := make([]byte, 0, 5)
35 b = strconv.AppendUint(b, v.Major, 10)
36 b = append(b, '.')
37 b = strconv.AppendUint(b, v.Minor, 10)
38 b = append(b, '.')
39 b = strconv.AppendUint(b, v.Patch, 10)
40
41 if len(v.Pre) > 0 {
42 b = append(b, '-')
43 b = append(b, v.Pre[0].String()...)
44
45 for _, pre := range v.Pre[1:] {
46 b = append(b, '.')
47 b = append(b, pre.String()...)
48 }
49 }
50
51 if len(v.Build) > 0 {
52 b = append(b, '+')
53 b = append(b, v.Build[0]...)
54
55 for _, build := range v.Build[1:] {
56 b = append(b, '.')
57 b = append(b, build...)
58 }
59 }
60
61 return string(b)
62}
63
64// Equals checks if v is equal to o.
65func (v Version) Equals(o Version) bool {
66 return (v.Compare(o) == 0)
67}
68
69// EQ checks if v is equal to o.
70func (v Version) EQ(o Version) bool {
71 return (v.Compare(o) == 0)
72}
73
74// NE checks if v is not equal to o.
75func (v Version) NE(o Version) bool {
76 return (v.Compare(o) != 0)
77}
78
79// GT checks if v is greater than o.
80func (v Version) GT(o Version) bool {
81 return (v.Compare(o) == 1)
82}
83
84// GTE checks if v is greater than or equal to o.
85func (v Version) GTE(o Version) bool {
86 return (v.Compare(o) >= 0)
87}
88
89// GE checks if v is greater than or equal to o.
90func (v Version) GE(o Version) bool {
91 return (v.Compare(o) >= 0)
92}
93
94// LT checks if v is less than o.
95func (v Version) LT(o Version) bool {
96 return (v.Compare(o) == -1)
97}
98
99// LTE checks if v is less than or equal to o.
100func (v Version) LTE(o Version) bool {
101 return (v.Compare(o) <= 0)
102}
103
104// LE checks if v is less than or equal to o.
105func (v Version) LE(o Version) bool {
106 return (v.Compare(o) <= 0)
107}
108
109// Compare compares Versions v to o:
110// -1 == v is less than o
111// 0 == v is equal to o
112// 1 == v is greater than o
113func (v Version) Compare(o Version) int {
114 if v.Major != o.Major {
115 if v.Major > o.Major {
116 return 1
117 }
118 return -1
119 }
120 if v.Minor != o.Minor {
121 if v.Minor > o.Minor {
122 return 1
123 }
124 return -1
125 }
126 if v.Patch != o.Patch {
127 if v.Patch > o.Patch {
128 return 1
129 }
130 return -1
131 }
132
133 // Quick comparison if a version has no prerelease versions
134 if len(v.Pre) == 0 && len(o.Pre) == 0 {
135 return 0
136 } else if len(v.Pre) == 0 && len(o.Pre) > 0 {
137 return 1
138 } else if len(v.Pre) > 0 && len(o.Pre) == 0 {
139 return -1
140 }
141
142 i := 0
143 for ; i < len(v.Pre) && i < len(o.Pre); i++ {
144 if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 {
145 continue
146 } else if comp == 1 {
147 return 1
148 } else {
149 return -1
150 }
151 }
152
153 // If all pr versions are the equal but one has further prversion, this one greater
154 if i == len(v.Pre) && i == len(o.Pre) {
155 return 0
156 } else if i == len(v.Pre) && i < len(o.Pre) {
157 return -1
158 } else {
159 return 1
160 }
161
162}
163
164// Validate validates v and returns error in case
165func (v Version) Validate() error {
166 // Major, Minor, Patch already validated using uint64
167
168 for _, pre := range v.Pre {
169 if !pre.IsNum { //Numeric prerelease versions already uint64
170 if len(pre.VersionStr) == 0 {
171 return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr)
172 }
173 if !containsOnly(pre.VersionStr, alphanum) {
174 return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr)
175 }
176 }
177 }
178
179 for _, build := range v.Build {
180 if len(build) == 0 {
181 return fmt.Errorf("Build meta data can not be empty %q", build)
182 }
183 if !containsOnly(build, alphanum) {
184 return fmt.Errorf("Invalid character(s) found in build meta data %q", build)
185 }
186 }
187
188 return nil
189}
190
191// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error
192func New(s string) (vp *Version, err error) {
193 v, err := Parse(s)
194 vp = &v
195 return
196}
197
198// Make is an alias for Parse, parses version string and returns a validated Version or error
199func Make(s string) (Version, error) {
200 return Parse(s)
201}
202
203// ParseTolerant allows for certain version specifications that do not strictly adhere to semver
204// specs to be parsed by this library. It does so by normalizing versions before passing them to
205// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions
206// with only major and minor components specified
207func ParseTolerant(s string) (Version, error) {
208 s = strings.TrimSpace(s)
209 s = strings.TrimPrefix(s, "v")
210
211 // Split into major.minor.(patch+pr+meta)
212 parts := strings.SplitN(s, ".", 3)
213 if len(parts) < 3 {
214 if strings.ContainsAny(parts[len(parts)-1], "+-") {
215 return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data")
216 }
217 for len(parts) < 3 {
218 parts = append(parts, "0")
219 }
220 s = strings.Join(parts, ".")
221 }
222
223 return Parse(s)
224}
225
226// Parse parses version string and returns a validated Version or error
227func Parse(s string) (Version, error) {
228 if len(s) == 0 {
229 return Version{}, errors.New("Version string empty")
230 }
231
232 // Split into major.minor.(patch+pr+meta)
233 parts := strings.SplitN(s, ".", 3)
234 if len(parts) != 3 {
235 return Version{}, errors.New("No Major.Minor.Patch elements found")
236 }
237
238 // Major
239 if !containsOnly(parts[0], numbers) {
240 return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0])
241 }
242 if hasLeadingZeroes(parts[0]) {
243 return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0])
244 }
245 major, err := strconv.ParseUint(parts[0], 10, 64)
246 if err != nil {
247 return Version{}, err
248 }
249
250 // Minor
251 if !containsOnly(parts[1], numbers) {
252 return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1])
253 }
254 if hasLeadingZeroes(parts[1]) {
255 return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1])
256 }
257 minor, err := strconv.ParseUint(parts[1], 10, 64)
258 if err != nil {
259 return Version{}, err
260 }
261
262 v := Version{}
263 v.Major = major
264 v.Minor = minor
265
266 var build, prerelease []string
267 patchStr := parts[2]
268
269 if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 {
270 build = strings.Split(patchStr[buildIndex+1:], ".")
271 patchStr = patchStr[:buildIndex]
272 }
273
274 if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 {
275 prerelease = strings.Split(patchStr[preIndex+1:], ".")
276 patchStr = patchStr[:preIndex]
277 }
278
279 if !containsOnly(patchStr, numbers) {
280 return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr)
281 }
282 if hasLeadingZeroes(patchStr) {
283 return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr)
284 }
285 patch, err := strconv.ParseUint(patchStr, 10, 64)
286 if err != nil {
287 return Version{}, err
288 }
289
290 v.Patch = patch
291
292 // Prerelease
293 for _, prstr := range prerelease {
294 parsedPR, err := NewPRVersion(prstr)
295 if err != nil {
296 return Version{}, err
297 }
298 v.Pre = append(v.Pre, parsedPR)
299 }
300
301 // Build meta data
302 for _, str := range build {
303 if len(str) == 0 {
304 return Version{}, errors.New("Build meta data is empty")
305 }
306 if !containsOnly(str, alphanum) {
307 return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str)
308 }
309 v.Build = append(v.Build, str)
310 }
311
312 return v, nil
313}
314
315// MustParse is like Parse but panics if the version cannot be parsed.
316func MustParse(s string) Version {
317 v, err := Parse(s)
318 if err != nil {
319 panic(`semver: Parse(` + s + `): ` + err.Error())
320 }
321 return v
322}
323
324// PRVersion represents a PreRelease Version
325type PRVersion struct {
326 VersionStr string
327 VersionNum uint64
328 IsNum bool
329}
330
331// NewPRVersion creates a new valid prerelease version
332func NewPRVersion(s string) (PRVersion, error) {
333 if len(s) == 0 {
334 return PRVersion{}, errors.New("Prerelease is empty")
335 }
336 v := PRVersion{}
337 if containsOnly(s, numbers) {
338 if hasLeadingZeroes(s) {
339 return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s)
340 }
341 num, err := strconv.ParseUint(s, 10, 64)
342
343 // Might never be hit, but just in case
344 if err != nil {
345 return PRVersion{}, err
346 }
347 v.VersionNum = num
348 v.IsNum = true
349 } else if containsOnly(s, alphanum) {
350 v.VersionStr = s
351 v.IsNum = false
352 } else {
353 return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s)
354 }
355 return v, nil
356}
357
358// IsNumeric checks if prerelease-version is numeric
359func (v PRVersion) IsNumeric() bool {
360 return v.IsNum
361}
362
363// Compare compares two PreRelease Versions v and o:
364// -1 == v is less than o
365// 0 == v is equal to o
366// 1 == v is greater than o
367func (v PRVersion) Compare(o PRVersion) int {
368 if v.IsNum && !o.IsNum {
369 return -1
370 } else if !v.IsNum && o.IsNum {
371 return 1
372 } else if v.IsNum && o.IsNum {
373 if v.VersionNum == o.VersionNum {
374 return 0
375 } else if v.VersionNum > o.VersionNum {
376 return 1
377 } else {
378 return -1
379 }
380 } else { // both are Alphas
381 if v.VersionStr == o.VersionStr {
382 return 0
383 } else if v.VersionStr > o.VersionStr {
384 return 1
385 } else {
386 return -1
387 }
388 }
389}
390
391// PreRelease version to string
392func (v PRVersion) String() string {
393 if v.IsNum {
394 return strconv.FormatUint(v.VersionNum, 10)
395 }
396 return v.VersionStr
397}
398
399func containsOnly(s string, set string) bool {
400 return strings.IndexFunc(s, func(r rune) bool {
401 return !strings.ContainsRune(set, r)
402 }) == -1
403}
404
405func hasLeadingZeroes(s string) bool {
406 return len(s) > 1 && s[0] == '0'
407}
408
409// NewBuildVersion creates a new valid build version
410func NewBuildVersion(s string) (string, error) {
411 if len(s) == 0 {
412 return "", errors.New("Buildversion is empty")
413 }
414 if !containsOnly(s, alphanum) {
415 return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s)
416 }
417 return s, nil
418}
diff --git a/vendor/github.com/blang/semver/sort.go b/vendor/github.com/blang/semver/sort.go
new file mode 100644
index 0000000..e18f880
--- /dev/null
+++ b/vendor/github.com/blang/semver/sort.go
@@ -0,0 +1,28 @@
1package semver
2
3import (
4 "sort"
5)
6
7// Versions represents multiple versions.
8type Versions []Version
9
10// Len returns length of version collection
11func (s Versions) Len() int {
12 return len(s)
13}
14
15// Swap swaps two versions inside the collection by its indices
16func (s Versions) Swap(i, j int) {
17 s[i], s[j] = s[j], s[i]
18}
19
20// Less checks if version at index i is less than version at index j
21func (s Versions) Less(i, j int) bool {
22 return s[i].LT(s[j])
23}
24
25// Sort sorts a slice of versions
26func Sort(versions []Version) {
27 sort.Sort(Versions(versions))
28}
diff --git a/vendor/github.com/blang/semver/sql.go b/vendor/github.com/blang/semver/sql.go
new file mode 100644
index 0000000..eb4d802
--- /dev/null
+++ b/vendor/github.com/blang/semver/sql.go
@@ -0,0 +1,30 @@
1package semver
2
3import (
4 "database/sql/driver"
5 "fmt"
6)
7
8// Scan implements the database/sql.Scanner interface.
9func (v *Version) Scan(src interface{}) (err error) {
10 var str string
11 switch src := src.(type) {
12 case string:
13 str = src
14 case []byte:
15 str = string(src)
16 default:
17 return fmt.Errorf("Version.Scan: cannot convert %T to string.", src)
18 }
19
20 if t, err := Parse(str); err == nil {
21 *v = t
22 }
23
24 return
25}
26
27// Value implements the database/sql/driver.Valuer interface.
28func (v Version) Value() (driver.Value, error) {
29 return v.String(), nil
30}
diff --git a/vendor/github.com/hashicorp/go-cleanhttp/LICENSE b/vendor/github.com/hashicorp/go-cleanhttp/LICENSE
new file mode 100644
index 0000000..e87a115
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-cleanhttp/LICENSE
@@ -0,0 +1,363 @@
1Mozilla Public License, version 2.0
2
31. Definitions
4
51.1. "Contributor"
6
7 means each individual or legal entity that creates, contributes to the
8 creation of, or owns Covered Software.
9
101.2. "Contributor Version"
11
12 means the combination of the Contributions of others (if any) used by a
13 Contributor and that particular Contributor's Contribution.
14
151.3. "Contribution"
16
17 means Covered Software of a particular Contributor.
18
191.4. "Covered Software"
20
21 means Source Code Form to which the initial Contributor has attached the
22 notice in Exhibit A, the Executable Form of such Source Code Form, and
23 Modifications of such Source Code Form, in each case including portions
24 thereof.
25
261.5. "Incompatible With Secondary Licenses"
27 means
28
29 a. that the initial Contributor has attached the notice described in
30 Exhibit B to the Covered Software; or
31
32 b. that the Covered Software was made available under the terms of
33 version 1.1 or earlier of the License, but not also under the terms of
34 a Secondary License.
35
361.6. "Executable Form"
37
38 means any form of the work other than Source Code Form.
39
401.7. "Larger Work"
41
42 means a work that combines Covered Software with other material, in a
43 separate file or files, that is not Covered Software.
44
451.8. "License"
46
47 means this document.
48
491.9. "Licensable"
50
51 means having the right to grant, to the maximum extent possible, whether
52 at the time of the initial grant or subsequently, any and all of the
53 rights conveyed by this License.
54
551.10. "Modifications"
56
57 means any of the following:
58
59 a. any file in Source Code Form that results from an addition to,
60 deletion from, or modification of the contents of Covered Software; or
61
62 b. any new file in Source Code Form that contains any Covered Software.
63
641.11. "Patent Claims" of a Contributor
65
66 means any patent claim(s), including without limitation, method,
67 process, and apparatus claims, in any patent Licensable by such
68 Contributor that would be infringed, but for the grant of the License,
69 by the making, using, selling, offering for sale, having made, import,
70 or transfer of either its Contributions or its Contributor Version.
71
721.12. "Secondary License"
73
74 means either the GNU General Public License, Version 2.0, the GNU Lesser
75 General Public License, Version 2.1, the GNU Affero General Public
76 License, Version 3.0, or any later versions of those licenses.
77
781.13. "Source Code Form"
79
80 means the form of the work preferred for making modifications.
81
821.14. "You" (or "Your")
83
84 means an individual or a legal entity exercising rights under this
85 License. For legal entities, "You" includes any entity that controls, is
86 controlled by, or is under common control with You. For purposes of this
87 definition, "control" means (a) the power, direct or indirect, to cause
88 the direction or management of such entity, whether by contract or
89 otherwise, or (b) ownership of more than fifty percent (50%) of the
90 outstanding shares or beneficial ownership of such entity.
91
92
932. License Grants and Conditions
94
952.1. Grants
96
97 Each Contributor hereby grants You a world-wide, royalty-free,
98 non-exclusive license:
99
100 a. under intellectual property rights (other than patent or trademark)
101 Licensable by such Contributor to use, reproduce, make available,
102 modify, display, perform, distribute, and otherwise exploit its
103 Contributions, either on an unmodified basis, with Modifications, or
104 as part of a Larger Work; and
105
106 b. under Patent Claims of such Contributor to make, use, sell, offer for
107 sale, have made, import, and otherwise transfer either its
108 Contributions or its Contributor Version.
109
1102.2. Effective Date
111
112 The licenses granted in Section 2.1 with respect to any Contribution
113 become effective for each Contribution on the date the Contributor first
114 distributes such Contribution.
115
1162.3. Limitations on Grant Scope
117
118 The licenses granted in this Section 2 are the only rights granted under
119 this License. No additional rights or licenses will be implied from the
120 distribution or licensing of Covered Software under this License.
121 Notwithstanding Section 2.1(b) above, no patent license is granted by a
122 Contributor:
123
124 a. for any code that a Contributor has removed from Covered Software; or
125
126 b. for infringements caused by: (i) Your and any other third party's
127 modifications of Covered Software, or (ii) the combination of its
128 Contributions with other software (except as part of its Contributor
129 Version); or
130
131 c. under Patent Claims infringed by Covered Software in the absence of
132 its Contributions.
133
134 This License does not grant any rights in the trademarks, service marks,
135 or logos of any Contributor (except as may be necessary to comply with
136 the notice requirements in Section 3.4).
137
1382.4. Subsequent Licenses
139
140 No Contributor makes additional grants as a result of Your choice to
141 distribute the Covered Software under a subsequent version of this
142 License (see Section 10.2) or under the terms of a Secondary License (if
143 permitted under the terms of Section 3.3).
144
1452.5. Representation
146
147 Each Contributor represents that the Contributor believes its
148 Contributions are its original creation(s) or it has sufficient rights to
149 grant the rights to its Contributions conveyed by this License.
150
1512.6. Fair Use
152
153 This License is not intended to limit any rights You have under
154 applicable copyright doctrines of fair use, fair dealing, or other
155 equivalents.
156
1572.7. Conditions
158
159 Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
160 Section 2.1.
161
162
1633. Responsibilities
164
1653.1. Distribution of Source Form
166
167 All distribution of Covered Software in Source Code Form, including any
168 Modifications that You create or to which You contribute, must be under
169 the terms of this License. You must inform recipients that the Source
170 Code Form of the Covered Software is governed by the terms of this
171 License, and how they can obtain a copy of this License. You may not
172 attempt to alter or restrict the recipients' rights in the Source Code
173 Form.
174
1753.2. Distribution of Executable Form
176
177 If You distribute Covered Software in Executable Form then:
178
179 a. such Covered Software must also be made available in Source Code Form,
180 as described in Section 3.1, and You must inform recipients of the
181 Executable Form how they can obtain a copy of such Source Code Form by
182 reasonable means in a timely manner, at a charge no more than the cost
183 of distribution to the recipient; and
184
185 b. You may distribute such Executable Form under the terms of this
186 License, or sublicense it under different terms, provided that the
187 license for the Executable Form does not attempt to limit or alter the
188 recipients' rights in the Source Code Form under this License.
189
1903.3. Distribution of a Larger Work
191
192 You may create and distribute a Larger Work under terms of Your choice,
193 provided that You also comply with the requirements of this License for
194 the Covered Software. If the Larger Work is a combination of Covered
195 Software with a work governed by one or more Secondary Licenses, and the
196 Covered Software is not Incompatible With Secondary Licenses, this
197 License permits You to additionally distribute such Covered Software
198 under the terms of such Secondary License(s), so that the recipient of
199 the Larger Work may, at their option, further distribute the Covered
200 Software under the terms of either this License or such Secondary
201 License(s).
202
2033.4. Notices
204
205 You may not remove or alter the substance of any license notices
206 (including copyright notices, patent notices, disclaimers of warranty, or
207 limitations of liability) contained within the Source Code Form of the
208 Covered Software, except that You may alter any license notices to the
209 extent required to remedy known factual inaccuracies.
210
2113.5. Application of Additional Terms
212
213 You may choose to offer, and to charge a fee for, warranty, support,
214 indemnity or liability obligations to one or more recipients of Covered
215 Software. However, You may do so only on Your own behalf, and not on
216 behalf of any Contributor. You must make it absolutely clear that any
217 such warranty, support, indemnity, or liability obligation is offered by
218 You alone, and You hereby agree to indemnify every Contributor for any
219 liability incurred by such Contributor as a result of warranty, support,
220 indemnity or liability terms You offer. You may include additional
221 disclaimers of warranty and limitations of liability specific to any
222 jurisdiction.
223
2244. Inability to Comply Due to Statute or Regulation
225
226 If it is impossible for You to comply with any of the terms of this License
227 with respect to some or all of the Covered Software due to statute,
228 judicial order, or regulation then You must: (a) comply with the terms of
229 this License to the maximum extent possible; and (b) describe the
230 limitations and the code they affect. Such description must be placed in a
231 text file included with all distributions of the Covered Software under
232 this License. Except to the extent prohibited by statute or regulation,
233 such description must be sufficiently detailed for a recipient of ordinary
234 skill to be able to understand it.
235
2365. Termination
237
2385.1. The rights granted under this License will terminate automatically if You
239 fail to comply with any of its terms. However, if You become compliant,
240 then the rights granted under this License from a particular Contributor
241 are reinstated (a) provisionally, unless and until such Contributor
242 explicitly and finally terminates Your grants, and (b) on an ongoing
243 basis, if such Contributor fails to notify You of the non-compliance by
244 some reasonable means prior to 60 days after You have come back into
245 compliance. Moreover, Your grants from a particular Contributor are
246 reinstated on an ongoing basis if such Contributor notifies You of the
247 non-compliance by some reasonable means, this is the first time You have
248 received notice of non-compliance with this License from such
249 Contributor, and You become compliant prior to 30 days after Your receipt
250 of the notice.
251
2525.2. If You initiate litigation against any entity by asserting a patent
253 infringement claim (excluding declaratory judgment actions,
254 counter-claims, and cross-claims) alleging that a Contributor Version
255 directly or indirectly infringes any patent, then the rights granted to
256 You by any and all Contributors for the Covered Software under Section
257 2.1 of this License shall terminate.
258
2595.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
260 license agreements (excluding distributors and resellers) which have been
261 validly granted by You or Your distributors under this License prior to
262 termination shall survive termination.
263
2646. Disclaimer of Warranty
265
266 Covered Software is provided under this License on an "as is" basis,
267 without warranty of any kind, either expressed, implied, or statutory,
268 including, without limitation, warranties that the Covered Software is free
269 of defects, merchantable, fit for a particular purpose or non-infringing.
270 The entire risk as to the quality and performance of the Covered Software
271 is with You. Should any Covered Software prove defective in any respect,
272 You (not any Contributor) assume the cost of any necessary servicing,
273 repair, or correction. This disclaimer of warranty constitutes an essential
274 part of this License. No use of any Covered Software is authorized under
275 this License except under this disclaimer.
276
2777. Limitation of Liability
278
279 Under no circumstances and under no legal theory, whether tort (including
280 negligence), contract, or otherwise, shall any Contributor, or anyone who
281 distributes Covered Software as permitted above, be liable to You for any
282 direct, indirect, special, incidental, or consequential damages of any
283 character including, without limitation, damages for lost profits, loss of
284 goodwill, work stoppage, computer failure or malfunction, or any and all
285 other commercial damages or losses, even if such party shall have been
286 informed of the possibility of such damages. This limitation of liability
287 shall not apply to liability for death or personal injury resulting from
288 such party's negligence to the extent applicable law prohibits such
289 limitation. Some jurisdictions do not allow the exclusion or limitation of
290 incidental or consequential damages, so this exclusion and limitation may
291 not apply to You.
292
2938. Litigation
294
295 Any litigation relating to this License may be brought only in the courts
296 of a jurisdiction where the defendant maintains its principal place of
297 business and such litigation shall be governed by laws of that
298 jurisdiction, without reference to its conflict-of-law provisions. Nothing
299 in this Section shall prevent a party's ability to bring cross-claims or
300 counter-claims.
301
3029. Miscellaneous
303
304 This License represents the complete agreement concerning the subject
305 matter hereof. If any provision of this License is held to be
306 unenforceable, such provision shall be reformed only to the extent
307 necessary to make it enforceable. Any law or regulation which provides that
308 the language of a contract shall be construed against the drafter shall not
309 be used to construe this License against a Contributor.
310
311
31210. Versions of the License
313
31410.1. New Versions
315
316 Mozilla Foundation is the license steward. Except as provided in Section
317 10.3, no one other than the license steward has the right to modify or
318 publish new versions of this License. Each version will be given a
319 distinguishing version number.
320
32110.2. Effect of New Versions
322
323 You may distribute the Covered Software under the terms of the version
324 of the License under which You originally received the Covered Software,
325 or under the terms of any subsequent version published by the license
326 steward.
327
32810.3. Modified Versions
329
330 If you create software not governed by this License, and you want to
331 create a new license for such software, you may create and use a
332 modified version of this License if you rename the license and remove
333 any references to the name of the license steward (except to note that
334 such modified license differs from this License).
335
33610.4. Distributing Source Code Form that is Incompatible With Secondary
337 Licenses If You choose to distribute Source Code Form that is
338 Incompatible With Secondary Licenses under the terms of this version of
339 the License, the notice described in Exhibit B of this License must be
340 attached.
341
342Exhibit A - Source Code Form License Notice
343
344 This Source Code Form is subject to the
345 terms of the Mozilla Public License, v.
346 2.0. If a copy of the MPL was not
347 distributed with this file, You can
348 obtain one at
349 http://mozilla.org/MPL/2.0/.
350
351If it is not possible or desirable to put the notice in a particular file,
352then You may include the notice in a location (such as a LICENSE file in a
353relevant directory) where a recipient would be likely to look for such a
354notice.
355
356You may add additional accurate notices of copyright ownership.
357
358Exhibit B - "Incompatible With Secondary Licenses" Notice
359
360 This Source Code Form is "Incompatible
361 With Secondary Licenses", as defined by
362 the Mozilla Public License, v. 2.0.
363
diff --git a/vendor/github.com/hashicorp/go-cleanhttp/README.md b/vendor/github.com/hashicorp/go-cleanhttp/README.md
new file mode 100644
index 0000000..036e531
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-cleanhttp/README.md
@@ -0,0 +1,30 @@
1# cleanhttp
2
3Functions for accessing "clean" Go http.Client values
4
5-------------
6
7The Go standard library contains a default `http.Client` called
8`http.DefaultClient`. It is a common idiom in Go code to start with
9`http.DefaultClient` and tweak it as necessary, and in fact, this is
10encouraged; from the `http` package documentation:
11
12> The Client's Transport typically has internal state (cached TCP connections),
13so Clients should be reused instead of created as needed. Clients are safe for
14concurrent use by multiple goroutines.
15
16Unfortunately, this is a shared value, and it is not uncommon for libraries to
17assume that they are free to modify it at will. With enough dependencies, it
18can be very easy to encounter strange problems and race conditions due to
19manipulation of this shared value across libraries and goroutines (clients are
20safe for concurrent use, but writing values to the client struct itself is not
21protected).
22
23Making things worse is the fact that a bare `http.Client` will use a default
24`http.Transport` called `http.DefaultTransport`, which is another global value
25that behaves the same way. So it is not simply enough to replace
26`http.DefaultClient` with `&http.Client{}`.
27
28This repository provides some simple functions to get a "clean" `http.Client`
29-- one that uses the same default values as the Go standard library, but
30returns a client that does not share any state with other clients.
diff --git a/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go b/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go
new file mode 100644
index 0000000..7d8a57c
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go
@@ -0,0 +1,56 @@
1package cleanhttp
2
3import (
4 "net"
5 "net/http"
6 "runtime"
7 "time"
8)
9
10// DefaultTransport returns a new http.Transport with similar default values to
11// http.DefaultTransport, but with idle connections and keepalives disabled.
12func DefaultTransport() *http.Transport {
13 transport := DefaultPooledTransport()
14 transport.DisableKeepAlives = true
15 transport.MaxIdleConnsPerHost = -1
16 return transport
17}
18
19// DefaultPooledTransport returns a new http.Transport with similar default
20// values to http.DefaultTransport. Do not use this for transient transports as
21// it can leak file descriptors over time. Only use this for transports that
22// will be re-used for the same host(s).
23func DefaultPooledTransport() *http.Transport {
24 transport := &http.Transport{
25 Proxy: http.ProxyFromEnvironment,
26 DialContext: (&net.Dialer{
27 Timeout: 30 * time.Second,
28 KeepAlive: 30 * time.Second,
29 }).DialContext,
30 MaxIdleConns: 100,
31 IdleConnTimeout: 90 * time.Second,
32 TLSHandshakeTimeout: 10 * time.Second,
33 ExpectContinueTimeout: 1 * time.Second,
34 MaxIdleConnsPerHost: runtime.GOMAXPROCS(0) + 1,
35 }
36 return transport
37}
38
39// DefaultClient returns a new http.Client with similar default values to
40// http.Client, but with a non-shared Transport, idle connections disabled, and
41// keepalives disabled.
42func DefaultClient() *http.Client {
43 return &http.Client{
44 Transport: DefaultTransport(),
45 }
46}
47
48// DefaultPooledClient returns a new http.Client with similar default values to
49// http.Client, but with a shared Transport. Do not use this function for
50// transient clients as it can leak file descriptors over time. Only use this
51// for clients that will be re-used for the same host(s).
52func DefaultPooledClient() *http.Client {
53 return &http.Client{
54 Transport: DefaultPooledTransport(),
55 }
56}
diff --git a/vendor/github.com/hashicorp/go-cleanhttp/doc.go b/vendor/github.com/hashicorp/go-cleanhttp/doc.go
new file mode 100644
index 0000000..0584109
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-cleanhttp/doc.go
@@ -0,0 +1,20 @@
1// Package cleanhttp offers convenience utilities for acquiring "clean"
2// http.Transport and http.Client structs.
3//
4// Values set on http.DefaultClient and http.DefaultTransport affect all
5// callers. This can have detrimental effects, esepcially in TLS contexts,
6// where client or root certificates set to talk to multiple endpoints can end
7// up displacing each other, leading to hard-to-debug issues. This package
8// provides non-shared http.Client and http.Transport structs to ensure that
9// the configuration will not be overwritten by other parts of the application
10// or dependencies.
11//
12// The DefaultClient and DefaultTransport functions disable idle connections
13// and keepalives. Without ensuring that idle connections are closed before
14// garbage collection, short-term clients/transports can leak file descriptors,
15// eventually leading to "too many open files" errors. If you will be
16// connecting to the same hosts repeatedly from the same client, you can use
17// DefaultPooledClient to receive a client that has connection pooling
18// semantics similar to http.DefaultClient.
19//
20package cleanhttp
diff --git a/vendor/github.com/hashicorp/terraform/config/config.go b/vendor/github.com/hashicorp/terraform/config/config.go
index a157824..3f756dc 100644
--- a/vendor/github.com/hashicorp/terraform/config/config.go
+++ b/vendor/github.com/hashicorp/terraform/config/config.go
@@ -12,6 +12,7 @@ import (
12 "github.com/hashicorp/hil" 12 "github.com/hashicorp/hil"
13 "github.com/hashicorp/hil/ast" 13 "github.com/hashicorp/hil/ast"
14 "github.com/hashicorp/terraform/helper/hilmapstructure" 14 "github.com/hashicorp/terraform/helper/hilmapstructure"
15 "github.com/hashicorp/terraform/plugin/discovery"
15 "github.com/mitchellh/reflectwalk" 16 "github.com/mitchellh/reflectwalk"
16) 17)
17 18
@@ -64,6 +65,7 @@ type Module struct {
64type ProviderConfig struct { 65type ProviderConfig struct {
65 Name string 66 Name string
66 Alias string 67 Alias string
68 Version string
67 RawConfig *RawConfig 69 RawConfig *RawConfig
68} 70}
69 71
@@ -238,6 +240,33 @@ func (r *Resource) Id() string {
238 } 240 }
239} 241}
240 242
243// ProviderFullName returns the full name of the provider for this resource,
244// which may either be specified explicitly using the "provider" meta-argument
245// or implied by the prefix on the resource type name.
246func (r *Resource) ProviderFullName() string {
247 return ResourceProviderFullName(r.Type, r.Provider)
248}
249
250// ResourceProviderFullName returns the full (dependable) name of the
251// provider for a hypothetical resource with the given resource type and
252// explicit provider string. If the explicit provider string is empty then
253// the provider name is inferred from the resource type name.
254func ResourceProviderFullName(resourceType, explicitProvider string) string {
255 if explicitProvider != "" {
256 return explicitProvider
257 }
258
259 idx := strings.IndexRune(resourceType, '_')
260 if idx == -1 {
261 // If no underscores, the resource name is assumed to be
262 // also the provider name, e.g. if the provider exposes
263 // only a single resource of each type.
264 return resourceType
265 }
266
267 return resourceType[:idx]
268}
269
241// Validate does some basic semantic checking of the configuration. 270// Validate does some basic semantic checking of the configuration.
242func (c *Config) Validate() error { 271func (c *Config) Validate() error {
243 if c == nil { 272 if c == nil {
@@ -349,7 +378,8 @@ func (c *Config) Validate() error {
349 } 378 }
350 } 379 }
351 380
352 // Check that providers aren't declared multiple times. 381 // Check that providers aren't declared multiple times and that their
382 // version constraints, where present, are syntactically valid.
353 providerSet := make(map[string]struct{}) 383 providerSet := make(map[string]struct{})
354 for _, p := range c.ProviderConfigs { 384 for _, p := range c.ProviderConfigs {
355 name := p.FullName() 385 name := p.FullName()
@@ -360,6 +390,16 @@ func (c *Config) Validate() error {
360 continue 390 continue
361 } 391 }
362 392
393 if p.Version != "" {
394 _, err := discovery.ConstraintStr(p.Version).Parse()
395 if err != nil {
396 errs = append(errs, fmt.Errorf(
397 "provider.%s: invalid version constraint %q: %s",
398 name, p.Version, err,
399 ))
400 }
401 }
402
363 providerSet[name] = struct{}{} 403 providerSet[name] = struct{}{}
364 } 404 }
365 405
diff --git a/vendor/github.com/hashicorp/terraform/config/interpolate_funcs.go b/vendor/github.com/hashicorp/terraform/config/interpolate_funcs.go
index 7b7b3f2..a298cf2 100644
--- a/vendor/github.com/hashicorp/terraform/config/interpolate_funcs.go
+++ b/vendor/github.com/hashicorp/terraform/config/interpolate_funcs.go
@@ -70,6 +70,7 @@ func Funcs() map[string]ast.Function {
70 "coalescelist": interpolationFuncCoalesceList(), 70 "coalescelist": interpolationFuncCoalesceList(),
71 "compact": interpolationFuncCompact(), 71 "compact": interpolationFuncCompact(),
72 "concat": interpolationFuncConcat(), 72 "concat": interpolationFuncConcat(),
73 "contains": interpolationFuncContains(),
73 "dirname": interpolationFuncDirname(), 74 "dirname": interpolationFuncDirname(),
74 "distinct": interpolationFuncDistinct(), 75 "distinct": interpolationFuncDistinct(),
75 "element": interpolationFuncElement(), 76 "element": interpolationFuncElement(),
@@ -356,6 +357,22 @@ func interpolationFuncCoalesceList() ast.Function {
356 } 357 }
357} 358}
358 359
360// interpolationFuncContains returns true if an element is in the list
361// and return false otherwise
362func interpolationFuncContains() ast.Function {
363 return ast.Function{
364 ArgTypes: []ast.Type{ast.TypeList, ast.TypeString},
365 ReturnType: ast.TypeBool,
366 Callback: func(args []interface{}) (interface{}, error) {
367 _, err := interpolationFuncIndex().Callback(args)
368 if err != nil {
369 return false, nil
370 }
371 return true, nil
372 },
373 }
374}
375
359// interpolationFuncConcat implements the "concat" function that concatenates 376// interpolationFuncConcat implements the "concat" function that concatenates
360// multiple lists. 377// multiple lists.
361func interpolationFuncConcat() ast.Function { 378func interpolationFuncConcat() ast.Function {
diff --git a/vendor/github.com/hashicorp/terraform/config/loader.go b/vendor/github.com/hashicorp/terraform/config/loader.go
index 0bfa89c..5dd7d46 100644
--- a/vendor/github.com/hashicorp/terraform/config/loader.go
+++ b/vendor/github.com/hashicorp/terraform/config/loader.go
@@ -194,7 +194,7 @@ func dirFiles(dir string) ([]string, []string, error) {
194 // Only care about files that are valid to load 194 // Only care about files that are valid to load
195 name := fi.Name() 195 name := fi.Name()
196 extValue := ext(name) 196 extValue := ext(name)
197 if extValue == "" || isIgnoredFile(name) { 197 if extValue == "" || IsIgnoredFile(name) {
198 continue 198 continue
199 } 199 }
200 200
@@ -215,9 +215,9 @@ func dirFiles(dir string) ([]string, []string, error) {
215 return files, overrides, nil 215 return files, overrides, nil
216} 216}
217 217
218// isIgnoredFile returns true or false depending on whether the 218// IsIgnoredFile returns true or false depending on whether the
219// provided file name is a file that should be ignored. 219// provided file name is a file that should be ignored.
220func isIgnoredFile(name string) bool { 220func IsIgnoredFile(name string) bool {
221 return strings.HasPrefix(name, ".") || // Unix-like hidden files 221 return strings.HasPrefix(name, ".") || // Unix-like hidden files
222 strings.HasSuffix(name, "~") || // vim 222 strings.HasSuffix(name, "~") || // vim
223 strings.HasPrefix(name, "#") && strings.HasSuffix(name, "#") // emacs 223 strings.HasPrefix(name, "#") && strings.HasSuffix(name, "#") // emacs
diff --git a/vendor/github.com/hashicorp/terraform/config/loader_hcl.go b/vendor/github.com/hashicorp/terraform/config/loader_hcl.go
index 9abb196..e85e493 100644
--- a/vendor/github.com/hashicorp/terraform/config/loader_hcl.go
+++ b/vendor/github.com/hashicorp/terraform/config/loader_hcl.go
@@ -17,6 +17,20 @@ type hclConfigurable struct {
17 Root *ast.File 17 Root *ast.File
18} 18}
19 19
20var ReservedResourceFields = []string{
21 "connection",
22 "count",
23 "depends_on",
24 "lifecycle",
25 "provider",
26 "provisioner",
27}
28
29var ReservedProviderFields = []string{
30 "alias",
31 "version",
32}
33
20func (t *hclConfigurable) Config() (*Config, error) { 34func (t *hclConfigurable) Config() (*Config, error) {
21 validKeys := map[string]struct{}{ 35 validKeys := map[string]struct{}{
22 "atlas": struct{}{}, 36 "atlas": struct{}{},
@@ -562,6 +576,7 @@ func loadProvidersHcl(list *ast.ObjectList) ([]*ProviderConfig, error) {
562 } 576 }
563 577
564 delete(config, "alias") 578 delete(config, "alias")
579 delete(config, "version")
565 580
566 rawConfig, err := NewRawConfig(config) 581 rawConfig, err := NewRawConfig(config)
567 if err != nil { 582 if err != nil {
@@ -583,9 +598,22 @@ func loadProvidersHcl(list *ast.ObjectList) ([]*ProviderConfig, error) {
583 } 598 }
584 } 599 }
585 600
601 // If we have a version field then extract it
602 var version string
603 if a := listVal.Filter("version"); len(a.Items) > 0 {
604 err := hcl.DecodeObject(&version, a.Items[0].Val)
605 if err != nil {
606 return nil, fmt.Errorf(
607 "Error reading version for provider[%s]: %s",
608 n,
609 err)
610 }
611 }
612
586 result = append(result, &ProviderConfig{ 613 result = append(result, &ProviderConfig{
587 Name: n, 614 Name: n,
588 Alias: alias, 615 Alias: alias,
616 Version: version,
589 RawConfig: rawConfig, 617 RawConfig: rawConfig,
590 }) 618 })
591 } 619 }
diff --git a/vendor/github.com/hashicorp/terraform/config/module/tree.go b/vendor/github.com/hashicorp/terraform/config/module/tree.go
index b6f90fd..4b0b153 100644
--- a/vendor/github.com/hashicorp/terraform/config/module/tree.go
+++ b/vendor/github.com/hashicorp/terraform/config/module/tree.go
@@ -92,6 +92,25 @@ func (t *Tree) Children() map[string]*Tree {
92 return t.children 92 return t.children
93} 93}
94 94
95// DeepEach calls the provided callback for the receiver and then all of
96// its descendents in the tree, allowing an operation to be performed on
97// all modules in the tree.
98//
99// Parents will be visited before their children but otherwise the order is
100// not defined.
101func (t *Tree) DeepEach(cb func(*Tree)) {
102 t.lock.RLock()
103 defer t.lock.RUnlock()
104 t.deepEach(cb)
105}
106
107func (t *Tree) deepEach(cb func(*Tree)) {
108 cb(t)
109 for _, c := range t.children {
110 c.deepEach(cb)
111 }
112}
113
95// Loaded says whether or not this tree has been loaded or not yet. 114// Loaded says whether or not this tree has been loaded or not yet.
96func (t *Tree) Loaded() bool { 115func (t *Tree) Loaded() bool {
97 t.lock.RLock() 116 t.lock.RLock()
diff --git a/vendor/github.com/hashicorp/terraform/config/providers.go b/vendor/github.com/hashicorp/terraform/config/providers.go
new file mode 100644
index 0000000..7a50782
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/config/providers.go
@@ -0,0 +1,103 @@
1package config
2
3import "github.com/blang/semver"
4
5// ProviderVersionConstraint presents a constraint for a particular
6// provider, identified by its full name.
7type ProviderVersionConstraint struct {
8 Constraint string
9 ProviderType string
10}
11
12// ProviderVersionConstraints is a map from provider full name to its associated
13// ProviderVersionConstraint, as produced by Config.RequiredProviders.
14type ProviderVersionConstraints map[string]ProviderVersionConstraint
15
16// RequiredProviders returns the ProviderVersionConstraints for this
17// module.
18//
19// This includes both providers that are explicitly requested by provider
20// blocks and those that are used implicitly by instantiating one of their
21// resource types. In the latter case, the returned semver Range will
22// accept any version of the provider.
23func (c *Config) RequiredProviders() ProviderVersionConstraints {
24 ret := make(ProviderVersionConstraints, len(c.ProviderConfigs))
25
26 configs := c.ProviderConfigsByFullName()
27
28 // In order to find the *implied* dependencies (those without explicit
29 // "provider" blocks) we need to walk over all of the resources and
30 // cross-reference with the provider configs.
31 for _, rc := range c.Resources {
32 providerName := rc.ProviderFullName()
33 var providerType string
34
35 // Default to (effectively) no constraint whatsoever, but we might
36 // override if there's an explicit constraint in config.
37 constraint := ">=0.0.0"
38
39 config, ok := configs[providerName]
40 if ok {
41 if config.Version != "" {
42 constraint = config.Version
43 }
44 providerType = config.Name
45 } else {
46 providerType = providerName
47 }
48
49 ret[providerName] = ProviderVersionConstraint{
50 ProviderType: providerType,
51 Constraint: constraint,
52 }
53 }
54
55 return ret
56}
57
58// RequiredRanges returns a semver.Range for each distinct provider type in
59// the constraint map. If the same provider type appears more than once
60// (e.g. because aliases are in use) then their respective constraints are
61// combined such that they must *all* apply.
62//
63// The result of this method can be passed to the
64// PluginMetaSet.ConstrainVersions method within the plugin/discovery
65// package in order to filter down the available plugins to those which
66// satisfy the given constraints.
67//
68// This function will panic if any of the constraints within cannot be
69// parsed as semver ranges. This is guaranteed to never happen for a
70// constraint set that was built from a configuration that passed validation.
71func (cons ProviderVersionConstraints) RequiredRanges() map[string]semver.Range {
72 ret := make(map[string]semver.Range, len(cons))
73
74 for _, con := range cons {
75 spec := semver.MustParseRange(con.Constraint)
76 if existing, exists := ret[con.ProviderType]; exists {
77 ret[con.ProviderType] = existing.AND(spec)
78 } else {
79 ret[con.ProviderType] = spec
80 }
81 }
82
83 return ret
84}
85
86// ProviderConfigsByFullName returns a map from provider full names (as
87// returned by ProviderConfig.FullName()) to the corresponding provider
88// configs.
89//
90// This function returns no new information than what's already in
91// c.ProviderConfigs, but returns it in a more convenient shape. If there
92// is more than one provider config with the same full name then the result
93// is undefined, but that is guaranteed not to happen for any config that
94// has passed validation.
95func (c *Config) ProviderConfigsByFullName() map[string]*ProviderConfig {
96 ret := make(map[string]*ProviderConfig, len(c.ProviderConfigs))
97
98 for _, pc := range c.ProviderConfigs {
99 ret[pc.FullName()] = pc
100 }
101
102 return ret
103}
diff --git a/vendor/github.com/hashicorp/terraform/flatmap/expand.go b/vendor/github.com/hashicorp/terraform/flatmap/expand.go
index e0b81b6..1449065 100644
--- a/vendor/github.com/hashicorp/terraform/flatmap/expand.go
+++ b/vendor/github.com/hashicorp/terraform/flatmap/expand.go
@@ -60,6 +60,11 @@ func expandArray(m map[string]string, prefix string) []interface{} {
60 return []interface{}{} 60 return []interface{}{}
61 } 61 }
62 62
63 // NOTE: "num" is not necessarily accurate, e.g. if a user tampers
64 // with state, so the following code should not crash when given a
65 // number of items more or less than what's given in num. The
66 // num key is mainly just a hint that this is a list or set.
67
63 // The Schema "Set" type stores its values in an array format, but 68 // The Schema "Set" type stores its values in an array format, but
64 // using numeric hash values instead of ordinal keys. Take the set 69 // using numeric hash values instead of ordinal keys. Take the set
65 // of keys regardless of value, and expand them in numeric order. 70 // of keys regardless of value, and expand them in numeric order.
@@ -101,7 +106,7 @@ func expandArray(m map[string]string, prefix string) []interface{} {
101 } 106 }
102 sort.Ints(keysList) 107 sort.Ints(keysList)
103 108
104 result := make([]interface{}, num) 109 result := make([]interface{}, len(keysList))
105 for i, key := range keysList { 110 for i, key := range keysList {
106 keyString := strconv.Itoa(key) 111 keyString := strconv.Itoa(key)
107 if computed[keyString] { 112 if computed[keyString] {
diff --git a/vendor/github.com/hashicorp/terraform/helper/resource/id.go b/vendor/github.com/hashicorp/terraform/helper/resource/id.go
index 629582b..1cde67c 100644
--- a/vendor/github.com/hashicorp/terraform/helper/resource/id.go
+++ b/vendor/github.com/hashicorp/terraform/helper/resource/id.go
@@ -1,21 +1,17 @@
1package resource 1package resource
2 2
3import ( 3import (
4 "crypto/rand"
5 "fmt" 4 "fmt"
6 "math/big" 5 "strings"
7 "sync" 6 "sync"
7 "time"
8) 8)
9 9
10const UniqueIdPrefix = `terraform-` 10const UniqueIdPrefix = `terraform-`
11 11
12// idCounter is a randomly seeded monotonic counter for generating ordered 12// idCounter is a monotonic counter for generating ordered unique ids.
13// unique ids. It uses a big.Int so we can easily increment a long numeric
14// string. The max possible hex value here with 12 random bytes is
15// "01000000000000000000000000", so there's no chance of rollover during
16// operation.
17var idMutex sync.Mutex 13var idMutex sync.Mutex
18var idCounter = big.NewInt(0).SetBytes(randomBytes(12)) 14var idCounter uint32
19 15
20// Helper for a resource to generate a unique identifier w/ default prefix 16// Helper for a resource to generate a unique identifier w/ default prefix
21func UniqueId() string { 17func UniqueId() string {
@@ -25,15 +21,20 @@ func UniqueId() string {
25// Helper for a resource to generate a unique identifier w/ given prefix 21// Helper for a resource to generate a unique identifier w/ given prefix
26// 22//
27// After the prefix, the ID consists of an incrementing 26 digit value (to match 23// After the prefix, the ID consists of an incrementing 26 digit value (to match
28// previous timestamp output). 24// previous timestamp output). After the prefix, the ID consists of a timestamp
25// and an incrementing 8 hex digit value The timestamp means that multiple IDs
26// created with the same prefix will sort in the order of their creation, even
27// across multiple terraform executions, as long as the clock is not turned back
28// between calls, and as long as any given terraform execution generates fewer
29// than 4 billion IDs.
29func PrefixedUniqueId(prefix string) string { 30func PrefixedUniqueId(prefix string) string {
31 // Be precise to 4 digits of fractional seconds, but remove the dot before the
32 // fractional seconds.
33 timestamp := strings.Replace(
34 time.Now().UTC().Format("20060102150405.0000"), ".", "", 1)
35
30 idMutex.Lock() 36 idMutex.Lock()
31 defer idMutex.Unlock() 37 defer idMutex.Unlock()
32 return fmt.Sprintf("%s%026x", prefix, idCounter.Add(idCounter, big.NewInt(1))) 38 idCounter++
33} 39 return fmt.Sprintf("%s%s%08x", prefix, timestamp, idCounter)
34
35func randomBytes(n int) []byte {
36 b := make([]byte, n)
37 rand.Read(b)
38 return b
39} 40}
diff --git a/vendor/github.com/hashicorp/terraform/helper/resource/testing.go b/vendor/github.com/hashicorp/terraform/helper/resource/testing.go
index ebdbde2..d7de1a0 100644
--- a/vendor/github.com/hashicorp/terraform/helper/resource/testing.go
+++ b/vendor/github.com/hashicorp/terraform/helper/resource/testing.go
@@ -383,11 +383,11 @@ func Test(t TestT, c TestCase) {
383 c.PreCheck() 383 c.PreCheck()
384 } 384 }
385 385
386 ctxProviders, err := testProviderFactories(c) 386 providerResolver, err := testProviderResolver(c)
387 if err != nil { 387 if err != nil {
388 t.Fatal(err) 388 t.Fatal(err)
389 } 389 }
390 opts := terraform.ContextOpts{Providers: ctxProviders} 390 opts := terraform.ContextOpts{ProviderResolver: providerResolver}
391 391
392 // A single state variable to track the lifecycle, starting with no state 392 // A single state variable to track the lifecycle, starting with no state
393 var state *terraform.State 393 var state *terraform.State
@@ -400,15 +400,22 @@ func Test(t TestT, c TestCase) {
400 var err error 400 var err error
401 log.Printf("[WARN] Test: Executing step %d", i) 401 log.Printf("[WARN] Test: Executing step %d", i)
402 402
403 // Determine the test mode to execute 403 if step.Config == "" && !step.ImportState {
404 if step.Config != "" {
405 state, err = testStepConfig(opts, state, step)
406 } else if step.ImportState {
407 state, err = testStepImportState(opts, state, step)
408 } else {
409 err = fmt.Errorf( 404 err = fmt.Errorf(
410 "unknown test mode for step. Please see TestStep docs\n\n%#v", 405 "unknown test mode for step. Please see TestStep docs\n\n%#v",
411 step) 406 step)
407 } else {
408 if step.ImportState {
409 if step.Config == "" {
410 step.Config = testProviderConfig(c)
411 }
412
413 // Can optionally set step.Config in addition to
414 // step.ImportState, to provide config for the import.
415 state, err = testStepImportState(opts, state, step)
416 } else {
417 state, err = testStepConfig(opts, state, step)
418 }
412 } 419 }
413 420
414 // If there was an error, exit 421 // If there was an error, exit
@@ -496,16 +503,29 @@ func Test(t TestT, c TestCase) {
496 } 503 }
497} 504}
498 505
499// testProviderFactories is a helper to build the ResourceProviderFactory map 506// testProviderConfig takes the list of Providers in a TestCase and returns a
507// config with only empty provider blocks. This is useful for Import, where no
508// config is provided, but the providers must be defined.
509func testProviderConfig(c TestCase) string {
510 var lines []string
511 for p := range c.Providers {
512 lines = append(lines, fmt.Sprintf("provider %q {}\n", p))
513 }
514
515 return strings.Join(lines, "")
516}
517
518// testProviderResolver is a helper to build a ResourceProviderResolver
500// with pre instantiated ResourceProviders, so that we can reset them for the 519// with pre instantiated ResourceProviders, so that we can reset them for the
501// test, while only calling the factory function once. 520// test, while only calling the factory function once.
502// Any errors are stored so that they can be returned by the factory in 521// Any errors are stored so that they can be returned by the factory in
503// terraform to match non-test behavior. 522// terraform to match non-test behavior.
504func testProviderFactories(c TestCase) (map[string]terraform.ResourceProviderFactory, error) { 523func testProviderResolver(c TestCase) (terraform.ResourceProviderResolver, error) {
505 ctxProviders := c.ProviderFactories // make(map[string]terraform.ResourceProviderFactory) 524 ctxProviders := c.ProviderFactories
506 if ctxProviders == nil { 525 if ctxProviders == nil {
507 ctxProviders = make(map[string]terraform.ResourceProviderFactory) 526 ctxProviders = make(map[string]terraform.ResourceProviderFactory)
508 } 527 }
528
509 // add any fixed providers 529 // add any fixed providers
510 for k, p := range c.Providers { 530 for k, p := range c.Providers {
511 ctxProviders[k] = terraform.ResourceProviderFactoryFixed(p) 531 ctxProviders[k] = terraform.ResourceProviderFactoryFixed(p)
@@ -527,7 +547,7 @@ func testProviderFactories(c TestCase) (map[string]terraform.ResourceProviderFac
527 } 547 }
528 } 548 }
529 549
530 return ctxProviders, nil 550 return terraform.ResourceProviderResolverFixed(ctxProviders), nil
531} 551}
532 552
533// UnitTest is a helper to force the acceptance testing harness to run in the 553// UnitTest is a helper to force the acceptance testing harness to run in the
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/provider.go b/vendor/github.com/hashicorp/terraform/helper/schema/provider.go
index d52d2f5..fb28b41 100644
--- a/vendor/github.com/hashicorp/terraform/helper/schema/provider.go
+++ b/vendor/github.com/hashicorp/terraform/helper/schema/provider.go
@@ -8,6 +8,7 @@ import (
8 "sync" 8 "sync"
9 9
10 "github.com/hashicorp/go-multierror" 10 "github.com/hashicorp/go-multierror"
11 "github.com/hashicorp/terraform/config"
11 "github.com/hashicorp/terraform/terraform" 12 "github.com/hashicorp/terraform/terraform"
12) 13)
13 14
@@ -89,6 +90,13 @@ func (p *Provider) InternalValidate() error {
89 validationErrors = multierror.Append(validationErrors, err) 90 validationErrors = multierror.Append(validationErrors, err)
90 } 91 }
91 92
93 // Provider-specific checks
94 for k, _ := range sm {
95 if isReservedProviderFieldName(k) {
96 return fmt.Errorf("%s is a reserved field name for a provider", k)
97 }
98 }
99
92 for k, r := range p.ResourcesMap { 100 for k, r := range p.ResourcesMap {
93 if err := r.InternalValidate(nil, true); err != nil { 101 if err := r.InternalValidate(nil, true); err != nil {
94 validationErrors = multierror.Append(validationErrors, fmt.Errorf("resource %s: %s", k, err)) 102 validationErrors = multierror.Append(validationErrors, fmt.Errorf("resource %s: %s", k, err))
@@ -104,6 +112,15 @@ func (p *Provider) InternalValidate() error {
104 return validationErrors 112 return validationErrors
105} 113}
106 114
115func isReservedProviderFieldName(name string) bool {
116 for _, reservedName := range config.ReservedProviderFields {
117 if name == reservedName {
118 return true
119 }
120 }
121 return false
122}
123
107// Meta returns the metadata associated with this provider that was 124// Meta returns the metadata associated with this provider that was
108// returned by the Configure call. It will be nil until Configure is called. 125// returned by the Configure call. It will be nil until Configure is called.
109func (p *Provider) Meta() interface{} { 126func (p *Provider) Meta() interface{} {
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go b/vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go
index 856c675..476192e 100644
--- a/vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go
+++ b/vendor/github.com/hashicorp/terraform/helper/schema/provisioner.go
@@ -43,7 +43,7 @@ type Provisioner struct {
43 43
44 // ValidateFunc is a function for extended validation. This is optional 44 // ValidateFunc is a function for extended validation. This is optional
45 // and should be used when individual field validation is not enough. 45 // and should be used when individual field validation is not enough.
46 ValidateFunc func(*ResourceData) ([]string, []error) 46 ValidateFunc func(*terraform.ResourceConfig) ([]string, []error)
47 47
48 stopCtx context.Context 48 stopCtx context.Context
49 stopCtxCancel context.CancelFunc 49 stopCtxCancel context.CancelFunc
@@ -121,32 +121,6 @@ func (p *Provisioner) Stop() error {
121 return nil 121 return nil
122} 122}
123 123
124func (p *Provisioner) Validate(config *terraform.ResourceConfig) ([]string, []error) {
125 if err := p.InternalValidate(); err != nil {
126 return nil, []error{fmt.Errorf(
127 "Internal validation of the provisioner failed! This is always a bug\n"+
128 "with the provisioner itself, and not a user issue. Please report\n"+
129 "this bug:\n\n%s", err)}
130 }
131 w := []string{}
132 e := []error{}
133 if p.Schema != nil {
134 w2, e2 := schemaMap(p.Schema).Validate(config)
135 w = append(w, w2...)
136 e = append(e, e2...)
137 }
138 if p.ValidateFunc != nil {
139 data := &ResourceData{
140 schema: p.Schema,
141 config: config,
142 }
143 w2, e2 := p.ValidateFunc(data)
144 w = append(w, w2...)
145 e = append(e, e2...)
146 }
147 return w, e
148}
149
150// Apply implementation of terraform.ResourceProvisioner interface. 124// Apply implementation of terraform.ResourceProvisioner interface.
151func (p *Provisioner) Apply( 125func (p *Provisioner) Apply(
152 o terraform.UIOutput, 126 o terraform.UIOutput,
@@ -204,3 +178,27 @@ func (p *Provisioner) Apply(
204 ctx = context.WithValue(ctx, ProvRawStateKey, s) 178 ctx = context.WithValue(ctx, ProvRawStateKey, s)
205 return p.ApplyFunc(ctx) 179 return p.ApplyFunc(ctx)
206} 180}
181
182// Validate implements the terraform.ResourceProvisioner interface.
183func (p *Provisioner) Validate(c *terraform.ResourceConfig) (ws []string, es []error) {
184 if err := p.InternalValidate(); err != nil {
185 return nil, []error{fmt.Errorf(
186 "Internal validation of the provisioner failed! This is always a bug\n"+
187 "with the provisioner itself, and not a user issue. Please report\n"+
188 "this bug:\n\n%s", err)}
189 }
190
191 if p.Schema != nil {
192 w, e := schemaMap(p.Schema).Validate(c)
193 ws = append(ws, w...)
194 es = append(es, e...)
195 }
196
197 if p.ValidateFunc != nil {
198 w, e := p.ValidateFunc(c)
199 ws = append(ws, w...)
200 es = append(es, e...)
201 }
202
203 return ws, es
204}
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/resource.go b/vendor/github.com/hashicorp/terraform/helper/schema/resource.go
index c810558..ddba109 100644
--- a/vendor/github.com/hashicorp/terraform/helper/schema/resource.go
+++ b/vendor/github.com/hashicorp/terraform/helper/schema/resource.go
@@ -6,6 +6,7 @@ import (
6 "log" 6 "log"
7 "strconv" 7 "strconv"
8 8
9 "github.com/hashicorp/terraform/config"
9 "github.com/hashicorp/terraform/terraform" 10 "github.com/hashicorp/terraform/terraform"
10) 11)
11 12
@@ -142,6 +143,12 @@ func (r *Resource) Apply(
142 if err := rt.DiffDecode(d); err != nil { 143 if err := rt.DiffDecode(d); err != nil {
143 log.Printf("[ERR] Error decoding ResourceTimeout: %s", err) 144 log.Printf("[ERR] Error decoding ResourceTimeout: %s", err)
144 } 145 }
146 } else if s != nil {
147 if _, ok := s.Meta[TimeoutKey]; ok {
148 if err := rt.StateDecode(s); err != nil {
149 log.Printf("[ERR] Error decoding ResourceTimeout: %s", err)
150 }
151 }
145 } else { 152 } else {
146 log.Printf("[DEBUG] No meta timeoutkey found in Apply()") 153 log.Printf("[DEBUG] No meta timeoutkey found in Apply()")
147 } 154 }
@@ -388,9 +395,25 @@ func (r *Resource) InternalValidate(topSchemaMap schemaMap, writable bool) error
388 } 395 }
389 } 396 }
390 397
398 // Resource-specific checks
399 for k, _ := range tsm {
400 if isReservedResourceFieldName(k) {
401 return fmt.Errorf("%s is a reserved field name for a resource", k)
402 }
403 }
404
391 return schemaMap(r.Schema).InternalValidate(tsm) 405 return schemaMap(r.Schema).InternalValidate(tsm)
392} 406}
393 407
408func isReservedResourceFieldName(name string) bool {
409 for _, reservedName := range config.ReservedResourceFields {
410 if name == reservedName {
411 return true
412 }
413 }
414 return false
415}
416
394// Data returns a ResourceData struct for this Resource. Each return value 417// Data returns a ResourceData struct for this Resource. Each return value
395// is a separate copy and can be safely modified differently. 418// is a separate copy and can be safely modified differently.
396// 419//
diff --git a/vendor/github.com/hashicorp/terraform/helper/schema/schema.go b/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
index 632672a..acb5618 100644
--- a/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
+++ b/vendor/github.com/hashicorp/terraform/helper/schema/schema.go
@@ -15,6 +15,7 @@ import (
15 "fmt" 15 "fmt"
16 "os" 16 "os"
17 "reflect" 17 "reflect"
18 "regexp"
18 "sort" 19 "sort"
19 "strconv" 20 "strconv"
20 "strings" 21 "strings"
@@ -661,7 +662,13 @@ func (m schemaMap) InternalValidate(topSchemaMap schemaMap) error {
661 if v.ValidateFunc != nil { 662 if v.ValidateFunc != nil {
662 switch v.Type { 663 switch v.Type {
663 case TypeList, TypeSet: 664 case TypeList, TypeSet:
664 return fmt.Errorf("ValidateFunc is not yet supported on lists or sets.") 665 return fmt.Errorf("%s: ValidateFunc is not yet supported on lists or sets.", k)
666 }
667 }
668
669 if v.Deprecated == "" && v.Removed == "" {
670 if !isValidFieldName(k) {
671 return fmt.Errorf("%s: Field name may only contain lowercase alphanumeric characters & underscores.", k)
665 } 672 }
666 } 673 }
667 } 674 }
@@ -669,6 +676,11 @@ func (m schemaMap) InternalValidate(topSchemaMap schemaMap) error {
669 return nil 676 return nil
670} 677}
671 678
679func isValidFieldName(name string) bool {
680 re := regexp.MustCompile("^[a-z0-9_]+$")
681 return re.MatchString(name)
682}
683
672func (m schemaMap) diff( 684func (m schemaMap) diff(
673 k string, 685 k string,
674 schema *Schema, 686 schema *Schema,
diff --git a/vendor/github.com/hashicorp/terraform/helper/shadow/closer.go b/vendor/github.com/hashicorp/terraform/helper/shadow/closer.go
index 7edd5e7..edc1e2a 100644
--- a/vendor/github.com/hashicorp/terraform/helper/shadow/closer.go
+++ b/vendor/github.com/hashicorp/terraform/helper/shadow/closer.go
@@ -39,6 +39,8 @@ func (w *closeWalker) Struct(reflect.Value) error {
39 return nil 39 return nil
40} 40}
41 41
42var closerType = reflect.TypeOf((*io.Closer)(nil)).Elem()
43
42func (w *closeWalker) StructField(f reflect.StructField, v reflect.Value) error { 44func (w *closeWalker) StructField(f reflect.StructField, v reflect.Value) error {
43 // Not sure why this would be but lets avoid some panics 45 // Not sure why this would be but lets avoid some panics
44 if !v.IsValid() { 46 if !v.IsValid() {
@@ -56,17 +58,18 @@ func (w *closeWalker) StructField(f reflect.StructField, v reflect.Value) error
56 return nil 58 return nil
57 } 59 }
58 60
59 // We're looking for an io.Closer 61 var closer io.Closer
60 raw := v.Interface() 62 if v.Type().Implements(closerType) {
61 if raw == nil { 63 closer = v.Interface().(io.Closer)
62 return nil 64 } else if v.CanAddr() {
65 // The Close method may require a pointer receiver, but we only have a value.
66 v := v.Addr()
67 if v.Type().Implements(closerType) {
68 closer = v.Interface().(io.Closer)
69 }
63 } 70 }
64 71
65 closer, ok := raw.(io.Closer) 72 if closer == nil {
66 if !ok && v.CanAddr() {
67 closer, ok = v.Addr().Interface().(io.Closer)
68 }
69 if !ok {
70 return reflectwalk.SkipEntry 73 return reflectwalk.SkipEntry
71 } 74 }
72 75
diff --git a/vendor/github.com/hashicorp/terraform/helper/shadow/value.go b/vendor/github.com/hashicorp/terraform/helper/shadow/value.go
index 2413335..178b7e7 100644
--- a/vendor/github.com/hashicorp/terraform/helper/shadow/value.go
+++ b/vendor/github.com/hashicorp/terraform/helper/shadow/value.go
@@ -26,6 +26,14 @@ type Value struct {
26 valueSet bool 26 valueSet bool
27} 27}
28 28
29func (v *Value) Lock() {
30 v.lock.Lock()
31}
32
33func (v *Value) Unlock() {
34 v.lock.Unlock()
35}
36
29// Close closes the value. This can never fail. For a definition of 37// Close closes the value. This can never fail. For a definition of
30// "close" see the struct docs. 38// "close" see the struct docs.
31func (w *Value) Close() error { 39func (w *Value) Close() error {
diff --git a/vendor/github.com/hashicorp/terraform/moduledeps/dependencies.go b/vendor/github.com/hashicorp/terraform/moduledeps/dependencies.go
new file mode 100644
index 0000000..87c8431
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/moduledeps/dependencies.go
@@ -0,0 +1,43 @@
1package moduledeps
2
3import (
4 "github.com/hashicorp/terraform/plugin/discovery"
5)
6
7// Providers describes a set of provider dependencies for a given module.
8//
9// Each named provider instance can have one version constraint.
10type Providers map[ProviderInstance]ProviderDependency
11
12// ProviderDependency describes the dependency for a particular provider
13// instance, including both the set of allowed versions and the reason for
14// the dependency.
15type ProviderDependency struct {
16 Constraints discovery.Constraints
17 Reason ProviderDependencyReason
18}
19
20// ProviderDependencyReason is an enumeration of reasons why a dependency might be
21// present.
22type ProviderDependencyReason int
23
24const (
25 // ProviderDependencyExplicit means that there is an explicit "provider"
26 // block in the configuration for this module.
27 ProviderDependencyExplicit ProviderDependencyReason = iota
28
29 // ProviderDependencyImplicit means that there is no explicit "provider"
30 // block but there is at least one resource that uses this provider.
31 ProviderDependencyImplicit
32
33 // ProviderDependencyInherited is a special case of
34 // ProviderDependencyImplicit where a parent module has defined a
35 // configuration for the provider that has been inherited by at least one
36 // resource in this module.
37 ProviderDependencyInherited
38
39 // ProviderDependencyFromState means that this provider is not currently
40 // referenced by configuration at all, but some existing instances in
41 // the state still depend on it.
42 ProviderDependencyFromState
43)
diff --git a/vendor/github.com/hashicorp/terraform/moduledeps/doc.go b/vendor/github.com/hashicorp/terraform/moduledeps/doc.go
new file mode 100644
index 0000000..7eff083
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/moduledeps/doc.go
@@ -0,0 +1,7 @@
1// Package moduledeps contains types that can be used to describe the
2// providers required for all of the modules in a module tree.
3//
4// It does not itself contain the functionality for populating such
5// data structures; that's in Terraform core, since this package intentionally
6// does not depend on terraform core to avoid package dependency cycles.
7package moduledeps
diff --git a/vendor/github.com/hashicorp/terraform/moduledeps/module.go b/vendor/github.com/hashicorp/terraform/moduledeps/module.go
new file mode 100644
index 0000000..d6cbaf5
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/moduledeps/module.go
@@ -0,0 +1,204 @@
1package moduledeps
2
3import (
4 "sort"
5 "strings"
6
7 "github.com/hashicorp/terraform/plugin/discovery"
8)
9
10// Module represents the dependencies of a single module, as well being
11// a node in a tree of such structures representing the dependencies of
12// an entire configuration.
13type Module struct {
14 Name string
15 Providers Providers
16 Children []*Module
17}
18
19// WalkFunc is a callback type for use with Module.WalkTree
20type WalkFunc func(path []string, parent *Module, current *Module) error
21
22// WalkTree calls the given callback once for the receiver and then
23// once for each descendent, in an order such that parents are called
24// before their children and siblings are called in the order they
25// appear in the Children slice.
26//
27// When calling the callback, parent will be nil for the first call
28// for the receiving module, and then set to the direct parent of
29// each module for the subsequent calls.
30//
31// The path given to the callback is valid only until the callback
32// returns, after which it will be mutated and reused. Callbacks must
33// therefore copy the path slice if they wish to retain it.
34//
35// If the given callback returns an error, the walk will be aborted at
36// that point and that error returned to the caller.
37//
38// This function is not thread-safe for concurrent modifications of the
39// data structure, so it's the caller's responsibility to arrange for that
40// should it be needed.
41//
42// It is safe for a callback to modify the descendents of the "current"
43// module, including the ordering of the Children slice itself, but the
44// callback MUST NOT modify the parent module.
45func (m *Module) WalkTree(cb WalkFunc) error {
46 return walkModuleTree(make([]string, 0, 1), nil, m, cb)
47}
48
49func walkModuleTree(path []string, parent *Module, current *Module, cb WalkFunc) error {
50 path = append(path, current.Name)
51 err := cb(path, parent, current)
52 if err != nil {
53 return err
54 }
55
56 for _, child := range current.Children {
57 err := walkModuleTree(path, current, child, cb)
58 if err != nil {
59 return err
60 }
61 }
62 return nil
63}
64
65// SortChildren sorts the Children slice into lexicographic order by
66// name, in-place.
67//
68// This is primarily useful prior to calling WalkTree so that the walk
69// will proceed in a consistent order.
70func (m *Module) SortChildren() {
71 sort.Sort(sortModules{m.Children})
72}
73
74// SortDescendents is a convenience wrapper for calling SortChildren on
75// the receiver and all of its descendent modules.
76func (m *Module) SortDescendents() {
77 m.WalkTree(func(path []string, parent *Module, current *Module) error {
78 current.SortChildren()
79 return nil
80 })
81}
82
83type sortModules struct {
84 modules []*Module
85}
86
87func (s sortModules) Len() int {
88 return len(s.modules)
89}
90
91func (s sortModules) Less(i, j int) bool {
92 cmp := strings.Compare(s.modules[i].Name, s.modules[j].Name)
93 return cmp < 0
94}
95
96func (s sortModules) Swap(i, j int) {
97 s.modules[i], s.modules[j] = s.modules[j], s.modules[i]
98}
99
100// PluginRequirements produces a PluginRequirements structure that can
101// be used with discovery.PluginMetaSet.ConstrainVersions to identify
102// suitable plugins to satisfy the module's provider dependencies.
103//
104// This method only considers the direct requirements of the receiver.
105// Use AllPluginRequirements to flatten the dependencies for the
106// entire tree of modules.
107//
108// Requirements returned by this method include only version constraints,
109// and apply no particular SHA256 hash constraint.
110func (m *Module) PluginRequirements() discovery.PluginRequirements {
111 ret := make(discovery.PluginRequirements)
112 for inst, dep := range m.Providers {
113 // m.Providers is keyed on provider names, such as "aws.foo".
114 // a PluginRequirements wants keys to be provider *types*, such
115 // as "aws". If there are multiple aliases for the same
116 // provider then we will flatten them into a single requirement
117 // by combining their constraint sets.
118 pty := inst.Type()
119 if existing, exists := ret[pty]; exists {
120 ret[pty].Versions = existing.Versions.Append(dep.Constraints)
121 } else {
122 ret[pty] = &discovery.PluginConstraints{
123 Versions: dep.Constraints,
124 }
125 }
126 }
127 return ret
128}
129
130// AllPluginRequirements calls PluginRequirements for the receiver and all
131// of its descendents, and merges the result into a single PluginRequirements
132// structure that would satisfy all of the modules together.
133//
134// Requirements returned by this method include only version constraints,
135// and apply no particular SHA256 hash constraint.
136func (m *Module) AllPluginRequirements() discovery.PluginRequirements {
137 var ret discovery.PluginRequirements
138 m.WalkTree(func(path []string, parent *Module, current *Module) error {
139 ret = ret.Merge(current.PluginRequirements())
140 return nil
141 })
142 return ret
143}
144
145// Equal returns true if the receiver is the root of an identical tree
146// to the other given Module. This is a deep comparison that considers
147// the equality of all downstream modules too.
148//
149// The children are considered to be ordered, so callers may wish to use
150// SortDescendents first to normalize the order of the slices of child nodes.
151//
152// The implementation of this function is not optimized since it is provided
153// primarily for use in tests.
154func (m *Module) Equal(other *Module) bool {
155 // take care of nils first
156 if m == nil && other == nil {
157 return true
158 } else if (m == nil && other != nil) || (m != nil && other == nil) {
159 return false
160 }
161
162 if m.Name != other.Name {
163 return false
164 }
165
166 if len(m.Providers) != len(other.Providers) {
167 return false
168 }
169 if len(m.Children) != len(other.Children) {
170 return false
171 }
172
173 // Can't use reflect.DeepEqual on this provider structure because
174 // the nested Constraints objects contain function pointers that
175 // never compare as equal. So we'll need to walk it the long way.
176 for inst, dep := range m.Providers {
177 if _, exists := other.Providers[inst]; !exists {
178 return false
179 }
180
181 if dep.Reason != other.Providers[inst].Reason {
182 return false
183 }
184
185 // Constraints are not too easy to compare robustly, so
186 // we'll just use their string representations as a proxy
187 // for now.
188 if dep.Constraints.String() != other.Providers[inst].Constraints.String() {
189 return false
190 }
191 }
192
193 // Above we already checked that we have the same number of children
194 // in each module, so now we just need to check that they are
195 // recursively equal.
196 for i := range m.Children {
197 if !m.Children[i].Equal(other.Children[i]) {
198 return false
199 }
200 }
201
202 // If we fall out here then they are equal
203 return true
204}
diff --git a/vendor/github.com/hashicorp/terraform/moduledeps/provider.go b/vendor/github.com/hashicorp/terraform/moduledeps/provider.go
new file mode 100644
index 0000000..89ceefb
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/moduledeps/provider.go
@@ -0,0 +1,30 @@
1package moduledeps
2
3import (
4 "strings"
5)
6
7// ProviderInstance describes a particular provider instance by its full name,
8// like "null" or "aws.foo".
9type ProviderInstance string
10
11// Type returns the provider type of this instance. For example, for an instance
12// named "aws.foo" the type is "aws".
13func (p ProviderInstance) Type() string {
14 t := string(p)
15 if dotPos := strings.Index(t, "."); dotPos != -1 {
16 t = t[:dotPos]
17 }
18 return t
19}
20
21// Alias returns the alias of this provider, if any. An instance named "aws.foo"
22// has the alias "foo", while an instance named just "docker" has no alias,
23// so the empty string would be returned.
24func (p ProviderInstance) Alias() string {
25 t := string(p)
26 if dotPos := strings.Index(t, "."); dotPos != -1 {
27 return t[dotPos+1:]
28 }
29 return ""
30}
diff --git a/vendor/github.com/hashicorp/terraform/plugin/client.go b/vendor/github.com/hashicorp/terraform/plugin/client.go
new file mode 100644
index 0000000..3a5cb7a
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/plugin/client.go
@@ -0,0 +1,24 @@
1package plugin
2
3import (
4 "os/exec"
5
6 plugin "github.com/hashicorp/go-plugin"
7 "github.com/hashicorp/terraform/plugin/discovery"
8)
9
10// ClientConfig returns a configuration object that can be used to instantiate
11// a client for the plugin described by the given metadata.
12func ClientConfig(m discovery.PluginMeta) *plugin.ClientConfig {
13 return &plugin.ClientConfig{
14 Cmd: exec.Command(m.Path),
15 HandshakeConfig: Handshake,
16 Managed: true,
17 Plugins: PluginMap,
18 }
19}
20
21// Client returns a plugin client for the plugin described by the given metadata.
22func Client(m discovery.PluginMeta) *plugin.Client {
23 return plugin.NewClient(ClientConfig(m))
24}
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/error.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/error.go
new file mode 100644
index 0000000..df855a7
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/error.go
@@ -0,0 +1,30 @@
1package discovery
2
3// Error is a type used to describe situations that the caller must handle
4// since they indicate some form of user error.
5//
6// The functions and methods that return these specialized errors indicate so
7// in their documentation. The Error type should not itself be used directly,
8// but rather errors should be compared using the == operator with the
9// error constants in this package.
10//
11// Values of this type are _not_ used when the error being reported is an
12// operational error (server unavailable, etc) or indicative of a bug in
13// this package or its caller.
14type Error string
15
16// ErrorNoSuitableVersion indicates that a suitable version (meeting given
17// constraints) is not available.
18const ErrorNoSuitableVersion = Error("no suitable version is available")
19
20// ErrorNoVersionCompatible indicates that all of the available versions
21// that otherwise met constraints are not compatible with the current
22// version of Terraform.
23const ErrorNoVersionCompatible = Error("no available version is compatible with this version of Terraform")
24
25// ErrorNoSuchProvider indicates that no provider exists with a name given
26const ErrorNoSuchProvider = Error("no provider exists with the given name")
27
28func (err Error) Error() string {
29 return string(err)
30}
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/find.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/find.go
new file mode 100644
index 0000000..f5bc4c1
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/find.go
@@ -0,0 +1,168 @@
1package discovery
2
3import (
4 "io/ioutil"
5 "log"
6 "path/filepath"
7 "strings"
8)
9
10// FindPlugins looks in the given directories for files whose filenames
11// suggest that they are plugins of the given kind (e.g. "provider") and
12// returns a PluginMetaSet representing the discovered potential-plugins.
13//
14// Currently this supports two different naming schemes. The current
15// standard naming scheme is a subdirectory called $GOOS-$GOARCH containing
16// files named terraform-$KIND-$NAME-V$VERSION. The legacy naming scheme is
17// files directly in the given directory whose names are like
18// terraform-$KIND-$NAME.
19//
20// Only one plugin will be returned for each unique plugin (name, version)
21// pair, with preference given to files found in earlier directories.
22//
23// This is a convenience wrapper around FindPluginPaths and ResolvePluginsPaths.
24func FindPlugins(kind string, dirs []string) PluginMetaSet {
25 return ResolvePluginPaths(FindPluginPaths(kind, dirs))
26}
27
28// FindPluginPaths looks in the given directories for files whose filenames
29// suggest that they are plugins of the given kind (e.g. "provider").
30//
31// The return value is a list of absolute paths that appear to refer to
32// plugins in the given directories, based only on what can be inferred
33// from the naming scheme. The paths returned are ordered such that files
34// in later dirs appear after files in earlier dirs in the given directory
35// list. Within the same directory plugins are returned in a consistent but
36// undefined order.
37func FindPluginPaths(kind string, dirs []string) []string {
38 // This is just a thin wrapper around findPluginPaths so that we can
39 // use the latter in tests with a fake machineName so we can use our
40 // test fixtures.
41 return findPluginPaths(kind, dirs)
42}
43
44func findPluginPaths(kind string, dirs []string) []string {
45 prefix := "terraform-" + kind + "-"
46
47 ret := make([]string, 0, len(dirs))
48
49 for _, dir := range dirs {
50 items, err := ioutil.ReadDir(dir)
51 if err != nil {
52 // Ignore missing dirs, non-dirs, etc
53 continue
54 }
55
56 log.Printf("[DEBUG] checking for %s in %q", kind, dir)
57
58 for _, item := range items {
59 fullName := item.Name()
60
61 if !strings.HasPrefix(fullName, prefix) {
62 log.Printf("[DEBUG] skipping %q, not a %s", fullName, kind)
63 continue
64 }
65
66 // New-style paths must have a version segment in filename
67 if strings.Contains(strings.ToLower(fullName), "_v") {
68 absPath, err := filepath.Abs(filepath.Join(dir, fullName))
69 if err != nil {
70 log.Printf("[ERROR] plugin filepath error: %s", err)
71 continue
72 }
73
74 log.Printf("[DEBUG] found %s %q", kind, fullName)
75 ret = append(ret, filepath.Clean(absPath))
76 continue
77 }
78
79 // Legacy style with files directly in the base directory
80 absPath, err := filepath.Abs(filepath.Join(dir, fullName))
81 if err != nil {
82 log.Printf("[ERROR] plugin filepath error: %s", err)
83 continue
84 }
85
86 log.Printf("[WARNING] found legacy %s %q", kind, fullName)
87
88 ret = append(ret, filepath.Clean(absPath))
89 }
90 }
91
92 return ret
93}
94
95// ResolvePluginPaths takes a list of paths to plugin executables (as returned
96// by e.g. FindPluginPaths) and produces a PluginMetaSet describing the
97// referenced plugins.
98//
99// If the same combination of plugin name and version appears multiple times,
100// the earlier reference will be preferred. Several different versions of
101// the same plugin name may be returned, in which case the methods of
102// PluginMetaSet can be used to filter down.
103func ResolvePluginPaths(paths []string) PluginMetaSet {
104 s := make(PluginMetaSet)
105
106 type nameVersion struct {
107 Name string
108 Version string
109 }
110 found := make(map[nameVersion]struct{})
111
112 for _, path := range paths {
113 baseName := strings.ToLower(filepath.Base(path))
114 if !strings.HasPrefix(baseName, "terraform-") {
115 // Should never happen with reasonable input
116 continue
117 }
118
119 baseName = baseName[10:]
120 firstDash := strings.Index(baseName, "-")
121 if firstDash == -1 {
122 // Should never happen with reasonable input
123 continue
124 }
125
126 baseName = baseName[firstDash+1:]
127 if baseName == "" {
128 // Should never happen with reasonable input
129 continue
130 }
131
132 // Trim the .exe suffix used on Windows before we start wrangling
133 // the remainder of the path.
134 if strings.HasSuffix(baseName, ".exe") {
135 baseName = baseName[:len(baseName)-4]
136 }
137
138 parts := strings.SplitN(baseName, "_v", 2)
139 name := parts[0]
140 version := VersionZero
141 if len(parts) == 2 {
142 version = parts[1]
143 }
144
145 // Auto-installed plugins contain an extra name portion representing
146 // the expected plugin version, which we must trim off.
147 if underX := strings.Index(version, "_x"); underX != -1 {
148 version = version[:underX]
149 }
150
151 if _, ok := found[nameVersion{name, version}]; ok {
152 // Skip duplicate versions of the same plugin
153 // (We do this during this step because after this we will be
154 // dealing with sets and thus lose our ordering with which to
155 // decide preference.)
156 continue
157 }
158
159 s.Add(PluginMeta{
160 Name: name,
161 Version: VersionStr(version),
162 Path: path,
163 })
164 found[nameVersion{name, version}] = struct{}{}
165 }
166
167 return s
168}
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/get.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/get.go
new file mode 100644
index 0000000..241b5cb
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/get.go
@@ -0,0 +1,424 @@
1package discovery
2
3import (
4 "errors"
5 "fmt"
6 "io/ioutil"
7 "log"
8 "net/http"
9 "os"
10 "runtime"
11 "strconv"
12 "strings"
13
14 "golang.org/x/net/html"
15
16 cleanhttp "github.com/hashicorp/go-cleanhttp"
17 getter "github.com/hashicorp/go-getter"
18 multierror "github.com/hashicorp/go-multierror"
19)
20
21// Releases are located by parsing the html listing from releases.hashicorp.com.
22//
23// The URL for releases follows the pattern:
24// https://releases.hashicorp.com/terraform-provider-name/<x.y.z>/terraform-provider-name_<x.y.z>_<os>_<arch>.<ext>
25//
26// The plugin protocol version will be saved with the release and returned in
27// the header X-TERRAFORM_PROTOCOL_VERSION.
28
29const protocolVersionHeader = "x-terraform-protocol-version"
30
31var releaseHost = "https://releases.hashicorp.com"
32
33var httpClient = cleanhttp.DefaultClient()
34
35// An Installer maintains a local cache of plugins by downloading plugins
36// from an online repository.
37type Installer interface {
38 Get(name string, req Constraints) (PluginMeta, error)
39 PurgeUnused(used map[string]PluginMeta) (removed PluginMetaSet, err error)
40}
41
42// ProviderInstaller is an Installer implementation that knows how to
43// download Terraform providers from the official HashiCorp releases service
44// into a local directory. The files downloaded are compliant with the
45// naming scheme expected by FindPlugins, so the target directory of a
46// provider installer can be used as one of several plugin discovery sources.
47type ProviderInstaller struct {
48 Dir string
49
50 PluginProtocolVersion uint
51
52 // OS and Arch specify the OS and architecture that should be used when
53 // installing plugins. These use the same labels as the runtime.GOOS and
54 // runtime.GOARCH variables respectively, and indeed the values of these
55 // are used as defaults if either of these is the empty string.
56 OS string
57 Arch string
58
59 // Skip checksum and signature verification
60 SkipVerify bool
61}
62
63// Get is part of an implementation of type Installer, and attempts to download
64// and install a Terraform provider matching the given constraints.
65//
66// This method may return one of a number of sentinel errors from this
67// package to indicate issues that are likely to be resolvable via user action:
68//
69// ErrorNoSuchProvider: no provider with the given name exists in the repository.
70// ErrorNoSuitableVersion: the provider exists but no available version matches constraints.
71// ErrorNoVersionCompatible: a plugin was found within the constraints but it is
72// incompatible with the current Terraform version.
73//
74// These errors should be recognized and handled as special cases by the caller
75// to present a suitable user-oriented error message.
76//
77// All other errors indicate an internal problem that is likely _not_ solvable
78// through user action, or at least not within Terraform's scope. Error messages
79// are produced under the assumption that if presented to the user they will
80// be presented alongside context about what is being installed, and thus the
81// error messages do not redundantly include such information.
82func (i *ProviderInstaller) Get(provider string, req Constraints) (PluginMeta, error) {
83 versions, err := i.listProviderVersions(provider)
84 // TODO: return multiple errors
85 if err != nil {
86 return PluginMeta{}, err
87 }
88
89 if len(versions) == 0 {
90 return PluginMeta{}, ErrorNoSuitableVersion
91 }
92
93 versions = allowedVersions(versions, req)
94 if len(versions) == 0 {
95 return PluginMeta{}, ErrorNoSuitableVersion
96 }
97
98 // sort them newest to oldest
99 Versions(versions).Sort()
100
101 // take the first matching plugin we find
102 for _, v := range versions {
103 url := i.providerURL(provider, v.String())
104
105 if !i.SkipVerify {
106 sha256, err := i.getProviderChecksum(provider, v.String())
107 if err != nil {
108 return PluginMeta{}, err
109 }
110
111 // add the checksum parameter for go-getter to verify the download for us.
112 if sha256 != "" {
113 url = url + "?checksum=sha256:" + sha256
114 }
115 }
116
117 log.Printf("[DEBUG] fetching provider info for %s version %s", provider, v)
118 if checkPlugin(url, i.PluginProtocolVersion) {
119 log.Printf("[DEBUG] getting provider %q version %q at %s", provider, v, url)
120 err := getter.Get(i.Dir, url)
121 if err != nil {
122 return PluginMeta{}, err
123 }
124
125 // Find what we just installed
126 // (This is weird, because go-getter doesn't directly return
127 // information about what was extracted, and we just extracted
128 // the archive directly into a shared dir here.)
129 log.Printf("[DEBUG] looking for the %s %s plugin we just installed", provider, v)
130 metas := FindPlugins("provider", []string{i.Dir})
131 log.Printf("[DEBUG] all plugins found %#v", metas)
132 metas, _ = metas.ValidateVersions()
133 metas = metas.WithName(provider).WithVersion(v)
134 log.Printf("[DEBUG] filtered plugins %#v", metas)
135 if metas.Count() == 0 {
136 // This should never happen. Suggests that the release archive
137 // contains an executable file whose name doesn't match the
138 // expected convention.
139 return PluginMeta{}, fmt.Errorf(
140 "failed to find installed plugin version %s; this is a bug in Terraform and should be reported",
141 v,
142 )
143 }
144
145 if metas.Count() > 1 {
146 // This should also never happen, and suggests that a
147 // particular version was re-released with a different
148 // executable filename. We consider releases as immutable, so
149 // this is an error.
150 return PluginMeta{}, fmt.Errorf(
151 "multiple plugins installed for version %s; this is a bug in Terraform and should be reported",
152 v,
153 )
154 }
155
156 // By now we know we have exactly one meta, and so "Newest" will
157 // return that one.
158 return metas.Newest(), nil
159 }
160
161 log.Printf("[INFO] incompatible ProtocolVersion for %s version %s", provider, v)
162 }
163
164 return PluginMeta{}, ErrorNoVersionCompatible
165}
166
167func (i *ProviderInstaller) PurgeUnused(used map[string]PluginMeta) (PluginMetaSet, error) {
168 purge := make(PluginMetaSet)
169
170 present := FindPlugins("provider", []string{i.Dir})
171 for meta := range present {
172 chosen, ok := used[meta.Name]
173 if !ok {
174 purge.Add(meta)
175 }
176 if chosen.Path != meta.Path {
177 purge.Add(meta)
178 }
179 }
180
181 removed := make(PluginMetaSet)
182 var errs error
183 for meta := range purge {
184 path := meta.Path
185 err := os.Remove(path)
186 if err != nil {
187 errs = multierror.Append(errs, fmt.Errorf(
188 "failed to remove unused provider plugin %s: %s",
189 path, err,
190 ))
191 } else {
192 removed.Add(meta)
193 }
194 }
195
196 return removed, errs
197}
198
199// Plugins are referred to by the short name, but all URLs and files will use
200// the full name prefixed with terraform-<plugin_type>-
201func (i *ProviderInstaller) providerName(name string) string {
202 return "terraform-provider-" + name
203}
204
205func (i *ProviderInstaller) providerFileName(name, version string) string {
206 os := i.OS
207 arch := i.Arch
208 if os == "" {
209 os = runtime.GOOS
210 }
211 if arch == "" {
212 arch = runtime.GOARCH
213 }
214 return fmt.Sprintf("%s_%s_%s_%s.zip", i.providerName(name), version, os, arch)
215}
216
217// providerVersionsURL returns the path to the released versions directory for the provider:
218// https://releases.hashicorp.com/terraform-provider-name/
219func (i *ProviderInstaller) providerVersionsURL(name string) string {
220 return releaseHost + "/" + i.providerName(name) + "/"
221}
222
223// providerURL returns the full path to the provider file, using the current OS
224// and ARCH:
225// .../terraform-provider-name_<x.y.z>/terraform-provider-name_<x.y.z>_<os>_<arch>.<ext>
226func (i *ProviderInstaller) providerURL(name, version string) string {
227 return fmt.Sprintf("%s%s/%s", i.providerVersionsURL(name), version, i.providerFileName(name, version))
228}
229
230func (i *ProviderInstaller) providerChecksumURL(name, version string) string {
231 fileName := fmt.Sprintf("%s_%s_SHA256SUMS", i.providerName(name), version)
232 u := fmt.Sprintf("%s%s/%s", i.providerVersionsURL(name), version, fileName)
233 return u
234}
235
236func (i *ProviderInstaller) getProviderChecksum(name, version string) (string, error) {
237 checksums, err := getPluginSHA256SUMs(i.providerChecksumURL(name, version))
238 if err != nil {
239 return "", err
240 }
241
242 return checksumForFile(checksums, i.providerFileName(name, version)), nil
243}
244
245// Return the plugin version by making a HEAD request to the provided url.
246// If the header is not present, we assume the latest version will be
247// compatible, and leave the check for discovery or execution.
248func checkPlugin(url string, pluginProtocolVersion uint) bool {
249 resp, err := httpClient.Head(url)
250 if err != nil {
251 log.Printf("[ERROR] error fetching plugin headers: %s", err)
252 return false
253 }
254
255 if resp.StatusCode != http.StatusOK {
256 log.Println("[ERROR] non-200 status fetching plugin headers:", resp.Status)
257 return false
258 }
259
260 proto := resp.Header.Get(protocolVersionHeader)
261 if proto == "" {
262 // The header isn't present, but we don't make this error fatal since
263 // the latest version will probably work.
264 log.Printf("[WARNING] missing %s from: %s", protocolVersionHeader, url)
265 return true
266 }
267
268 protoVersion, err := strconv.Atoi(proto)
269 if err != nil {
270 log.Printf("[ERROR] invalid ProtocolVersion: %s", proto)
271 return false
272 }
273
274 return protoVersion == int(pluginProtocolVersion)
275}
276
277// list the version available for the named plugin
278func (i *ProviderInstaller) listProviderVersions(name string) ([]Version, error) {
279 versions, err := listPluginVersions(i.providerVersionsURL(name))
280 if err != nil {
281 // listPluginVersions returns a verbose error message indicating
282 // what was being accessed and what failed
283 return nil, err
284 }
285 return versions, nil
286}
287
288var errVersionNotFound = errors.New("version not found")
289
290// take the list of available versions for a plugin, and filter out those that
291// don't fit the constraints.
292func allowedVersions(available []Version, required Constraints) []Version {
293 var allowed []Version
294
295 for _, v := range available {
296 if required.Allows(v) {
297 allowed = append(allowed, v)
298 }
299 }
300
301 return allowed
302}
303
304// return a list of the plugin versions at the given URL
305func listPluginVersions(url string) ([]Version, error) {
306 resp, err := httpClient.Get(url)
307 if err != nil {
308 // http library produces a verbose error message that includes the
309 // URL being accessed, etc.
310 return nil, err
311 }
312 defer resp.Body.Close()
313
314 if resp.StatusCode != http.StatusOK {
315 body, _ := ioutil.ReadAll(resp.Body)
316 log.Printf("[ERROR] failed to fetch plugin versions from %s\n%s\n%s", url, resp.Status, body)
317
318 switch resp.StatusCode {
319 case http.StatusNotFound, http.StatusForbidden:
320 // These are treated as indicative of the given name not being
321 // a valid provider name at all.
322 return nil, ErrorNoSuchProvider
323
324 default:
325 // All other errors are assumed to be operational problems.
326 return nil, fmt.Errorf("error accessing %s: %s", url, resp.Status)
327 }
328
329 }
330
331 body, err := html.Parse(resp.Body)
332 if err != nil {
333 log.Fatal(err)
334 }
335
336 names := []string{}
337
338 // all we need to do is list links on the directory listing page that look like plugins
339 var f func(*html.Node)
340 f = func(n *html.Node) {
341 if n.Type == html.ElementNode && n.Data == "a" {
342 c := n.FirstChild
343 if c != nil && c.Type == html.TextNode && strings.HasPrefix(c.Data, "terraform-") {
344 names = append(names, c.Data)
345 return
346 }
347 }
348 for c := n.FirstChild; c != nil; c = c.NextSibling {
349 f(c)
350 }
351 }
352 f(body)
353
354 return versionsFromNames(names), nil
355}
356
357// parse the list of directory names into a sorted list of available versions
358func versionsFromNames(names []string) []Version {
359 var versions []Version
360 for _, name := range names {
361 parts := strings.SplitN(name, "_", 2)
362 if len(parts) == 2 && parts[1] != "" {
363 v, err := VersionStr(parts[1]).Parse()
364 if err != nil {
365 // filter invalid versions scraped from the page
366 log.Printf("[WARN] invalid version found for %q: %s", name, err)
367 continue
368 }
369
370 versions = append(versions, v)
371 }
372 }
373
374 return versions
375}
376
377func checksumForFile(sums []byte, name string) string {
378 for _, line := range strings.Split(string(sums), "\n") {
379 parts := strings.Fields(line)
380 if len(parts) > 1 && parts[1] == name {
381 return parts[0]
382 }
383 }
384 return ""
385}
386
387// fetch the SHA256SUMS file provided, and verify its signature.
388func getPluginSHA256SUMs(sumsURL string) ([]byte, error) {
389 sigURL := sumsURL + ".sig"
390
391 sums, err := getFile(sumsURL)
392 if err != nil {
393 return nil, fmt.Errorf("error fetching checksums: %s", err)
394 }
395
396 sig, err := getFile(sigURL)
397 if err != nil {
398 return nil, fmt.Errorf("error fetching checksums signature: %s", err)
399 }
400
401 if err := verifySig(sums, sig); err != nil {
402 return nil, err
403 }
404
405 return sums, nil
406}
407
408func getFile(url string) ([]byte, error) {
409 resp, err := httpClient.Get(url)
410 if err != nil {
411 return nil, err
412 }
413 defer resp.Body.Close()
414
415 if resp.StatusCode != http.StatusOK {
416 return nil, fmt.Errorf("%s", resp.Status)
417 }
418
419 data, err := ioutil.ReadAll(resp.Body)
420 if err != nil {
421 return data, err
422 }
423 return data, nil
424}
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/meta.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/meta.go
new file mode 100644
index 0000000..bdcebcb
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/meta.go
@@ -0,0 +1,41 @@
1package discovery
2
3import (
4 "crypto/sha256"
5 "io"
6 "os"
7)
8
9// PluginMeta is metadata about a plugin, useful for launching the plugin
10// and for understanding which plugins are available.
11type PluginMeta struct {
12 // Name is the name of the plugin, e.g. as inferred from the plugin
13 // binary's filename, or by explicit configuration.
14 Name string
15
16 // Version is the semver version of the plugin, expressed as a string
17 // that might not be semver-valid.
18 Version VersionStr
19
20 // Path is the absolute path of the executable that can be launched
21 // to provide the RPC server for this plugin.
22 Path string
23}
24
25// SHA256 returns a SHA256 hash of the content of the referenced executable
26// file, or an error if the file's contents cannot be read.
27func (m PluginMeta) SHA256() ([]byte, error) {
28 f, err := os.Open(m.Path)
29 if err != nil {
30 return nil, err
31 }
32 defer f.Close()
33
34 h := sha256.New()
35 _, err = io.Copy(h, f)
36 if err != nil {
37 return nil, err
38 }
39
40 return h.Sum(nil), nil
41}
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go
new file mode 100644
index 0000000..181ea1f
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/meta_set.go
@@ -0,0 +1,195 @@
1package discovery
2
3// A PluginMetaSet is a set of PluginMeta objects meeting a certain criteria.
4//
5// Methods on this type allow filtering of the set to produce subsets that
6// meet more restrictive criteria.
7type PluginMetaSet map[PluginMeta]struct{}
8
9// Add inserts the given PluginMeta into the receiving set. This is a no-op
10// if the given meta is already present.
11func (s PluginMetaSet) Add(p PluginMeta) {
12 s[p] = struct{}{}
13}
14
15// Remove removes the given PluginMeta from the receiving set. This is a no-op
16// if the given meta is not already present.
17func (s PluginMetaSet) Remove(p PluginMeta) {
18 delete(s, p)
19}
20
21// Has returns true if the given meta is in the receiving set, or false
22// otherwise.
23func (s PluginMetaSet) Has(p PluginMeta) bool {
24 _, ok := s[p]
25 return ok
26}
27
28// Count returns the number of metas in the set
29func (s PluginMetaSet) Count() int {
30 return len(s)
31}
32
33// ValidateVersions returns two new PluginMetaSets, separating those with
34// versions that have syntax-valid semver versions from those that don't.
35//
36// Eliminating invalid versions from consideration (and possibly warning about
37// them) is usually the first step of working with a meta set after discovery
38// has completed.
39func (s PluginMetaSet) ValidateVersions() (valid, invalid PluginMetaSet) {
40 valid = make(PluginMetaSet)
41 invalid = make(PluginMetaSet)
42 for p := range s {
43 if _, err := p.Version.Parse(); err == nil {
44 valid.Add(p)
45 } else {
46 invalid.Add(p)
47 }
48 }
49 return
50}
51
52// WithName returns the subset of metas that have the given name.
53func (s PluginMetaSet) WithName(name string) PluginMetaSet {
54 ns := make(PluginMetaSet)
55 for p := range s {
56 if p.Name == name {
57 ns.Add(p)
58 }
59 }
60 return ns
61}
62
63// WithVersion returns the subset of metas that have the given version.
64//
65// This should be used only with the "valid" result from ValidateVersions;
66// it will ignore any plugin metas that have a invalid version strings.
67func (s PluginMetaSet) WithVersion(version Version) PluginMetaSet {
68 ns := make(PluginMetaSet)
69 for p := range s {
70 gotVersion, err := p.Version.Parse()
71 if err != nil {
72 continue
73 }
74 if gotVersion.Equal(version) {
75 ns.Add(p)
76 }
77 }
78 return ns
79}
80
81// ByName groups the metas in the set by their Names, returning a map.
82func (s PluginMetaSet) ByName() map[string]PluginMetaSet {
83 ret := make(map[string]PluginMetaSet)
84 for p := range s {
85 if _, ok := ret[p.Name]; !ok {
86 ret[p.Name] = make(PluginMetaSet)
87 }
88 ret[p.Name].Add(p)
89 }
90 return ret
91}
92
93// Newest returns the one item from the set that has the newest Version value.
94//
95// The result is meaningful only if the set is already filtered such that
96// all of the metas have the same Name.
97//
98// If there isn't at least one meta in the set then this function will panic.
99// Use Count() to ensure that there is at least one value before calling.
100//
101// If any of the metas have invalid version strings then this function will
102// panic. Use ValidateVersions() first to filter out metas with invalid
103// versions.
104//
105// If two metas have the same Version then one is arbitrarily chosen. This
106// situation should be avoided by pre-filtering the set.
107func (s PluginMetaSet) Newest() PluginMeta {
108 if len(s) == 0 {
109 panic("can't call NewestStable on empty PluginMetaSet")
110 }
111
112 var first = true
113 var winner PluginMeta
114 var winnerVersion Version
115 for p := range s {
116 version, err := p.Version.Parse()
117 if err != nil {
118 panic(err)
119 }
120
121 if first == true || version.NewerThan(winnerVersion) {
122 winner = p
123 winnerVersion = version
124 first = false
125 }
126 }
127
128 return winner
129}
130
131// ConstrainVersions takes a set of requirements and attempts to
132// return a map from name to a set of metas that have the matching
133// name and an appropriate version.
134//
135// If any of the given requirements match *no* plugins then its PluginMetaSet
136// in the returned map will be empty.
137//
138// All viable metas are returned, so the caller can apply any desired filtering
139// to reduce down to a single option. For example, calling Newest() to obtain
140// the highest available version.
141//
142// If any of the metas in the set have invalid version strings then this
143// function will panic. Use ValidateVersions() first to filter out metas with
144// invalid versions.
145func (s PluginMetaSet) ConstrainVersions(reqd PluginRequirements) map[string]PluginMetaSet {
146 ret := make(map[string]PluginMetaSet)
147 for p := range s {
148 name := p.Name
149 allowedVersions, ok := reqd[name]
150 if !ok {
151 continue
152 }
153 if _, ok := ret[p.Name]; !ok {
154 ret[p.Name] = make(PluginMetaSet)
155 }
156 version, err := p.Version.Parse()
157 if err != nil {
158 panic(err)
159 }
160 if allowedVersions.Allows(version) {
161 ret[p.Name].Add(p)
162 }
163 }
164 return ret
165}
166
167// OverridePaths returns a new set where any existing plugins with the given
168// names are removed and replaced with the single path given in the map.
169//
170// This is here only to continue to support the legacy way of overriding
171// plugin binaries in the .terraformrc file. It treats all given plugins
172// as pre-versioning (version 0.0.0). This mechanism will eventually be
173// phased out, with vendor directories being the intended replacement.
174func (s PluginMetaSet) OverridePaths(paths map[string]string) PluginMetaSet {
175 ret := make(PluginMetaSet)
176 for p := range s {
177 if _, ok := paths[p.Name]; ok {
178 // Skip plugins that we're overridding
179 continue
180 }
181
182 ret.Add(p)
183 }
184
185 // Now add the metadata for overriding plugins
186 for name, path := range paths {
187 ret.Add(PluginMeta{
188 Name: name,
189 Version: VersionZero,
190 Path: path,
191 })
192 }
193
194 return ret
195}
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/requirements.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/requirements.go
new file mode 100644
index 0000000..75430fd
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/requirements.go
@@ -0,0 +1,105 @@
1package discovery
2
3import (
4 "bytes"
5)
6
7// PluginRequirements describes a set of plugins (assumed to be of a consistent
8// kind) that are required to exist and have versions within the given
9// corresponding sets.
10type PluginRequirements map[string]*PluginConstraints
11
12// PluginConstraints represents an element of PluginRequirements describing
13// the constraints for a single plugin.
14type PluginConstraints struct {
15 // Specifies that the plugin's version must be within the given
16 // constraints.
17 Versions Constraints
18
19 // If non-nil, the hash of the on-disk plugin executable must exactly
20 // match the SHA256 hash given here.
21 SHA256 []byte
22}
23
24// Allows returns true if the given version is within the receiver's version
25// constraints.
26func (s *PluginConstraints) Allows(v Version) bool {
27 return s.Versions.Allows(v)
28}
29
30// AcceptsSHA256 returns true if the given executable SHA256 hash is acceptable,
31// either because it matches the constraint or because there is no such
32// constraint.
33func (s *PluginConstraints) AcceptsSHA256(digest []byte) bool {
34 if s.SHA256 == nil {
35 return true
36 }
37 return bytes.Equal(s.SHA256, digest)
38}
39
40// Merge takes the contents of the receiver and the other given requirements
41// object and merges them together into a single requirements structure
42// that satisfies both sets of requirements.
43//
44// Note that it doesn't make sense to merge two PluginRequirements with
45// differing required plugin SHA256 hashes, since the result will never
46// match any plugin.
47func (r PluginRequirements) Merge(other PluginRequirements) PluginRequirements {
48 ret := make(PluginRequirements)
49 for n, c := range r {
50 ret[n] = &PluginConstraints{
51 Versions: Constraints{}.Append(c.Versions),
52 SHA256: c.SHA256,
53 }
54 }
55 for n, c := range other {
56 if existing, exists := ret[n]; exists {
57 ret[n].Versions = ret[n].Versions.Append(c.Versions)
58
59 if existing.SHA256 != nil {
60 if c.SHA256 != nil && !bytes.Equal(c.SHA256, existing.SHA256) {
61 // If we've been asked to merge two constraints with
62 // different SHA256 hashes then we'll produce a dummy value
63 // that can never match anything. This is a silly edge case
64 // that no reasonable caller should hit.
65 ret[n].SHA256 = []byte(invalidProviderHash)
66 }
67 } else {
68 ret[n].SHA256 = c.SHA256 // might still be nil
69 }
70 } else {
71 ret[n] = &PluginConstraints{
72 Versions: Constraints{}.Append(c.Versions),
73 SHA256: c.SHA256,
74 }
75 }
76 }
77 return ret
78}
79
80// LockExecutables applies additional constraints to the receiver that
81// require plugin executables with specific SHA256 digests. This modifies
82// the receiver in-place, since it's intended to be applied after
83// version constraints have been resolved.
84//
85// The given map must include a key for every plugin that is already
86// required. If not, any missing keys will cause the corresponding plugin
87// to never match, though the direct caller doesn't necessarily need to
88// guarantee this as long as the downstream code _applying_ these constraints
89// is able to deal with the non-match in some way.
90func (r PluginRequirements) LockExecutables(sha256s map[string][]byte) {
91 for name, cons := range r {
92 digest := sha256s[name]
93
94 if digest == nil {
95 // Prevent any match, which will then presumably cause the
96 // downstream consumer of this requirements to report an error.
97 cons.SHA256 = []byte(invalidProviderHash)
98 continue
99 }
100
101 cons.SHA256 = digest
102 }
103}
104
105const invalidProviderHash = "<invalid>"
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/signature.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/signature.go
new file mode 100644
index 0000000..b6686a5
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/signature.go
@@ -0,0 +1,53 @@
1package discovery
2
3import (
4 "bytes"
5 "log"
6 "strings"
7
8 "golang.org/x/crypto/openpgp"
9)
10
11// Verify the data using the provided openpgp detached signature and the
12// embedded hashicorp public key.
13func verifySig(data, sig []byte) error {
14 el, err := openpgp.ReadArmoredKeyRing(strings.NewReader(hashiPublicKey))
15 if err != nil {
16 log.Fatal(err)
17 }
18
19 _, err = openpgp.CheckDetachedSignature(el, bytes.NewReader(data), bytes.NewReader(sig))
20 return err
21}
22
23// this is the public key that signs the checksums file for releases.
24const hashiPublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
25Version: GnuPG v1
26
27mQENBFMORM0BCADBRyKO1MhCirazOSVwcfTr1xUxjPvfxD3hjUwHtjsOy/bT6p9f
28W2mRPfwnq2JB5As+paL3UGDsSRDnK9KAxQb0NNF4+eVhr/EJ18s3wwXXDMjpIifq
29fIm2WyH3G+aRLTLPIpscUNKDyxFOUbsmgXAmJ46Re1fn8uKxKRHbfa39aeuEYWFA
303drdL1WoUngvED7f+RnKBK2G6ZEpO+LDovQk19xGjiMTtPJrjMjZJ3QXqPvx5wca
31KSZLr4lMTuoTI/ZXyZy5bD4tShiZz6KcyX27cD70q2iRcEZ0poLKHyEIDAi3TM5k
32SwbbWBFd5RNPOR0qzrb/0p9ksKK48IIfH2FvABEBAAG0K0hhc2hpQ29ycCBTZWN1
33cml0eSA8c2VjdXJpdHlAaGFzaGljb3JwLmNvbT6JATgEEwECACIFAlMORM0CGwMG
34CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEFGFLYc0j/xMyWIIAIPhcVqiQ59n
35Jc07gjUX0SWBJAxEG1lKxfzS4Xp+57h2xxTpdotGQ1fZwsihaIqow337YHQI3q0i
36SqV534Ms+j/tU7X8sq11xFJIeEVG8PASRCwmryUwghFKPlHETQ8jJ+Y8+1asRydi
37psP3B/5Mjhqv/uOK+Vy3zAyIpyDOMtIpOVfjSpCplVRdtSTFWBu9Em7j5I2HMn1w
38sJZnJgXKpybpibGiiTtmnFLOwibmprSu04rsnP4ncdC2XRD4wIjoyA+4PKgX3sCO
39klEzKryWYBmLkJOMDdo52LttP3279s7XrkLEE7ia0fXa2c12EQ0f0DQ1tGUvyVEW
40WmJVccm5bq25AQ0EUw5EzQEIANaPUY04/g7AmYkOMjaCZ6iTp9hB5Rsj/4ee/ln9
41wArzRO9+3eejLWh53FoN1rO+su7tiXJA5YAzVy6tuolrqjM8DBztPxdLBbEi4V+j
422tK0dATdBQBHEh3OJApO2UBtcjaZBT31zrG9K55D+CrcgIVEHAKY8Cb4kLBkb5wM
43skn+DrASKU0BNIV1qRsxfiUdQHZfSqtp004nrql1lbFMLFEuiY8FZrkkQ9qduixo
44mTT6f34/oiY+Jam3zCK7RDN/OjuWheIPGj/Qbx9JuNiwgX6yRj7OE1tjUx6d8g9y
450H1fmLJbb3WZZbuuGFnK6qrE3bGeY8+AWaJAZ37wpWh1p0cAEQEAAYkBHwQYAQIA
46CQUCUw5EzQIbDAAKCRBRhS2HNI/8TJntCAClU7TOO/X053eKF1jqNW4A1qpxctVc
47z8eTcY8Om5O4f6a/rfxfNFKn9Qyja/OG1xWNobETy7MiMXYjaa8uUx5iFy6kMVaP
480BXJ59NLZjMARGw6lVTYDTIvzqqqwLxgliSDfSnqUhubGwvykANPO+93BBx89MRG
49unNoYGXtPlhNFrAsB1VR8+EyKLv2HQtGCPSFBhrjuzH3gxGibNDDdFQLxxuJWepJ
50EK1UbTS4ms0NgZ2Uknqn1WRU1Ki7rE4sTy68iZtWpKQXZEJa0IGnuI2sSINGcXCJ
51oEIgXTMyCILo34Fa/C6VCm2WBgz9zZO8/rHIiQm1J5zqz0DrDwKBUM9C
52=LYpS
53-----END PGP PUBLIC KEY BLOCK-----`
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/version.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/version.go
new file mode 100644
index 0000000..8fad58d
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/version.go
@@ -0,0 +1,72 @@
1package discovery
2
3import (
4 "fmt"
5 "sort"
6
7 version "github.com/hashicorp/go-version"
8)
9
10const VersionZero = "0.0.0"
11
12// A VersionStr is a string containing a possibly-invalid representation
13// of a semver version number. Call Parse on it to obtain a real Version
14// object, or discover that it is invalid.
15type VersionStr string
16
17// Parse transforms a VersionStr into a Version if it is
18// syntactically valid. If it isn't then an error is returned instead.
19func (s VersionStr) Parse() (Version, error) {
20 raw, err := version.NewVersion(string(s))
21 if err != nil {
22 return Version{}, err
23 }
24 return Version{raw}, nil
25}
26
27// MustParse transforms a VersionStr into a Version if it is
28// syntactically valid. If it isn't then it panics.
29func (s VersionStr) MustParse() Version {
30 ret, err := s.Parse()
31 if err != nil {
32 panic(err)
33 }
34 return ret
35}
36
37// Version represents a version number that has been parsed from
38// a semver string and known to be valid.
39type Version struct {
40 // We wrap this here just because it avoids a proliferation of
41 // direct go-version imports all over the place, and keeps the
42 // version-processing details within this package.
43 raw *version.Version
44}
45
46func (v Version) String() string {
47 return v.raw.String()
48}
49
50func (v Version) NewerThan(other Version) bool {
51 return v.raw.GreaterThan(other.raw)
52}
53
54func (v Version) Equal(other Version) bool {
55 return v.raw.Equal(other.raw)
56}
57
58// MinorUpgradeConstraintStr returns a ConstraintStr that would permit
59// minor upgrades relative to the receiving version.
60func (v Version) MinorUpgradeConstraintStr() ConstraintStr {
61 segments := v.raw.Segments()
62 return ConstraintStr(fmt.Sprintf("~> %d.%d", segments[0], segments[1]))
63}
64
65type Versions []Version
66
67// Sort sorts version from newest to oldest.
68func (v Versions) Sort() {
69 sort.Slice(v, func(i, j int) bool {
70 return v[i].NewerThan(v[j])
71 })
72}
diff --git a/vendor/github.com/hashicorp/terraform/plugin/discovery/version_set.go b/vendor/github.com/hashicorp/terraform/plugin/discovery/version_set.go
new file mode 100644
index 0000000..0aefd75
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/plugin/discovery/version_set.go
@@ -0,0 +1,84 @@
1package discovery
2
3import (
4 "sort"
5
6 version "github.com/hashicorp/go-version"
7)
8
9// A ConstraintStr is a string containing a possibly-invalid representation
10// of a version constraint provided in configuration. Call Parse on it to
11// obtain a real Constraint object, or discover that it is invalid.
12type ConstraintStr string
13
14// Parse transforms a ConstraintStr into a Constraints if it is
15// syntactically valid. If it isn't then an error is returned instead.
16func (s ConstraintStr) Parse() (Constraints, error) {
17 raw, err := version.NewConstraint(string(s))
18 if err != nil {
19 return Constraints{}, err
20 }
21 return Constraints{raw}, nil
22}
23
24// MustParse is like Parse but it panics if the constraint string is invalid.
25func (s ConstraintStr) MustParse() Constraints {
26 ret, err := s.Parse()
27 if err != nil {
28 panic(err)
29 }
30 return ret
31}
32
33// Constraints represents a set of versions which any given Version is either
34// a member of or not.
35type Constraints struct {
36 raw version.Constraints
37}
38
39// AllVersions is a Constraints containing all versions
40var AllVersions Constraints
41
42func init() {
43 AllVersions = Constraints{
44 raw: make(version.Constraints, 0),
45 }
46}
47
48// Allows returns true if the given version permitted by the receiving
49// constraints set.
50func (s Constraints) Allows(v Version) bool {
51 return s.raw.Check(v.raw)
52}
53
54// Append combines the receiving set with the given other set to produce
55// a set that is the intersection of both sets, which is to say that resulting
56// constraints contain only the versions that are members of both.
57func (s Constraints) Append(other Constraints) Constraints {
58 raw := make(version.Constraints, 0, len(s.raw)+len(other.raw))
59
60 // Since "raw" is a list of constraints that remove versions from the set,
61 // "Intersection" is implemented by concatenating together those lists,
62 // thus leaving behind only the versions not removed by either list.
63 raw = append(raw, s.raw...)
64 raw = append(raw, other.raw...)
65
66 // while the set is unordered, we sort these lexically for consistent output
67 sort.Slice(raw, func(i, j int) bool {
68 return raw[i].String() < raw[j].String()
69 })
70
71 return Constraints{raw}
72}
73
74// String returns a string representation of the set members as a set
75// of range constraints.
76func (s Constraints) String() string {
77 return s.raw.String()
78}
79
80// Unconstrained returns true if and only if the receiver is an empty
81// constraint set.
82func (s Constraints) Unconstrained() bool {
83 return len(s.raw) == 0
84}
diff --git a/vendor/github.com/hashicorp/terraform/terraform/context.go b/vendor/github.com/hashicorp/terraform/terraform/context.go
index 306128e..a814a85 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/context.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/context.go
@@ -57,12 +57,17 @@ type ContextOpts struct {
57 Parallelism int 57 Parallelism int
58 State *State 58 State *State
59 StateFutureAllowed bool 59 StateFutureAllowed bool
60 Providers map[string]ResourceProviderFactory 60 ProviderResolver ResourceProviderResolver
61 Provisioners map[string]ResourceProvisionerFactory 61 Provisioners map[string]ResourceProvisionerFactory
62 Shadow bool 62 Shadow bool
63 Targets []string 63 Targets []string
64 Variables map[string]interface{} 64 Variables map[string]interface{}
65 65
66 // If non-nil, will apply as additional constraints on the provider
67 // plugins that will be requested from the provider resolver.
68 ProviderSHA256s map[string][]byte
69 SkipProviderVerify bool
70
66 UIInput UIInput 71 UIInput UIInput
67} 72}
68 73
@@ -102,6 +107,7 @@ type Context struct {
102 l sync.Mutex // Lock acquired during any task 107 l sync.Mutex // Lock acquired during any task
103 parallelSem Semaphore 108 parallelSem Semaphore
104 providerInputConfig map[string]map[string]interface{} 109 providerInputConfig map[string]map[string]interface{}
110 providerSHA256s map[string][]byte
105 runLock sync.Mutex 111 runLock sync.Mutex
106 runCond *sync.Cond 112 runCond *sync.Cond
107 runContext context.Context 113 runContext context.Context
@@ -166,7 +172,6 @@ func NewContext(opts *ContextOpts) (*Context, error) {
166 // set by environment variables if necessary. This includes 172 // set by environment variables if necessary. This includes
167 // values taken from -var-file in addition. 173 // values taken from -var-file in addition.
168 variables := make(map[string]interface{}) 174 variables := make(map[string]interface{})
169
170 if opts.Module != nil { 175 if opts.Module != nil {
171 var err error 176 var err error
172 variables, err = Variables(opts.Module, opts.Variables) 177 variables, err = Variables(opts.Module, opts.Variables)
@@ -175,6 +180,23 @@ func NewContext(opts *ContextOpts) (*Context, error) {
175 } 180 }
176 } 181 }
177 182
183 // Bind available provider plugins to the constraints in config
184 var providers map[string]ResourceProviderFactory
185 if opts.ProviderResolver != nil {
186 var err error
187 deps := ModuleTreeDependencies(opts.Module, state)
188 reqd := deps.AllPluginRequirements()
189 if opts.ProviderSHA256s != nil && !opts.SkipProviderVerify {
190 reqd.LockExecutables(opts.ProviderSHA256s)
191 }
192 providers, err = resourceProviderFactories(opts.ProviderResolver, reqd)
193 if err != nil {
194 return nil, err
195 }
196 } else {
197 providers = make(map[string]ResourceProviderFactory)
198 }
199
178 diff := opts.Diff 200 diff := opts.Diff
179 if diff == nil { 201 if diff == nil {
180 diff = &Diff{} 202 diff = &Diff{}
@@ -182,7 +204,7 @@ func NewContext(opts *ContextOpts) (*Context, error) {
182 204
183 return &Context{ 205 return &Context{
184 components: &basicComponentFactory{ 206 components: &basicComponentFactory{
185 providers: opts.Providers, 207 providers: providers,
186 provisioners: opts.Provisioners, 208 provisioners: opts.Provisioners,
187 }, 209 },
188 destroy: opts.Destroy, 210 destroy: opts.Destroy,
@@ -198,6 +220,7 @@ func NewContext(opts *ContextOpts) (*Context, error) {
198 220
199 parallelSem: NewSemaphore(par), 221 parallelSem: NewSemaphore(par),
200 providerInputConfig: make(map[string]map[string]interface{}), 222 providerInputConfig: make(map[string]map[string]interface{}),
223 providerSHA256s: opts.ProviderSHA256s,
201 sh: sh, 224 sh: sh,
202 }, nil 225 }, nil
203} 226}
@@ -509,6 +532,9 @@ func (c *Context) Plan() (*Plan, error) {
509 Vars: c.variables, 532 Vars: c.variables,
510 State: c.state, 533 State: c.state,
511 Targets: c.targets, 534 Targets: c.targets,
535
536 TerraformVersion: VersionString(),
537 ProviderSHA256s: c.providerSHA256s,
512 } 538 }
513 539
514 var operation walkOperation 540 var operation walkOperation
diff --git a/vendor/github.com/hashicorp/terraform/terraform/diff.go b/vendor/github.com/hashicorp/terraform/terraform/diff.go
index a9fae6c..fd1687e 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/diff.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/diff.go
@@ -28,7 +28,7 @@ const (
28// multiVal matches the index key to a flatmapped set, list or map 28// multiVal matches the index key to a flatmapped set, list or map
29var multiVal = regexp.MustCompile(`\.(#|%)$`) 29var multiVal = regexp.MustCompile(`\.(#|%)$`)
30 30
31// Diff trackes the changes that are necessary to apply a configuration 31// Diff tracks the changes that are necessary to apply a configuration
32// to an existing infrastructure. 32// to an existing infrastructure.
33type Diff struct { 33type Diff struct {
34 // Modules contains all the modules that have a diff 34 // Modules contains all the modules that have a diff
@@ -370,7 +370,7 @@ type InstanceDiff struct {
370 370
371 // Meta is a simple K/V map that is stored in a diff and persisted to 371 // Meta is a simple K/V map that is stored in a diff and persisted to
372 // plans but otherwise is completely ignored by Terraform core. It is 372 // plans but otherwise is completely ignored by Terraform core. It is
373 // mean to be used for additional data a resource may want to pass through. 373 // meant to be used for additional data a resource may want to pass through.
374 // The value here must only contain Go primitives and collections. 374 // The value here must only contain Go primitives and collections.
375 Meta map[string]interface{} 375 Meta map[string]interface{}
376} 376}
@@ -551,7 +551,7 @@ func (d *InstanceDiff) SetDestroyDeposed(b bool) {
551} 551}
552 552
553// These methods are properly locked, for use outside other InstanceDiff 553// These methods are properly locked, for use outside other InstanceDiff
554// methods but everywhere else within in the terraform package. 554// methods but everywhere else within the terraform package.
555// TODO refactor the locking scheme 555// TODO refactor the locking scheme
556func (d *InstanceDiff) SetTainted(b bool) { 556func (d *InstanceDiff) SetTainted(b bool) {
557 d.mu.Lock() 557 d.mu.Lock()
diff --git a/vendor/github.com/hashicorp/terraform/terraform/eval_diff.go b/vendor/github.com/hashicorp/terraform/terraform/eval_diff.go
index 6f09526..c35f908 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/eval_diff.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/eval_diff.go
@@ -81,6 +81,12 @@ type EvalDiff struct {
81 // Resource is needed to fetch the ignore_changes list so we can 81 // Resource is needed to fetch the ignore_changes list so we can
82 // filter user-requested ignored attributes from the diff. 82 // filter user-requested ignored attributes from the diff.
83 Resource *config.Resource 83 Resource *config.Resource
84
85 // Stub is used to flag the generated InstanceDiff as a stub. This is used to
86 // ensure that the node exists to perform interpolations and generate
87 // computed paths off of, but not as an actual diff where resouces should be
88 // counted, and not as a diff that should be acted on.
89 Stub bool
84} 90}
85 91
86// TODO: test 92// TODO: test
@@ -90,11 +96,13 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
90 provider := *n.Provider 96 provider := *n.Provider
91 97
92 // Call pre-diff hook 98 // Call pre-diff hook
93 err := ctx.Hook(func(h Hook) (HookAction, error) { 99 if !n.Stub {
94 return h.PreDiff(n.Info, state) 100 err := ctx.Hook(func(h Hook) (HookAction, error) {
95 }) 101 return h.PreDiff(n.Info, state)
96 if err != nil { 102 })
97 return nil, err 103 if err != nil {
104 return nil, err
105 }
98 } 106 }
99 107
100 // The state for the diff must never be nil 108 // The state for the diff must never be nil
@@ -158,15 +166,19 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
158 } 166 }
159 167
160 // Call post-refresh hook 168 // Call post-refresh hook
161 err = ctx.Hook(func(h Hook) (HookAction, error) { 169 if !n.Stub {
162 return h.PostDiff(n.Info, diff) 170 err = ctx.Hook(func(h Hook) (HookAction, error) {
163 }) 171 return h.PostDiff(n.Info, diff)
164 if err != nil { 172 })
165 return nil, err 173 if err != nil {
174 return nil, err
175 }
166 } 176 }
167 177
168 // Update our output 178 // Update our output if we care
169 *n.OutputDiff = diff 179 if n.OutputDiff != nil {
180 *n.OutputDiff = diff
181 }
170 182
171 // Update the state if we care 183 // Update the state if we care
172 if n.OutputState != nil { 184 if n.OutputState != nil {
diff --git a/vendor/github.com/hashicorp/terraform/terraform/graph_builder_plan.go b/vendor/github.com/hashicorp/terraform/terraform/graph_builder_plan.go
index a6a3a90..4b29bbb 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/graph_builder_plan.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/graph_builder_plan.go
@@ -117,7 +117,15 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer {
117 &CountBoundaryTransformer{}, 117 &CountBoundaryTransformer{},
118 118
119 // Target 119 // Target
120 &TargetsTransformer{Targets: b.Targets}, 120 &TargetsTransformer{
121 Targets: b.Targets,
122
123 // Resource nodes from config have not yet been expanded for
124 // "count", so we must apply targeting without indices. Exact
125 // targeting will be dealt with later when these resources
126 // DynamicExpand.
127 IgnoreIndices: true,
128 },
121 129
122 // Close opened plugin connections 130 // Close opened plugin connections
123 &CloseProviderTransformer{}, 131 &CloseProviderTransformer{},
diff --git a/vendor/github.com/hashicorp/terraform/terraform/graph_builder_refresh.go b/vendor/github.com/hashicorp/terraform/terraform/graph_builder_refresh.go
index 0634f96..3d3e968 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/graph_builder_refresh.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/graph_builder_refresh.go
@@ -144,7 +144,15 @@ func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
144 &ReferenceTransformer{}, 144 &ReferenceTransformer{},
145 145
146 // Target 146 // Target
147 &TargetsTransformer{Targets: b.Targets}, 147 &TargetsTransformer{
148 Targets: b.Targets,
149
150 // Resource nodes from config have not yet been expanded for
151 // "count", so we must apply targeting without indices. Exact
152 // targeting will be dealt with later when these resources
153 // DynamicExpand.
154 IgnoreIndices: true,
155 },
148 156
149 // Close opened plugin connections 157 // Close opened plugin connections
150 &CloseProviderTransformer{}, 158 &CloseProviderTransformer{},
diff --git a/vendor/github.com/hashicorp/terraform/terraform/interpolate.go b/vendor/github.com/hashicorp/terraform/terraform/interpolate.go
index 0def295..22ddce6 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/interpolate.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/interpolate.go
@@ -317,9 +317,13 @@ func (i *Interpolater) valueTerraformVar(
317 n string, 317 n string,
318 v *config.TerraformVariable, 318 v *config.TerraformVariable,
319 result map[string]ast.Variable) error { 319 result map[string]ast.Variable) error {
320 if v.Field != "env" { 320
321 // "env" is supported for backward compatibility, but it's deprecated and
322 // so we won't advertise it as being allowed in the error message. It will
323 // be removed in a future version of Terraform.
324 if v.Field != "workspace" && v.Field != "env" {
321 return fmt.Errorf( 325 return fmt.Errorf(
322 "%s: only supported key for 'terraform.X' interpolations is 'env'", n) 326 "%s: only supported key for 'terraform.X' interpolations is 'workspace'", n)
323 } 327 }
324 328
325 if i.Meta == nil { 329 if i.Meta == nil {
diff --git a/vendor/github.com/hashicorp/terraform/terraform/module_dependencies.go b/vendor/github.com/hashicorp/terraform/terraform/module_dependencies.go
new file mode 100644
index 0000000..b9f44a0
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/terraform/module_dependencies.go
@@ -0,0 +1,156 @@
1package terraform
2
3import (
4 "github.com/hashicorp/terraform/config"
5 "github.com/hashicorp/terraform/config/module"
6 "github.com/hashicorp/terraform/moduledeps"
7 "github.com/hashicorp/terraform/plugin/discovery"
8)
9
10// ModuleTreeDependencies returns the dependencies of the tree of modules
11// described by the given configuration tree and state.
12//
13// Both configuration and state are required because there can be resources
14// implied by instances in the state that no longer exist in config.
15//
16// This function will panic if any invalid version constraint strings are
17// present in the configuration. This is guaranteed not to happen for any
18// configuration that has passed a call to Config.Validate().
19func ModuleTreeDependencies(root *module.Tree, state *State) *moduledeps.Module {
20
21 // First we walk the configuration tree to build the overall structure
22 // and capture the explicit/implicit/inherited provider dependencies.
23 deps := moduleTreeConfigDependencies(root, nil)
24
25 // Next we walk over the resources in the state to catch any additional
26 // dependencies created by existing resources that are no longer in config.
27 // Most things we find in state will already be present in 'deps', but
28 // we're interested in the rare thing that isn't.
29 moduleTreeMergeStateDependencies(deps, state)
30
31 return deps
32}
33
34func moduleTreeConfigDependencies(root *module.Tree, inheritProviders map[string]*config.ProviderConfig) *moduledeps.Module {
35 if root == nil {
36 // If no config is provided, we'll make a synthetic root.
37 // This isn't necessarily correct if we're called with a nil that
38 // *isn't* at the root, but in practice that can never happen.
39 return &moduledeps.Module{
40 Name: "root",
41 }
42 }
43
44 ret := &moduledeps.Module{
45 Name: root.Name(),
46 }
47
48 cfg := root.Config()
49 providerConfigs := cfg.ProviderConfigsByFullName()
50
51 // Provider dependencies
52 {
53 providers := make(moduledeps.Providers, len(providerConfigs))
54
55 // Any providerConfigs elements are *explicit* provider dependencies,
56 // which is the only situation where the user might provide an actual
57 // version constraint. We'll take care of these first.
58 for fullName, pCfg := range providerConfigs {
59 inst := moduledeps.ProviderInstance(fullName)
60 versionSet := discovery.AllVersions
61 if pCfg.Version != "" {
62 versionSet = discovery.ConstraintStr(pCfg.Version).MustParse()
63 }
64 providers[inst] = moduledeps.ProviderDependency{
65 Constraints: versionSet,
66 Reason: moduledeps.ProviderDependencyExplicit,
67 }
68 }
69
70 // Each resource in the configuration creates an *implicit* provider
71 // dependency, though we'll only record it if there isn't already
72 // an explicit dependency on the same provider.
73 for _, rc := range cfg.Resources {
74 fullName := rc.ProviderFullName()
75 inst := moduledeps.ProviderInstance(fullName)
76 if _, exists := providers[inst]; exists {
77 // Explicit dependency already present
78 continue
79 }
80
81 reason := moduledeps.ProviderDependencyImplicit
82 if _, inherited := inheritProviders[fullName]; inherited {
83 reason = moduledeps.ProviderDependencyInherited
84 }
85
86 providers[inst] = moduledeps.ProviderDependency{
87 Constraints: discovery.AllVersions,
88 Reason: reason,
89 }
90 }
91
92 ret.Providers = providers
93 }
94
95 childInherit := make(map[string]*config.ProviderConfig)
96 for k, v := range inheritProviders {
97 childInherit[k] = v
98 }
99 for k, v := range providerConfigs {
100 childInherit[k] = v
101 }
102 for _, c := range root.Children() {
103 ret.Children = append(ret.Children, moduleTreeConfigDependencies(c, childInherit))
104 }
105
106 return ret
107}
108
109func moduleTreeMergeStateDependencies(root *moduledeps.Module, state *State) {
110 if state == nil {
111 return
112 }
113
114 findModule := func(path []string) *moduledeps.Module {
115 module := root
116 for _, name := range path[1:] { // skip initial "root"
117 var next *moduledeps.Module
118 for _, cm := range module.Children {
119 if cm.Name == name {
120 next = cm
121 break
122 }
123 }
124
125 if next == nil {
126 // If we didn't find a next node, we'll need to make one
127 next = &moduledeps.Module{
128 Name: name,
129 }
130 module.Children = append(module.Children, next)
131 }
132
133 module = next
134 }
135 return module
136 }
137
138 for _, ms := range state.Modules {
139 module := findModule(ms.Path)
140
141 for _, is := range ms.Resources {
142 fullName := config.ResourceProviderFullName(is.Type, is.Provider)
143 inst := moduledeps.ProviderInstance(fullName)
144 if _, exists := module.Providers[inst]; !exists {
145 if module.Providers == nil {
146 module.Providers = make(moduledeps.Providers)
147 }
148 module.Providers[inst] = moduledeps.ProviderDependency{
149 Constraints: discovery.AllVersions,
150 Reason: moduledeps.ProviderDependencyFromState,
151 }
152 }
153 }
154 }
155
156}
diff --git a/vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go b/vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go
index 6ab9df7..cd4fe92 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/node_resource_refresh.go
@@ -45,13 +45,6 @@ func (n *NodeRefreshableManagedResource) DynamicExpand(ctx EvalContext) (*Graph,
45 Addr: n.ResourceAddr(), 45 Addr: n.ResourceAddr(),
46 }, 46 },
47 47
48 // Switch up any node missing state to a plannable resource. This helps
49 // catch cases where data sources depend on the counts from this resource
50 // during a scale out.
51 &ResourceRefreshPlannableTransformer{
52 State: state,
53 },
54
55 // Add the count orphans to make sure these resources are accounted for 48 // Add the count orphans to make sure these resources are accounted for
56 // during a scale in. 49 // during a scale in.
57 &OrphanResourceCountTransformer{ 50 &OrphanResourceCountTransformer{
@@ -100,6 +93,9 @@ func (n *NodeRefreshableManagedResourceInstance) EvalTree() EvalNode {
100 // Eval info is different depending on what kind of resource this is 93 // Eval info is different depending on what kind of resource this is
101 switch mode := n.Addr.Mode; mode { 94 switch mode := n.Addr.Mode; mode {
102 case config.ManagedResourceMode: 95 case config.ManagedResourceMode:
96 if n.ResourceState == nil {
97 return n.evalTreeManagedResourceNoState()
98 }
103 return n.evalTreeManagedResource() 99 return n.evalTreeManagedResource()
104 100
105 case config.DataResourceMode: 101 case config.DataResourceMode:
@@ -176,3 +172,88 @@ func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResource() EvalN
176 }, 172 },
177 } 173 }
178} 174}
175
176// evalTreeManagedResourceNoState produces an EvalSequence for refresh resource
177// nodes that don't have state attached. An example of where this functionality
178// is useful is when a resource that already exists in state is being scaled
179// out, ie: has its resource count increased. In this case, the scaled out node
180// needs to be available to other nodes (namely data sources) that may depend
181// on it for proper interpolation, or confusing "index out of range" errors can
182// occur.
183//
184// The steps in this sequence are very similar to the steps carried out in
185// plan, but nothing is done with the diff after it is created - it is dropped,
186// and its changes are not counted in the UI.
187func (n *NodeRefreshableManagedResourceInstance) evalTreeManagedResourceNoState() EvalNode {
188 // Declare a bunch of variables that are used for state during
189 // evaluation. Most of this are written to by-address below.
190 var provider ResourceProvider
191 var state *InstanceState
192 var resourceConfig *ResourceConfig
193
194 addr := n.NodeAbstractResource.Addr
195 stateID := addr.stateId()
196 info := &InstanceInfo{
197 Id: stateID,
198 Type: addr.Type,
199 ModulePath: normalizeModulePath(addr.Path),
200 }
201
202 // Build the resource for eval
203 resource := &Resource{
204 Name: addr.Name,
205 Type: addr.Type,
206 CountIndex: addr.Index,
207 }
208 if resource.CountIndex < 0 {
209 resource.CountIndex = 0
210 }
211
212 // Determine the dependencies for the state.
213 stateDeps := n.StateReferences()
214
215 return &EvalSequence{
216 Nodes: []EvalNode{
217 &EvalInterpolate{
218 Config: n.Config.RawConfig.Copy(),
219 Resource: resource,
220 Output: &resourceConfig,
221 },
222 &EvalGetProvider{
223 Name: n.ProvidedBy()[0],
224 Output: &provider,
225 },
226 // Re-run validation to catch any errors we missed, e.g. type
227 // mismatches on computed values.
228 &EvalValidateResource{
229 Provider: &provider,
230 Config: &resourceConfig,
231 ResourceName: n.Config.Name,
232 ResourceType: n.Config.Type,
233 ResourceMode: n.Config.Mode,
234 IgnoreWarnings: true,
235 },
236 &EvalReadState{
237 Name: stateID,
238 Output: &state,
239 },
240 &EvalDiff{
241 Name: stateID,
242 Info: info,
243 Config: &resourceConfig,
244 Resource: n.Config,
245 Provider: &provider,
246 State: &state,
247 OutputState: &state,
248 Stub: true,
249 },
250 &EvalWriteState{
251 Name: stateID,
252 ResourceType: n.Config.Type,
253 Provider: n.Config.Provider,
254 Dependencies: stateDeps,
255 State: &state,
256 },
257 },
258 }
259}
diff --git a/vendor/github.com/hashicorp/terraform/terraform/plan.go b/vendor/github.com/hashicorp/terraform/terraform/plan.go
index ea08845..51d6652 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/plan.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/plan.go
@@ -6,6 +6,7 @@ import (
6 "errors" 6 "errors"
7 "fmt" 7 "fmt"
8 "io" 8 "io"
9 "log"
9 "sync" 10 "sync"
10 11
11 "github.com/hashicorp/terraform/config/module" 12 "github.com/hashicorp/terraform/config/module"
@@ -31,6 +32,9 @@ type Plan struct {
31 Vars map[string]interface{} 32 Vars map[string]interface{}
32 Targets []string 33 Targets []string
33 34
35 TerraformVersion string
36 ProviderSHA256s map[string][]byte
37
34 // Backend is the backend that this plan should use and store data with. 38 // Backend is the backend that this plan should use and store data with.
35 Backend *BackendState 39 Backend *BackendState
36 40
@@ -40,19 +44,58 @@ type Plan struct {
40// Context returns a Context with the data encapsulated in this plan. 44// Context returns a Context with the data encapsulated in this plan.
41// 45//
42// The following fields in opts are overridden by the plan: Config, 46// The following fields in opts are overridden by the plan: Config,
43// Diff, State, Variables. 47// Diff, Variables.
48//
49// If State is not provided, it is set from the plan. If it _is_ provided,
50// it must be Equal to the state stored in plan, but may have a newer
51// serial.
44func (p *Plan) Context(opts *ContextOpts) (*Context, error) { 52func (p *Plan) Context(opts *ContextOpts) (*Context, error) {
53 var err error
54 opts, err = p.contextOpts(opts)
55 if err != nil {
56 return nil, err
57 }
58 return NewContext(opts)
59}
60
61// contextOpts mutates the given base ContextOpts in place to use input
62// objects obtained from the receiving plan.
63func (p *Plan) contextOpts(base *ContextOpts) (*ContextOpts, error) {
64 opts := base
65
45 opts.Diff = p.Diff 66 opts.Diff = p.Diff
46 opts.Module = p.Module 67 opts.Module = p.Module
47 opts.State = p.State
48 opts.Targets = p.Targets 68 opts.Targets = p.Targets
69 opts.ProviderSHA256s = p.ProviderSHA256s
70
71 if opts.State == nil {
72 opts.State = p.State
73 } else if !opts.State.Equal(p.State) {
74 // Even if we're overriding the state, it should be logically equal
75 // to what's in plan. The only valid change to have made by the time
76 // we get here is to have incremented the serial.
77 //
78 // Due to the fact that serialization may change the representation of
79 // the state, there is little chance that these aren't actually equal.
80 // Log the error condition for reference, but continue with the state
81 // we have.
82 log.Println("[WARNING] Plan state and ContextOpts state are not equal")
83 }
84
85 thisVersion := VersionString()
86 if p.TerraformVersion != "" && p.TerraformVersion != thisVersion {
87 return nil, fmt.Errorf(
88 "plan was created with a different version of Terraform (created with %s, but running %s)",
89 p.TerraformVersion, thisVersion,
90 )
91 }
49 92
50 opts.Variables = make(map[string]interface{}) 93 opts.Variables = make(map[string]interface{})
51 for k, v := range p.Vars { 94 for k, v := range p.Vars {
52 opts.Variables[k] = v 95 opts.Variables[k] = v
53 } 96 }
54 97
55 return NewContext(opts) 98 return opts, nil
56} 99}
57 100
58func (p *Plan) String() string { 101func (p *Plan) String() string {
@@ -86,7 +129,7 @@ func (p *Plan) init() {
86// the ability in the future to change the file format if we want for any 129// the ability in the future to change the file format if we want for any
87// reason. 130// reason.
88const planFormatMagic = "tfplan" 131const planFormatMagic = "tfplan"
89const planFormatVersion byte = 1 132const planFormatVersion byte = 2
90 133
91// ReadPlan reads a plan structure out of a reader in the format that 134// ReadPlan reads a plan structure out of a reader in the format that
92// was written by WritePlan. 135// was written by WritePlan.
diff --git a/vendor/github.com/hashicorp/terraform/terraform/resource_address.go b/vendor/github.com/hashicorp/terraform/terraform/resource_address.go
index a8a0c95..8badca8 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/resource_address.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/resource_address.go
@@ -8,6 +8,7 @@ import (
8 "strings" 8 "strings"
9 9
10 "github.com/hashicorp/terraform/config" 10 "github.com/hashicorp/terraform/config"
11 "github.com/hashicorp/terraform/config/module"
11) 12)
12 13
13// ResourceAddress is a way of identifying an individual resource (or, 14// ResourceAddress is a way of identifying an individual resource (or,
@@ -89,6 +90,51 @@ func (r *ResourceAddress) String() string {
89 return strings.Join(result, ".") 90 return strings.Join(result, ".")
90} 91}
91 92
93// HasResourceSpec returns true if the address has a resource spec, as
94// defined in the documentation:
95// https://www.terraform.io/docs/internals/resource-addressing.html
96// In particular, this returns false if the address contains only
97// a module path, thus addressing the entire module.
98func (r *ResourceAddress) HasResourceSpec() bool {
99 return r.Type != "" && r.Name != ""
100}
101
102// WholeModuleAddress returns the resource address that refers to all
103// resources in the same module as the receiver address.
104func (r *ResourceAddress) WholeModuleAddress() *ResourceAddress {
105 return &ResourceAddress{
106 Path: r.Path,
107 Index: -1,
108 InstanceTypeSet: false,
109 }
110}
111
112// MatchesConfig returns true if the receiver matches the given
113// configuration resource within the given configuration module.
114//
115// Since resource configuration blocks represent all of the instances of
116// a multi-instance resource, the index of the address (if any) is not
117// considered.
118func (r *ResourceAddress) MatchesConfig(mod *module.Tree, rc *config.Resource) bool {
119 if r.HasResourceSpec() {
120 if r.Mode != rc.Mode || r.Type != rc.Type || r.Name != rc.Name {
121 return false
122 }
123 }
124
125 addrPath := r.Path
126 cfgPath := mod.Path()
127
128 // normalize
129 if len(addrPath) == 0 {
130 addrPath = nil
131 }
132 if len(cfgPath) == 0 {
133 cfgPath = nil
134 }
135 return reflect.DeepEqual(addrPath, cfgPath)
136}
137
92// stateId returns the ID that this resource should be entered with 138// stateId returns the ID that this resource should be entered with
93// in the state. This is also used for diffs. In the future, we'd like to 139// in the state. This is also used for diffs. In the future, we'd like to
94// move away from this string field so I don't export this. 140// move away from this string field so I don't export this.
@@ -185,7 +231,10 @@ func ParseResourceAddress(s string) (*ResourceAddress, error) {
185 231
186 // not allowed to say "data." without a type following 232 // not allowed to say "data." without a type following
187 if mode == config.DataResourceMode && matches["type"] == "" { 233 if mode == config.DataResourceMode && matches["type"] == "" {
188 return nil, fmt.Errorf("must target specific data instance") 234 return nil, fmt.Errorf(
235 "invalid resource address %q: must target specific data instance",
236 s,
237 )
189 } 238 }
190 239
191 return &ResourceAddress{ 240 return &ResourceAddress{
@@ -199,6 +248,75 @@ func ParseResourceAddress(s string) (*ResourceAddress, error) {
199 }, nil 248 }, nil
200} 249}
201 250
251// ParseResourceAddressForInstanceDiff creates a ResourceAddress for a
252// resource name as described in a module diff.
253//
254// For historical reasons a different addressing format is used in this
255// context. The internal format should not be shown in the UI and instead
256// this function should be used to translate to a ResourceAddress and
257// then, where appropriate, use the String method to produce a canonical
258// resource address string for display in the UI.
259//
260// The given path slice must be empty (or nil) for the root module, and
261// otherwise consist of a sequence of module names traversing down into
262// the module tree. If a non-nil path is provided, the caller must not
263// modify its underlying array after passing it to this function.
264func ParseResourceAddressForInstanceDiff(path []string, key string) (*ResourceAddress, error) {
265 addr, err := parseResourceAddressInternal(key)
266 if err != nil {
267 return nil, err
268 }
269 addr.Path = path
270 return addr, nil
271}
272
273// Contains returns true if and only if the given node is contained within
274// the receiver.
275//
276// Containment is defined in terms of the module and resource heirarchy:
277// a resource is contained within its module and any ancestor modules,
278// an indexed resource instance is contained with the unindexed resource, etc.
279func (addr *ResourceAddress) Contains(other *ResourceAddress) bool {
280 ourPath := addr.Path
281 givenPath := other.Path
282 if len(givenPath) < len(ourPath) {
283 return false
284 }
285 for i := range ourPath {
286 if ourPath[i] != givenPath[i] {
287 return false
288 }
289 }
290
291 // If the receiver is a whole-module address then the path prefix
292 // matching is all we need.
293 if !addr.HasResourceSpec() {
294 return true
295 }
296
297 if addr.Type != other.Type || addr.Name != other.Name || addr.Mode != other.Mode {
298 return false
299 }
300
301 if addr.Index != -1 && addr.Index != other.Index {
302 return false
303 }
304
305 if addr.InstanceTypeSet && (addr.InstanceTypeSet != other.InstanceTypeSet || addr.InstanceType != other.InstanceType) {
306 return false
307 }
308
309 return true
310}
311
312// Equals returns true if the receiver matches the given address.
313//
314// The name of this method is a misnomer, since it doesn't test for exact
315// equality. Instead, it tests that the _specified_ parts of each
316// address match, treating any unspecified parts as wildcards.
317//
318// See also Contains, which takes a more heirarchical approach to comparing
319// addresses.
202func (addr *ResourceAddress) Equals(raw interface{}) bool { 320func (addr *ResourceAddress) Equals(raw interface{}) bool {
203 other, ok := raw.(*ResourceAddress) 321 other, ok := raw.(*ResourceAddress)
204 if !ok { 322 if !ok {
@@ -233,6 +351,58 @@ func (addr *ResourceAddress) Equals(raw interface{}) bool {
233 modeMatch 351 modeMatch
234} 352}
235 353
354// Less returns true if and only if the receiver should be sorted before
355// the given address when presenting a list of resource addresses to
356// an end-user.
357//
358// This sort uses lexicographic sorting for most components, but uses
359// numeric sort for indices, thus causing index 10 to sort after
360// index 9, rather than after index 1.
361func (addr *ResourceAddress) Less(other *ResourceAddress) bool {
362
363 switch {
364
365 case len(addr.Path) < len(other.Path):
366 return true
367
368 case !reflect.DeepEqual(addr.Path, other.Path):
369 // If the two paths are the same length but don't match, we'll just
370 // cheat and compare the string forms since it's easier than
371 // comparing all of the path segments in turn.
372 addrStr := addr.String()
373 otherStr := other.String()
374 return addrStr < otherStr
375
376 case addr.Mode == config.DataResourceMode && other.Mode != config.DataResourceMode:
377 return true
378
379 case addr.Type < other.Type:
380 return true
381
382 case addr.Name < other.Name:
383 return true
384
385 case addr.Index < other.Index:
386 // Since "Index" is -1 for an un-indexed address, this also conveniently
387 // sorts unindexed addresses before indexed ones, should they both
388 // appear for some reason.
389 return true
390
391 case other.InstanceTypeSet && !addr.InstanceTypeSet:
392 return true
393
394 case addr.InstanceType < other.InstanceType:
395 // InstanceType is actually an enum, so this is just an arbitrary
396 // sort based on the enum numeric values, and thus not particularly
397 // meaningful.
398 return true
399
400 default:
401 return false
402
403 }
404}
405
236func ParseResourceIndex(s string) (int, error) { 406func ParseResourceIndex(s string) (int, error) {
237 if s == "" { 407 if s == "" {
238 return -1, nil 408 return -1, nil
@@ -275,7 +445,7 @@ func tokenizeResourceAddress(s string) (map[string]string, error) {
275 // string "aws_instance.web.tainted[1]" 445 // string "aws_instance.web.tainted[1]"
276 re := regexp.MustCompile(`\A` + 446 re := regexp.MustCompile(`\A` +
277 // "module.foo.module.bar" (optional) 447 // "module.foo.module.bar" (optional)
278 `(?P<path>(?:module\.[^.]+\.?)*)` + 448 `(?P<path>(?:module\.(?P<module_name>[^.]+)\.?)*)` +
279 // possibly "data.", if targeting is a data resource 449 // possibly "data.", if targeting is a data resource
280 `(?P<data_prefix>(?:data\.)?)` + 450 `(?P<data_prefix>(?:data\.)?)` +
281 // "aws_instance.web" (optional when module path specified) 451 // "aws_instance.web" (optional when module path specified)
@@ -289,7 +459,7 @@ func tokenizeResourceAddress(s string) (map[string]string, error) {
289 groupNames := re.SubexpNames() 459 groupNames := re.SubexpNames()
290 rawMatches := re.FindAllStringSubmatch(s, -1) 460 rawMatches := re.FindAllStringSubmatch(s, -1)
291 if len(rawMatches) != 1 { 461 if len(rawMatches) != 1 {
292 return nil, fmt.Errorf("Problem parsing address: %q", s) 462 return nil, fmt.Errorf("invalid resource address %q", s)
293 } 463 }
294 464
295 matches := make(map[string]string) 465 matches := make(map[string]string)
diff --git a/vendor/github.com/hashicorp/terraform/terraform/resource_provider.go b/vendor/github.com/hashicorp/terraform/terraform/resource_provider.go
index 1a68c86..7d78f67 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/resource_provider.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/resource_provider.go
@@ -1,5 +1,12 @@
1package terraform 1package terraform
2 2
3import (
4 "fmt"
5
6 multierror "github.com/hashicorp/go-multierror"
7 "github.com/hashicorp/terraform/plugin/discovery"
8)
9
3// ResourceProvider is an interface that must be implemented by any 10// ResourceProvider is an interface that must be implemented by any
4// resource provider: the thing that creates and manages the resources in 11// resource provider: the thing that creates and manages the resources in
5// a Terraform configuration. 12// a Terraform configuration.
@@ -154,6 +161,18 @@ type ResourceProvider interface {
154 ReadDataApply(*InstanceInfo, *InstanceDiff) (*InstanceState, error) 161 ReadDataApply(*InstanceInfo, *InstanceDiff) (*InstanceState, error)
155} 162}
156 163
164// ResourceProviderError may be returned when creating a Context if the
165// required providers cannot be satisfied. This error can then be used to
166// format a more useful message for the user.
167type ResourceProviderError struct {
168 Errors []error
169}
170
171func (e *ResourceProviderError) Error() string {
172 // use multierror to format the default output
173 return multierror.Append(nil, e.Errors...).Error()
174}
175
157// ResourceProviderCloser is an interface that providers that can close 176// ResourceProviderCloser is an interface that providers that can close
158// connections that aren't needed anymore must implement. 177// connections that aren't needed anymore must implement.
159type ResourceProviderCloser interface { 178type ResourceProviderCloser interface {
@@ -171,6 +190,50 @@ type DataSource struct {
171 Name string 190 Name string
172} 191}
173 192
193// ResourceProviderResolver is an interface implemented by objects that are
194// able to resolve a given set of resource provider version constraints
195// into ResourceProviderFactory callbacks.
196type ResourceProviderResolver interface {
197 // Given a constraint map, return a ResourceProviderFactory for each
198 // requested provider. If some or all of the constraints cannot be
199 // satisfied, return a non-nil slice of errors describing the problems.
200 ResolveProviders(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error)
201}
202
203// ResourceProviderResolverFunc wraps a callback function and turns it into
204// a ResourceProviderResolver implementation, for convenience in situations
205// where a function and its associated closure are sufficient as a resolver
206// implementation.
207type ResourceProviderResolverFunc func(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error)
208
209// ResolveProviders implements ResourceProviderResolver by calling the
210// wrapped function.
211func (f ResourceProviderResolverFunc) ResolveProviders(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error) {
212 return f(reqd)
213}
214
215// ResourceProviderResolverFixed returns a ResourceProviderResolver that
216// has a fixed set of provider factories provided by the caller. The returned
217// resolver ignores version constraints entirely and just returns the given
218// factory for each requested provider name.
219//
220// This function is primarily used in tests, to provide mock providers or
221// in-process providers under test.
222func ResourceProviderResolverFixed(factories map[string]ResourceProviderFactory) ResourceProviderResolver {
223 return ResourceProviderResolverFunc(func(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error) {
224 ret := make(map[string]ResourceProviderFactory, len(reqd))
225 var errs []error
226 for name := range reqd {
227 if factory, exists := factories[name]; exists {
228 ret[name] = factory
229 } else {
230 errs = append(errs, fmt.Errorf("provider %q is not available", name))
231 }
232 }
233 return ret, errs
234 })
235}
236
174// ResourceProviderFactory is a function type that creates a new instance 237// ResourceProviderFactory is a function type that creates a new instance
175// of a resource provider. 238// of a resource provider.
176type ResourceProviderFactory func() (ResourceProvider, error) 239type ResourceProviderFactory func() (ResourceProvider, error)
@@ -202,3 +265,21 @@ func ProviderHasDataSource(p ResourceProvider, n string) bool {
202 265
203 return false 266 return false
204} 267}
268
269// resourceProviderFactories matches available plugins to the given version
270// requirements to produce a map of compatible provider plugins if possible,
271// or an error if the currently-available plugins are insufficient.
272//
273// This should be called only with configurations that have passed calls
274// to config.Validate(), which ensures that all of the given version
275// constraints are valid. It will panic if any invalid constraints are present.
276func resourceProviderFactories(resolver ResourceProviderResolver, reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, error) {
277 ret, errs := resolver.ResolveProviders(reqd)
278 if errs != nil {
279 return nil, &ResourceProviderError{
280 Errors: errs,
281 }
282 }
283
284 return ret, nil
285}
diff --git a/vendor/github.com/hashicorp/terraform/terraform/state.go b/vendor/github.com/hashicorp/terraform/terraform/state.go
index 074b682..0c46194 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/state.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/state.go
@@ -533,6 +533,43 @@ func (s *State) equal(other *State) bool {
533 return true 533 return true
534} 534}
535 535
536// MarshalEqual is similar to Equal but provides a stronger definition of
537// "equal", where two states are equal if and only if their serialized form
538// is byte-for-byte identical.
539//
540// This is primarily useful for callers that are trying to save snapshots
541// of state to persistent storage, allowing them to detect when a new
542// snapshot must be taken.
543//
544// Note that the serial number and lineage are included in the serialized form,
545// so it's the caller's responsibility to properly manage these attributes
546// so that this method is only called on two states that have the same
547// serial and lineage, unless detecting such differences is desired.
548func (s *State) MarshalEqual(other *State) bool {
549 if s == nil && other == nil {
550 return true
551 } else if s == nil || other == nil {
552 return false
553 }
554
555 recvBuf := &bytes.Buffer{}
556 otherBuf := &bytes.Buffer{}
557
558 err := WriteState(s, recvBuf)
559 if err != nil {
560 // should never happen, since we're writing to a buffer
561 panic(err)
562 }
563
564 err = WriteState(other, otherBuf)
565 if err != nil {
566 // should never happen, since we're writing to a buffer
567 panic(err)
568 }
569
570 return bytes.Equal(recvBuf.Bytes(), otherBuf.Bytes())
571}
572
536type StateAgeComparison int 573type StateAgeComparison int
537 574
538const ( 575const (
@@ -603,6 +640,10 @@ func (s *State) SameLineage(other *State) bool {
603// DeepCopy performs a deep copy of the state structure and returns 640// DeepCopy performs a deep copy of the state structure and returns
604// a new structure. 641// a new structure.
605func (s *State) DeepCopy() *State { 642func (s *State) DeepCopy() *State {
643 if s == nil {
644 return nil
645 }
646
606 copy, err := copystructure.Config{Lock: true}.Copy(s) 647 copy, err := copystructure.Config{Lock: true}.Copy(s)
607 if err != nil { 648 if err != nil {
608 panic(err) 649 panic(err)
@@ -611,30 +652,6 @@ func (s *State) DeepCopy() *State {
611 return copy.(*State) 652 return copy.(*State)
612} 653}
613 654
614// IncrementSerialMaybe increments the serial number of this state
615// if it different from the other state.
616func (s *State) IncrementSerialMaybe(other *State) {
617 if s == nil {
618 return
619 }
620 if other == nil {
621 return
622 }
623 s.Lock()
624 defer s.Unlock()
625
626 if s.Serial > other.Serial {
627 return
628 }
629 if other.TFVersion != s.TFVersion || !s.equal(other) {
630 if other.Serial > s.Serial {
631 s.Serial = other.Serial
632 }
633
634 s.Serial++
635 }
636}
637
638// FromFutureTerraform checks if this state was written by a Terraform 655// FromFutureTerraform checks if this state was written by a Terraform
639// version from the future. 656// version from the future.
640func (s *State) FromFutureTerraform() bool { 657func (s *State) FromFutureTerraform() bool {
@@ -660,6 +677,7 @@ func (s *State) init() {
660 if s.Version == 0 { 677 if s.Version == 0 {
661 s.Version = StateVersion 678 s.Version = StateVersion
662 } 679 }
680
663 if s.moduleByPath(rootModulePath) == nil { 681 if s.moduleByPath(rootModulePath) == nil {
664 s.addModule(rootModulePath) 682 s.addModule(rootModulePath)
665 } 683 }
diff --git a/vendor/github.com/hashicorp/terraform/terraform/test_failure b/vendor/github.com/hashicorp/terraform/terraform/test_failure
new file mode 100644
index 0000000..5d3ad1a
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/terraform/test_failure
@@ -0,0 +1,9 @@
1--- FAIL: TestContext2Plan_moduleProviderInherit (0.01s)
2 context_plan_test.go:552: bad: []string{"child"}
3map[string]dag.Vertex{}
4"module.middle.null"
5map[string]dag.Vertex{}
6"module.middle.module.inner.null"
7map[string]dag.Vertex{}
8"aws"
9FAIL
diff --git a/vendor/github.com/hashicorp/terraform/terraform/transform_resource_refresh_plannable.go b/vendor/github.com/hashicorp/terraform/terraform/transform_resource_refresh_plannable.go
deleted file mode 100644
index 35358a3..0000000
--- a/vendor/github.com/hashicorp/terraform/terraform/transform_resource_refresh_plannable.go
+++ /dev/null
@@ -1,55 +0,0 @@
1package terraform
2
3import (
4 "fmt"
5 "log"
6)
7
8// ResourceRefreshPlannableTransformer is a GraphTransformer that replaces any
9// nodes that don't have state yet exist in config with
10// NodePlannableResourceInstance.
11//
12// This transformer is used when expanding count on managed resource nodes
13// during the refresh phase to ensure that data sources that have
14// interpolations that depend on resources existing in the graph can be walked
15// properly.
16type ResourceRefreshPlannableTransformer struct {
17 // The full global state.
18 State *State
19}
20
21// Transform implements GraphTransformer for
22// ResourceRefreshPlannableTransformer.
23func (t *ResourceRefreshPlannableTransformer) Transform(g *Graph) error {
24nextVertex:
25 for _, v := range g.Vertices() {
26 addr := v.(*NodeRefreshableManagedResourceInstance).Addr
27
28 // Find the state for this address, if there is one
29 filter := &StateFilter{State: t.State}
30 results, err := filter.Filter(addr.String())
31 if err != nil {
32 return err
33 }
34
35 // Check to see if we have a state for this resource. If we do, skip this
36 // node.
37 for _, result := range results {
38 if _, ok := result.Value.(*ResourceState); ok {
39 continue nextVertex
40 }
41 }
42 // If we don't, convert this resource to a NodePlannableResourceInstance node
43 // with all of the data we need to make it happen.
44 log.Printf("[TRACE] No state for %s, converting to NodePlannableResourceInstance", addr.String())
45 new := &NodePlannableResourceInstance{
46 NodeAbstractResource: v.(*NodeRefreshableManagedResourceInstance).NodeAbstractResource,
47 }
48 // Replace the node in the graph
49 if !g.Replace(v, new) {
50 return fmt.Errorf("ResourceRefreshPlannableTransformer: Could not replace node %#v with %#v", v, new)
51 }
52 }
53
54 return nil
55}
diff --git a/vendor/github.com/hashicorp/terraform/terraform/transform_targets.go b/vendor/github.com/hashicorp/terraform/terraform/transform_targets.go
index 125f9e3..4f117b4 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/transform_targets.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/transform_targets.go
@@ -41,6 +41,12 @@ type TargetsTransformer struct {
41 // that already have the targets parsed 41 // that already have the targets parsed
42 ParsedTargets []ResourceAddress 42 ParsedTargets []ResourceAddress
43 43
44 // If set, the index portions of resource addresses will be ignored
45 // for comparison. This is used when transforming a graph where
46 // counted resources have not yet been expanded, since otherwise
47 // the unexpanded nodes (which never have indices) would not match.
48 IgnoreIndices bool
49
44 // Set to true when we're in a `terraform destroy` or a 50 // Set to true when we're in a `terraform destroy` or a
45 // `terraform plan -destroy` 51 // `terraform plan -destroy`
46 Destroy bool 52 Destroy bool
@@ -199,7 +205,12 @@ func (t *TargetsTransformer) nodeIsTarget(
199 205
200 addr := r.ResourceAddr() 206 addr := r.ResourceAddr()
201 for _, targetAddr := range addrs { 207 for _, targetAddr := range addrs {
202 if targetAddr.Equals(addr) { 208 if t.IgnoreIndices {
209 // targetAddr is not a pointer, so we can safely mutate it without
210 // interfering with references elsewhere.
211 targetAddr.Index = -1
212 }
213 if targetAddr.Contains(addr) {
203 return true 214 return true
204 } 215 }
205 } 216 }
diff --git a/vendor/github.com/hashicorp/terraform/terraform/util.go b/vendor/github.com/hashicorp/terraform/terraform/util.go
index f41f0d7..752241a 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/util.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/util.go
@@ -2,7 +2,8 @@ package terraform
2 2
3import ( 3import (
4 "sort" 4 "sort"
5 "strings" 5
6 "github.com/hashicorp/terraform/config"
6) 7)
7 8
8// Semaphore is a wrapper around a channel to provide 9// Semaphore is a wrapper around a channel to provide
@@ -47,21 +48,8 @@ func (s Semaphore) Release() {
47 } 48 }
48} 49}
49 50
50// resourceProvider returns the provider name for the given type. 51func resourceProvider(resourceType, explicitProvider string) string {
51func resourceProvider(t, alias string) string { 52 return config.ResourceProviderFullName(resourceType, explicitProvider)
52 if alias != "" {
53 return alias
54 }
55
56 idx := strings.IndexRune(t, '_')
57 if idx == -1 {
58 // If no underscores, the resource name is assumed to be
59 // also the provider name, e.g. if the provider exposes
60 // only a single resource of each type.
61 return t
62 }
63
64 return t[:idx]
65} 53}
66 54
67// strSliceContains checks if a given string is contained in a slice 55// strSliceContains checks if a given string is contained in a slice
diff --git a/vendor/github.com/hashicorp/terraform/terraform/version.go b/vendor/github.com/hashicorp/terraform/terraform/version.go
index cdfb8fb..d61b11e 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/version.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/version.go
@@ -7,12 +7,12 @@ import (
7) 7)
8 8
9// The main version number that is being run at the moment. 9// The main version number that is being run at the moment.
10const Version = "0.9.8" 10const Version = "0.10.0"
11 11
12// A pre-release marker for the version. If this is "" (empty string) 12// A pre-release marker for the version. If this is "" (empty string)
13// then it means that it is a final release. Otherwise, this is a pre-release 13// then it means that it is a final release. Otherwise, this is a pre-release
14// such as "dev" (in development), "beta", "rc1", etc. 14// such as "dev" (in development), "beta", "rc1", etc.
15var VersionPrerelease = "" 15var VersionPrerelease = "dev"
16 16
17// SemVersion is an instance of version.Version. This has the secondary 17// SemVersion is an instance of version.Version. This has the secondary
18// benefit of verifying during tests and init time that our version is a 18// benefit of verifying during tests and init time that our version is a
diff --git a/vendor/golang.org/x/crypto/cast5/cast5.go b/vendor/golang.org/x/crypto/cast5/cast5.go
new file mode 100644
index 0000000..0b4af37
--- /dev/null
+++ b/vendor/golang.org/x/crypto/cast5/cast5.go
@@ -0,0 +1,526 @@
1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package cast5 implements CAST5, as defined in RFC 2144. CAST5 is a common
6// OpenPGP cipher.
7package cast5 // import "golang.org/x/crypto/cast5"
8
9import "errors"
10
11const BlockSize = 8
12const KeySize = 16
13
14type Cipher struct {
15 masking [16]uint32
16 rotate [16]uint8
17}
18
19func NewCipher(key []byte) (c *Cipher, err error) {
20 if len(key) != KeySize {
21 return nil, errors.New("CAST5: keys must be 16 bytes")
22 }
23
24 c = new(Cipher)
25 c.keySchedule(key)
26 return
27}
28
29func (c *Cipher) BlockSize() int {
30 return BlockSize
31}
32
33func (c *Cipher) Encrypt(dst, src []byte) {
34 l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
35 r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
36
37 l, r = r, l^f1(r, c.masking[0], c.rotate[0])
38 l, r = r, l^f2(r, c.masking[1], c.rotate[1])
39 l, r = r, l^f3(r, c.masking[2], c.rotate[2])
40 l, r = r, l^f1(r, c.masking[3], c.rotate[3])
41
42 l, r = r, l^f2(r, c.masking[4], c.rotate[4])
43 l, r = r, l^f3(r, c.masking[5], c.rotate[5])
44 l, r = r, l^f1(r, c.masking[6], c.rotate[6])
45 l, r = r, l^f2(r, c.masking[7], c.rotate[7])
46
47 l, r = r, l^f3(r, c.masking[8], c.rotate[8])
48 l, r = r, l^f1(r, c.masking[9], c.rotate[9])
49 l, r = r, l^f2(r, c.masking[10], c.rotate[10])
50 l, r = r, l^f3(r, c.masking[11], c.rotate[11])
51
52 l, r = r, l^f1(r, c.masking[12], c.rotate[12])
53 l, r = r, l^f2(r, c.masking[13], c.rotate[13])
54 l, r = r, l^f3(r, c.masking[14], c.rotate[14])
55 l, r = r, l^f1(r, c.masking[15], c.rotate[15])
56
57 dst[0] = uint8(r >> 24)
58 dst[1] = uint8(r >> 16)
59 dst[2] = uint8(r >> 8)
60 dst[3] = uint8(r)
61 dst[4] = uint8(l >> 24)
62 dst[5] = uint8(l >> 16)
63 dst[6] = uint8(l >> 8)
64 dst[7] = uint8(l)
65}
66
67func (c *Cipher) Decrypt(dst, src []byte) {
68 l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
69 r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
70
71 l, r = r, l^f1(r, c.masking[15], c.rotate[15])
72 l, r = r, l^f3(r, c.masking[14], c.rotate[14])
73 l, r = r, l^f2(r, c.masking[13], c.rotate[13])
74 l, r = r, l^f1(r, c.masking[12], c.rotate[12])
75
76 l, r = r, l^f3(r, c.masking[11], c.rotate[11])
77 l, r = r, l^f2(r, c.masking[10], c.rotate[10])
78 l, r = r, l^f1(r, c.masking[9], c.rotate[9])
79 l, r = r, l^f3(r, c.masking[8], c.rotate[8])
80
81 l, r = r, l^f2(r, c.masking[7], c.rotate[7])
82 l, r = r, l^f1(r, c.masking[6], c.rotate[6])
83 l, r = r, l^f3(r, c.masking[5], c.rotate[5])
84 l, r = r, l^f2(r, c.masking[4], c.rotate[4])
85
86 l, r = r, l^f1(r, c.masking[3], c.rotate[3])
87 l, r = r, l^f3(r, c.masking[2], c.rotate[2])
88 l, r = r, l^f2(r, c.masking[1], c.rotate[1])
89 l, r = r, l^f1(r, c.masking[0], c.rotate[0])
90
91 dst[0] = uint8(r >> 24)
92 dst[1] = uint8(r >> 16)
93 dst[2] = uint8(r >> 8)
94 dst[3] = uint8(r)
95 dst[4] = uint8(l >> 24)
96 dst[5] = uint8(l >> 16)
97 dst[6] = uint8(l >> 8)
98 dst[7] = uint8(l)
99}
100
101type keyScheduleA [4][7]uint8
102type keyScheduleB [4][5]uint8
103
104// keyScheduleRound contains the magic values for a round of the key schedule.
105// The keyScheduleA deals with the lines like:
106// z0z1z2z3 = x0x1x2x3 ^ S5[xD] ^ S6[xF] ^ S7[xC] ^ S8[xE] ^ S7[x8]
107// Conceptually, both x and z are in the same array, x first. The first
108// element describes which word of this array gets written to and the
109// second, which word gets read. So, for the line above, it's "4, 0", because
110// it's writing to the first word of z, which, being after x, is word 4, and
111// reading from the first word of x: word 0.
112//
113// Next are the indexes into the S-boxes. Now the array is treated as bytes. So
114// "xD" is 0xd. The first byte of z is written as "16 + 0", just to be clear
115// that it's z that we're indexing.
116//
117// keyScheduleB deals with lines like:
118// K1 = S5[z8] ^ S6[z9] ^ S7[z7] ^ S8[z6] ^ S5[z2]
119// "K1" is ignored because key words are always written in order. So the five
120// elements are the S-box indexes. They use the same form as in keyScheduleA,
121// above.
122
123type keyScheduleRound struct{}
124type keySchedule []keyScheduleRound
125
126var schedule = []struct {
127 a keyScheduleA
128 b keyScheduleB
129}{
130 {
131 keyScheduleA{
132 {4, 0, 0xd, 0xf, 0xc, 0xe, 0x8},
133 {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
134 {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
135 {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
136 },
137 keyScheduleB{
138 {16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2},
139 {16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6},
140 {16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9},
141 {16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc},
142 },
143 },
144 {
145 keyScheduleA{
146 {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
147 {1, 4, 0, 2, 1, 3, 16 + 2},
148 {2, 5, 7, 6, 5, 4, 16 + 1},
149 {3, 7, 0xa, 9, 0xb, 8, 16 + 3},
150 },
151 keyScheduleB{
152 {3, 2, 0xc, 0xd, 8},
153 {1, 0, 0xe, 0xf, 0xd},
154 {7, 6, 8, 9, 3},
155 {5, 4, 0xa, 0xb, 7},
156 },
157 },
158 {
159 keyScheduleA{
160 {4, 0, 0xd, 0xf, 0xc, 0xe, 8},
161 {5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa},
162 {6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9},
163 {7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb},
164 },
165 keyScheduleB{
166 {16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9},
167 {16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc},
168 {16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2},
169 {16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6},
170 },
171 },
172 {
173 keyScheduleA{
174 {0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0},
175 {1, 4, 0, 2, 1, 3, 16 + 2},
176 {2, 5, 7, 6, 5, 4, 16 + 1},
177 {3, 7, 0xa, 9, 0xb, 8, 16 + 3},
178 },
179 keyScheduleB{
180 {8, 9, 7, 6, 3},
181 {0xa, 0xb, 5, 4, 7},
182 {0xc, 0xd, 3, 2, 8},
183 {0xe, 0xf, 1, 0, 0xd},
184 },
185 },
186}
187
188func (c *Cipher) keySchedule(in []byte) {
189 var t [8]uint32
190 var k [32]uint32
191
192 for i := 0; i < 4; i++ {
193 j := i * 4
194 t[i] = uint32(in[j])<<24 | uint32(in[j+1])<<16 | uint32(in[j+2])<<8 | uint32(in[j+3])
195 }
196
197 x := []byte{6, 7, 4, 5}
198 ki := 0
199
200 for half := 0; half < 2; half++ {
201 for _, round := range schedule {
202 for j := 0; j < 4; j++ {
203 var a [7]uint8
204 copy(a[:], round.a[j][:])
205 w := t[a[1]]
206 w ^= sBox[4][(t[a[2]>>2]>>(24-8*(a[2]&3)))&0xff]
207 w ^= sBox[5][(t[a[3]>>2]>>(24-8*(a[3]&3)))&0xff]
208 w ^= sBox[6][(t[a[4]>>2]>>(24-8*(a[4]&3)))&0xff]
209 w ^= sBox[7][(t[a[5]>>2]>>(24-8*(a[5]&3)))&0xff]
210 w ^= sBox[x[j]][(t[a[6]>>2]>>(24-8*(a[6]&3)))&0xff]
211 t[a[0]] = w
212 }
213
214 for j := 0; j < 4; j++ {
215 var b [5]uint8
216 copy(b[:], round.b[j][:])
217 w := sBox[4][(t[b[0]>>2]>>(24-8*(b[0]&3)))&0xff]
218 w ^= sBox[5][(t[b[1]>>2]>>(24-8*(b[1]&3)))&0xff]
219 w ^= sBox[6][(t[b[2]>>2]>>(24-8*(b[2]&3)))&0xff]
220 w ^= sBox[7][(t[b[3]>>2]>>(24-8*(b[3]&3)))&0xff]
221 w ^= sBox[4+j][(t[b[4]>>2]>>(24-8*(b[4]&3)))&0xff]
222 k[ki] = w
223 ki++
224 }
225 }
226 }
227
228 for i := 0; i < 16; i++ {
229 c.masking[i] = k[i]
230 c.rotate[i] = uint8(k[16+i] & 0x1f)
231 }
232}
233
234// These are the three 'f' functions. See RFC 2144, section 2.2.
235func f1(d, m uint32, r uint8) uint32 {
236 t := m + d
237 I := (t << r) | (t >> (32 - r))
238 return ((sBox[0][I>>24] ^ sBox[1][(I>>16)&0xff]) - sBox[2][(I>>8)&0xff]) + sBox[3][I&0xff]
239}
240
241func f2(d, m uint32, r uint8) uint32 {
242 t := m ^ d
243 I := (t << r) | (t >> (32 - r))
244 return ((sBox[0][I>>24] - sBox[1][(I>>16)&0xff]) + sBox[2][(I>>8)&0xff]) ^ sBox[3][I&0xff]
245}
246
247func f3(d, m uint32, r uint8) uint32 {
248 t := m - d
249 I := (t << r) | (t >> (32 - r))
250 return ((sBox[0][I>>24] + sBox[1][(I>>16)&0xff]) ^ sBox[2][(I>>8)&0xff]) - sBox[3][I&0xff]
251}
252
253var sBox = [8][256]uint32{
254 {
255 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
256 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
257 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
258 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
259 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
260 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
261 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
262 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
263 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
264 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
265 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
266 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
267 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
268 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
269 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
270 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
271 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
272 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
273 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
274 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
275 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
276 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
277 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
278 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
279 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
280 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
281 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
282 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
283 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
284 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
285 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
286 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf,
287 },
288 {
289 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
290 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
291 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
292 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
293 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
294 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
295 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
296 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
297 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
298 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
299 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
300 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
301 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
302 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
303 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
304 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
305 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
306 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
307 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
308 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
309 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
310 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
311 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
312 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
313 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
314 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
315 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
316 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
317 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
318 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
319 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
320 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1,
321 },
322 {
323 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
324 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
325 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
326 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
327 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
328 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
329 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
330 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
331 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
332 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
333 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
334 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
335 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
336 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
337 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
338 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
339 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
340 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
341 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
342 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
343 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
344 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
345 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
346 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
347 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
348 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
349 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
350 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
351 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
352 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
353 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
354 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783,
355 },
356 {
357 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
358 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
359 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
360 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
361 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
362 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
363 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
364 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
365 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
366 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
367 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
368 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
369 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
370 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
371 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
372 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
373 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
374 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
375 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
376 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
377 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
378 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
379 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
380 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
381 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
382 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
383 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
384 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
385 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
386 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
387 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
388 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2,
389 },
390 {
391 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
392 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
393 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
394 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
395 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
396 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
397 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
398 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
399 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
400 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
401 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
402 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
403 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
404 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
405 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
406 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
407 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
408 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
409 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
410 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
411 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
412 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
413 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
414 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
415 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
416 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
417 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
418 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
419 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
420 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
421 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
422 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4,
423 },
424 {
425 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
426 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
427 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
428 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
429 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
430 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
431 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
432 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
433 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
434 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
435 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
436 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
437 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
438 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
439 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
440 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
441 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
442 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
443 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
444 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
445 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
446 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
447 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
448 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
449 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
450 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
451 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
452 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
453 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
454 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
455 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
456 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f,
457 },
458 {
459 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
460 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
461 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
462 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
463 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
464 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
465 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
466 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
467 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
468 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
469 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
470 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
471 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
472 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
473 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
474 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
475 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
476 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
477 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
478 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
479 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
480 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
481 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
482 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
483 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
484 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
485 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
486 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
487 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
488 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
489 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
490 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3,
491 },
492 {
493 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
494 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
495 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
496 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
497 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
498 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
499 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
500 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
501 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
502 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
503 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
504 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
505 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
506 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
507 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
508 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
509 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
510 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
511 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
512 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
513 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
514 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
515 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
516 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
517 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
518 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
519 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
520 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
521 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
522 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
523 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
524 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e,
525 },
526}
diff --git a/vendor/golang.org/x/crypto/openpgp/armor/armor.go b/vendor/golang.org/x/crypto/openpgp/armor/armor.go
new file mode 100644
index 0000000..592d186
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/armor/armor.go
@@ -0,0 +1,219 @@
1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
6// very similar to PEM except that it has an additional CRC checksum.
7package armor // import "golang.org/x/crypto/openpgp/armor"
8
9import (
10 "bufio"
11 "bytes"
12 "encoding/base64"
13 "golang.org/x/crypto/openpgp/errors"
14 "io"
15)
16
17// A Block represents an OpenPGP armored structure.
18//
19// The encoded form is:
20// -----BEGIN Type-----
21// Headers
22//
23// base64-encoded Bytes
24// '=' base64 encoded checksum
25// -----END Type-----
26// where Headers is a possibly empty sequence of Key: Value lines.
27//
28// Since the armored data can be very large, this package presents a streaming
29// interface.
30type Block struct {
31 Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE").
32 Header map[string]string // Optional headers.
33 Body io.Reader // A Reader from which the contents can be read
34 lReader lineReader
35 oReader openpgpReader
36}
37
38var ArmorCorrupt error = errors.StructuralError("armor invalid")
39
40const crc24Init = 0xb704ce
41const crc24Poly = 0x1864cfb
42const crc24Mask = 0xffffff
43
44// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
45func crc24(crc uint32, d []byte) uint32 {
46 for _, b := range d {
47 crc ^= uint32(b) << 16
48 for i := 0; i < 8; i++ {
49 crc <<= 1
50 if crc&0x1000000 != 0 {
51 crc ^= crc24Poly
52 }
53 }
54 }
55 return crc
56}
57
58var armorStart = []byte("-----BEGIN ")
59var armorEnd = []byte("-----END ")
60var armorEndOfLine = []byte("-----")
61
62// lineReader wraps a line based reader. It watches for the end of an armor
63// block and records the expected CRC value.
64type lineReader struct {
65 in *bufio.Reader
66 buf []byte
67 eof bool
68 crc uint32
69}
70
71func (l *lineReader) Read(p []byte) (n int, err error) {
72 if l.eof {
73 return 0, io.EOF
74 }
75
76 if len(l.buf) > 0 {
77 n = copy(p, l.buf)
78 l.buf = l.buf[n:]
79 return
80 }
81
82 line, isPrefix, err := l.in.ReadLine()
83 if err != nil {
84 return
85 }
86 if isPrefix {
87 return 0, ArmorCorrupt
88 }
89
90 if len(line) == 5 && line[0] == '=' {
91 // This is the checksum line
92 var expectedBytes [3]byte
93 var m int
94 m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:])
95 if m != 3 || err != nil {
96 return
97 }
98 l.crc = uint32(expectedBytes[0])<<16 |
99 uint32(expectedBytes[1])<<8 |
100 uint32(expectedBytes[2])
101
102 line, _, err = l.in.ReadLine()
103 if err != nil && err != io.EOF {
104 return
105 }
106 if !bytes.HasPrefix(line, armorEnd) {
107 return 0, ArmorCorrupt
108 }
109
110 l.eof = true
111 return 0, io.EOF
112 }
113
114 if len(line) > 96 {
115 return 0, ArmorCorrupt
116 }
117
118 n = copy(p, line)
119 bytesToSave := len(line) - n
120 if bytesToSave > 0 {
121 if cap(l.buf) < bytesToSave {
122 l.buf = make([]byte, 0, bytesToSave)
123 }
124 l.buf = l.buf[0:bytesToSave]
125 copy(l.buf, line[n:])
126 }
127
128 return
129}
130
131// openpgpReader passes Read calls to the underlying base64 decoder, but keeps
132// a running CRC of the resulting data and checks the CRC against the value
133// found by the lineReader at EOF.
134type openpgpReader struct {
135 lReader *lineReader
136 b64Reader io.Reader
137 currentCRC uint32
138}
139
140func (r *openpgpReader) Read(p []byte) (n int, err error) {
141 n, err = r.b64Reader.Read(p)
142 r.currentCRC = crc24(r.currentCRC, p[:n])
143
144 if err == io.EOF {
145 if r.lReader.crc != uint32(r.currentCRC&crc24Mask) {
146 return 0, ArmorCorrupt
147 }
148 }
149
150 return
151}
152
153// Decode reads a PGP armored block from the given Reader. It will ignore
154// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The
155// given Reader is not usable after calling this function: an arbitrary amount
156// of data may have been read past the end of the block.
157func Decode(in io.Reader) (p *Block, err error) {
158 r := bufio.NewReaderSize(in, 100)
159 var line []byte
160 ignoreNext := false
161
162TryNextBlock:
163 p = nil
164
165 // Skip leading garbage
166 for {
167 ignoreThis := ignoreNext
168 line, ignoreNext, err = r.ReadLine()
169 if err != nil {
170 return
171 }
172 if ignoreNext || ignoreThis {
173 continue
174 }
175 line = bytes.TrimSpace(line)
176 if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
177 break
178 }
179 }
180
181 p = new(Block)
182 p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
183 p.Header = make(map[string]string)
184 nextIsContinuation := false
185 var lastKey string
186
187 // Read headers
188 for {
189 isContinuation := nextIsContinuation
190 line, nextIsContinuation, err = r.ReadLine()
191 if err != nil {
192 p = nil
193 return
194 }
195 if isContinuation {
196 p.Header[lastKey] += string(line)
197 continue
198 }
199 line = bytes.TrimSpace(line)
200 if len(line) == 0 {
201 break
202 }
203
204 i := bytes.Index(line, []byte(": "))
205 if i == -1 {
206 goto TryNextBlock
207 }
208 lastKey = string(line[:i])
209 p.Header[lastKey] = string(line[i+2:])
210 }
211
212 p.lReader.in = r
213 p.oReader.currentCRC = crc24Init
214 p.oReader.lReader = &p.lReader
215 p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
216 p.Body = &p.oReader
217
218 return
219}
diff --git a/vendor/golang.org/x/crypto/openpgp/armor/encode.go b/vendor/golang.org/x/crypto/openpgp/armor/encode.go
new file mode 100644
index 0000000..6f07582
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/armor/encode.go
@@ -0,0 +1,160 @@
1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package armor
6
7import (
8 "encoding/base64"
9 "io"
10)
11
12var armorHeaderSep = []byte(": ")
13var blockEnd = []byte("\n=")
14var newline = []byte("\n")
15var armorEndOfLineOut = []byte("-----\n")
16
17// writeSlices writes its arguments to the given Writer.
18func writeSlices(out io.Writer, slices ...[]byte) (err error) {
19 for _, s := range slices {
20 _, err = out.Write(s)
21 if err != nil {
22 return err
23 }
24 }
25 return
26}
27
28// lineBreaker breaks data across several lines, all of the same byte length
29// (except possibly the last). Lines are broken with a single '\n'.
30type lineBreaker struct {
31 lineLength int
32 line []byte
33 used int
34 out io.Writer
35 haveWritten bool
36}
37
38func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
39 return &lineBreaker{
40 lineLength: lineLength,
41 line: make([]byte, lineLength),
42 used: 0,
43 out: out,
44 }
45}
46
47func (l *lineBreaker) Write(b []byte) (n int, err error) {
48 n = len(b)
49
50 if n == 0 {
51 return
52 }
53
54 if l.used == 0 && l.haveWritten {
55 _, err = l.out.Write([]byte{'\n'})
56 if err != nil {
57 return
58 }
59 }
60
61 if l.used+len(b) < l.lineLength {
62 l.used += copy(l.line[l.used:], b)
63 return
64 }
65
66 l.haveWritten = true
67 _, err = l.out.Write(l.line[0:l.used])
68 if err != nil {
69 return
70 }
71 excess := l.lineLength - l.used
72 l.used = 0
73
74 _, err = l.out.Write(b[0:excess])
75 if err != nil {
76 return
77 }
78
79 _, err = l.Write(b[excess:])
80 return
81}
82
83func (l *lineBreaker) Close() (err error) {
84 if l.used > 0 {
85 _, err = l.out.Write(l.line[0:l.used])
86 if err != nil {
87 return
88 }
89 }
90
91 return
92}
93
94// encoding keeps track of a running CRC24 over the data which has been written
95// to it and outputs a OpenPGP checksum when closed, followed by an armor
96// trailer.
97//
98// It's built into a stack of io.Writers:
99// encoding -> base64 encoder -> lineBreaker -> out
100type encoding struct {
101 out io.Writer
102 breaker *lineBreaker
103 b64 io.WriteCloser
104 crc uint32
105 blockType []byte
106}
107
108func (e *encoding) Write(data []byte) (n int, err error) {
109 e.crc = crc24(e.crc, data)
110 return e.b64.Write(data)
111}
112
113func (e *encoding) Close() (err error) {
114 err = e.b64.Close()
115 if err != nil {
116 return
117 }
118 e.breaker.Close()
119
120 var checksumBytes [3]byte
121 checksumBytes[0] = byte(e.crc >> 16)
122 checksumBytes[1] = byte(e.crc >> 8)
123 checksumBytes[2] = byte(e.crc)
124
125 var b64ChecksumBytes [4]byte
126 base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
127
128 return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
129}
130
131// Encode returns a WriteCloser which will encode the data written to it in
132// OpenPGP armor.
133func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) {
134 bType := []byte(blockType)
135 err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
136 if err != nil {
137 return
138 }
139
140 for k, v := range headers {
141 err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline)
142 if err != nil {
143 return
144 }
145 }
146
147 _, err = out.Write(newline)
148 if err != nil {
149 return
150 }
151
152 e := &encoding{
153 out: out,
154 breaker: newLineBreaker(out, 64),
155 crc: crc24Init,
156 blockType: bType,
157 }
158 e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
159 return e, nil
160}
diff --git a/vendor/golang.org/x/crypto/openpgp/canonical_text.go b/vendor/golang.org/x/crypto/openpgp/canonical_text.go
new file mode 100644
index 0000000..e601e38
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/canonical_text.go
@@ -0,0 +1,59 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package openpgp
6
7import "hash"
8
9// NewCanonicalTextHash reformats text written to it into the canonical
10// form and then applies the hash h. See RFC 4880, section 5.2.1.
11func NewCanonicalTextHash(h hash.Hash) hash.Hash {
12 return &canonicalTextHash{h, 0}
13}
14
15type canonicalTextHash struct {
16 h hash.Hash
17 s int
18}
19
20var newline = []byte{'\r', '\n'}
21
22func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
23 start := 0
24
25 for i, c := range buf {
26 switch cth.s {
27 case 0:
28 if c == '\r' {
29 cth.s = 1
30 } else if c == '\n' {
31 cth.h.Write(buf[start:i])
32 cth.h.Write(newline)
33 start = i + 1
34 }
35 case 1:
36 cth.s = 0
37 }
38 }
39
40 cth.h.Write(buf[start:])
41 return len(buf), nil
42}
43
44func (cth *canonicalTextHash) Sum(in []byte) []byte {
45 return cth.h.Sum(in)
46}
47
48func (cth *canonicalTextHash) Reset() {
49 cth.h.Reset()
50 cth.s = 0
51}
52
53func (cth *canonicalTextHash) Size() int {
54 return cth.h.Size()
55}
56
57func (cth *canonicalTextHash) BlockSize() int {
58 return cth.h.BlockSize()
59}
diff --git a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go
new file mode 100644
index 0000000..73f4fe3
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go
@@ -0,0 +1,122 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package elgamal implements ElGamal encryption, suitable for OpenPGP,
6// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on
7// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31,
8// n. 4, 1985, pp. 469-472.
9//
10// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
11// unsuitable for other protocols. RSA should be used in preference in any
12// case.
13package elgamal // import "golang.org/x/crypto/openpgp/elgamal"
14
15import (
16 "crypto/rand"
17 "crypto/subtle"
18 "errors"
19 "io"
20 "math/big"
21)
22
23// PublicKey represents an ElGamal public key.
24type PublicKey struct {
25 G, P, Y *big.Int
26}
27
28// PrivateKey represents an ElGamal private key.
29type PrivateKey struct {
30 PublicKey
31 X *big.Int
32}
33
34// Encrypt encrypts the given message to the given public key. The result is a
35// pair of integers. Errors can result from reading random, or because msg is
36// too large to be encrypted to the public key.
37func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
38 pLen := (pub.P.BitLen() + 7) / 8
39 if len(msg) > pLen-11 {
40 err = errors.New("elgamal: message too long")
41 return
42 }
43
44 // EM = 0x02 || PS || 0x00 || M
45 em := make([]byte, pLen-1)
46 em[0] = 2
47 ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
48 err = nonZeroRandomBytes(ps, random)
49 if err != nil {
50 return
51 }
52 em[len(em)-len(msg)-1] = 0
53 copy(mm, msg)
54
55 m := new(big.Int).SetBytes(em)
56
57 k, err := rand.Int(random, pub.P)
58 if err != nil {
59 return
60 }
61
62 c1 = new(big.Int).Exp(pub.G, k, pub.P)
63 s := new(big.Int).Exp(pub.Y, k, pub.P)
64 c2 = s.Mul(s, m)
65 c2.Mod(c2, pub.P)
66
67 return
68}
69
70// Decrypt takes two integers, resulting from an ElGamal encryption, and
71// returns the plaintext of the message. An error can result only if the
72// ciphertext is invalid. Users should keep in mind that this is a padding
73// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
74// be used to break the cryptosystem. See ``Chosen Ciphertext Attacks
75// Against Protocols Based on the RSA Encryption Standard PKCS #1'', Daniel
76// Bleichenbacher, Advances in Cryptology (Crypto '98),
77func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
78 s := new(big.Int).Exp(c1, priv.X, priv.P)
79 s.ModInverse(s, priv.P)
80 s.Mul(s, c2)
81 s.Mod(s, priv.P)
82 em := s.Bytes()
83
84 firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
85
86 // The remainder of the plaintext must be a string of non-zero random
87 // octets, followed by a 0, followed by the message.
88 // lookingForIndex: 1 iff we are still looking for the zero.
89 // index: the offset of the first zero byte.
90 var lookingForIndex, index int
91 lookingForIndex = 1
92
93 for i := 1; i < len(em); i++ {
94 equals0 := subtle.ConstantTimeByteEq(em[i], 0)
95 index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
96 lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
97 }
98
99 if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
100 return nil, errors.New("elgamal: decryption error")
101 }
102 return em[index+1:], nil
103}
104
105// nonZeroRandomBytes fills the given slice with non-zero random octets.
106func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
107 _, err = io.ReadFull(rand, s)
108 if err != nil {
109 return
110 }
111
112 for i := 0; i < len(s); i++ {
113 for s[i] == 0 {
114 _, err = io.ReadFull(rand, s[i:i+1])
115 if err != nil {
116 return
117 }
118 }
119 }
120
121 return
122}
diff --git a/vendor/golang.org/x/crypto/openpgp/errors/errors.go b/vendor/golang.org/x/crypto/openpgp/errors/errors.go
new file mode 100644
index 0000000..eb0550b
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/errors/errors.go
@@ -0,0 +1,72 @@
1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package errors contains common error types for the OpenPGP packages.
6package errors // import "golang.org/x/crypto/openpgp/errors"
7
8import (
9 "strconv"
10)
11
12// A StructuralError is returned when OpenPGP data is found to be syntactically
13// invalid.
14type StructuralError string
15
16func (s StructuralError) Error() string {
17 return "openpgp: invalid data: " + string(s)
18}
19
20// UnsupportedError indicates that, although the OpenPGP data is valid, it
21// makes use of currently unimplemented features.
22type UnsupportedError string
23
24func (s UnsupportedError) Error() string {
25 return "openpgp: unsupported feature: " + string(s)
26}
27
28// InvalidArgumentError indicates that the caller is in error and passed an
29// incorrect value.
30type InvalidArgumentError string
31
32func (i InvalidArgumentError) Error() string {
33 return "openpgp: invalid argument: " + string(i)
34}
35
36// SignatureError indicates that a syntactically valid signature failed to
37// validate.
38type SignatureError string
39
40func (b SignatureError) Error() string {
41 return "openpgp: invalid signature: " + string(b)
42}
43
44type keyIncorrectError int
45
46func (ki keyIncorrectError) Error() string {
47 return "openpgp: incorrect key"
48}
49
50var ErrKeyIncorrect error = keyIncorrectError(0)
51
52type unknownIssuerError int
53
54func (unknownIssuerError) Error() string {
55 return "openpgp: signature made by unknown entity"
56}
57
58var ErrUnknownIssuer error = unknownIssuerError(0)
59
60type keyRevokedError int
61
62func (keyRevokedError) Error() string {
63 return "openpgp: signature made by revoked key"
64}
65
66var ErrKeyRevoked error = keyRevokedError(0)
67
68type UnknownPacketTypeError uint8
69
70func (upte UnknownPacketTypeError) Error() string {
71 return "openpgp: unknown packet type: " + strconv.Itoa(int(upte))
72}
diff --git a/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/golang.org/x/crypto/openpgp/keys.go
new file mode 100644
index 0000000..68b14c6
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/keys.go
@@ -0,0 +1,637 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package openpgp
6
7import (
8 "crypto/rsa"
9 "io"
10 "time"
11
12 "golang.org/x/crypto/openpgp/armor"
13 "golang.org/x/crypto/openpgp/errors"
14 "golang.org/x/crypto/openpgp/packet"
15)
16
17// PublicKeyType is the armor type for a PGP public key.
18var PublicKeyType = "PGP PUBLIC KEY BLOCK"
19
20// PrivateKeyType is the armor type for a PGP private key.
21var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
22
23// An Entity represents the components of an OpenPGP key: a primary public key
24// (which must be a signing key), one or more identities claimed by that key,
25// and zero or more subkeys, which may be encryption keys.
26type Entity struct {
27 PrimaryKey *packet.PublicKey
28 PrivateKey *packet.PrivateKey
29 Identities map[string]*Identity // indexed by Identity.Name
30 Revocations []*packet.Signature
31 Subkeys []Subkey
32}
33
34// An Identity represents an identity claimed by an Entity and zero or more
35// assertions by other entities about that claim.
36type Identity struct {
37 Name string // by convention, has the form "Full Name (comment) <email@example.com>"
38 UserId *packet.UserId
39 SelfSignature *packet.Signature
40 Signatures []*packet.Signature
41}
42
43// A Subkey is an additional public key in an Entity. Subkeys can be used for
44// encryption.
45type Subkey struct {
46 PublicKey *packet.PublicKey
47 PrivateKey *packet.PrivateKey
48 Sig *packet.Signature
49}
50
51// A Key identifies a specific public key in an Entity. This is either the
52// Entity's primary key or a subkey.
53type Key struct {
54 Entity *Entity
55 PublicKey *packet.PublicKey
56 PrivateKey *packet.PrivateKey
57 SelfSignature *packet.Signature
58}
59
60// A KeyRing provides access to public and private keys.
61type KeyRing interface {
62 // KeysById returns the set of keys that have the given key id.
63 KeysById(id uint64) []Key
64 // KeysByIdAndUsage returns the set of keys with the given id
65 // that also meet the key usage given by requiredUsage.
66 // The requiredUsage is expressed as the bitwise-OR of
67 // packet.KeyFlag* values.
68 KeysByIdUsage(id uint64, requiredUsage byte) []Key
69 // DecryptionKeys returns all private keys that are valid for
70 // decryption.
71 DecryptionKeys() []Key
72}
73
74// primaryIdentity returns the Identity marked as primary or the first identity
75// if none are so marked.
76func (e *Entity) primaryIdentity() *Identity {
77 var firstIdentity *Identity
78 for _, ident := range e.Identities {
79 if firstIdentity == nil {
80 firstIdentity = ident
81 }
82 if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
83 return ident
84 }
85 }
86 return firstIdentity
87}
88
89// encryptionKey returns the best candidate Key for encrypting a message to the
90// given Entity.
91func (e *Entity) encryptionKey(now time.Time) (Key, bool) {
92 candidateSubkey := -1
93
94 // Iterate the keys to find the newest key
95 var maxTime time.Time
96 for i, subkey := range e.Subkeys {
97 if subkey.Sig.FlagsValid &&
98 subkey.Sig.FlagEncryptCommunications &&
99 subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
100 !subkey.Sig.KeyExpired(now) &&
101 (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
102 candidateSubkey = i
103 maxTime = subkey.Sig.CreationTime
104 }
105 }
106
107 if candidateSubkey != -1 {
108 subkey := e.Subkeys[candidateSubkey]
109 return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true
110 }
111
112 // If we don't have any candidate subkeys for encryption and
113 // the primary key doesn't have any usage metadata then we
114 // assume that the primary key is ok. Or, if the primary key is
115 // marked as ok to encrypt to, then we can obviously use it.
116 i := e.primaryIdentity()
117 if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications &&
118 e.PrimaryKey.PubKeyAlgo.CanEncrypt() &&
119 !i.SelfSignature.KeyExpired(now) {
120 return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
121 }
122
123 // This Entity appears to be signing only.
124 return Key{}, false
125}
126
127// signingKey return the best candidate Key for signing a message with this
128// Entity.
129func (e *Entity) signingKey(now time.Time) (Key, bool) {
130 candidateSubkey := -1
131
132 for i, subkey := range e.Subkeys {
133 if subkey.Sig.FlagsValid &&
134 subkey.Sig.FlagSign &&
135 subkey.PublicKey.PubKeyAlgo.CanSign() &&
136 !subkey.Sig.KeyExpired(now) {
137 candidateSubkey = i
138 break
139 }
140 }
141
142 if candidateSubkey != -1 {
143 subkey := e.Subkeys[candidateSubkey]
144 return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true
145 }
146
147 // If we have no candidate subkey then we assume that it's ok to sign
148 // with the primary key.
149 i := e.primaryIdentity()
150 if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign &&
151 !i.SelfSignature.KeyExpired(now) {
152 return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true
153 }
154
155 return Key{}, false
156}
157
158// An EntityList contains one or more Entities.
159type EntityList []*Entity
160
161// KeysById returns the set of keys that have the given key id.
162func (el EntityList) KeysById(id uint64) (keys []Key) {
163 for _, e := range el {
164 if e.PrimaryKey.KeyId == id {
165 var selfSig *packet.Signature
166 for _, ident := range e.Identities {
167 if selfSig == nil {
168 selfSig = ident.SelfSignature
169 } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId {
170 selfSig = ident.SelfSignature
171 break
172 }
173 }
174 keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig})
175 }
176
177 for _, subKey := range e.Subkeys {
178 if subKey.PublicKey.KeyId == id {
179 keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
180 }
181 }
182 }
183 return
184}
185
186// KeysByIdAndUsage returns the set of keys with the given id that also meet
187// the key usage given by requiredUsage. The requiredUsage is expressed as
188// the bitwise-OR of packet.KeyFlag* values.
189func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
190 for _, key := range el.KeysById(id) {
191 if len(key.Entity.Revocations) > 0 {
192 continue
193 }
194
195 if key.SelfSignature.RevocationReason != nil {
196 continue
197 }
198
199 if key.SelfSignature.FlagsValid && requiredUsage != 0 {
200 var usage byte
201 if key.SelfSignature.FlagCertify {
202 usage |= packet.KeyFlagCertify
203 }
204 if key.SelfSignature.FlagSign {
205 usage |= packet.KeyFlagSign
206 }
207 if key.SelfSignature.FlagEncryptCommunications {
208 usage |= packet.KeyFlagEncryptCommunications
209 }
210 if key.SelfSignature.FlagEncryptStorage {
211 usage |= packet.KeyFlagEncryptStorage
212 }
213 if usage&requiredUsage != requiredUsage {
214 continue
215 }
216 }
217
218 keys = append(keys, key)
219 }
220 return
221}
222
223// DecryptionKeys returns all private keys that are valid for decryption.
224func (el EntityList) DecryptionKeys() (keys []Key) {
225 for _, e := range el {
226 for _, subKey := range e.Subkeys {
227 if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
228 keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig})
229 }
230 }
231 }
232 return
233}
234
235// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
236func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
237 block, err := armor.Decode(r)
238 if err == io.EOF {
239 return nil, errors.InvalidArgumentError("no armored data found")
240 }
241 if err != nil {
242 return nil, err
243 }
244 if block.Type != PublicKeyType && block.Type != PrivateKeyType {
245 return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
246 }
247
248 return ReadKeyRing(block.Body)
249}
250
251// ReadKeyRing reads one or more public/private keys. Unsupported keys are
252// ignored as long as at least a single valid key is found.
253func ReadKeyRing(r io.Reader) (el EntityList, err error) {
254 packets := packet.NewReader(r)
255 var lastUnsupportedError error
256
257 for {
258 var e *Entity
259 e, err = ReadEntity(packets)
260 if err != nil {
261 // TODO: warn about skipped unsupported/unreadable keys
262 if _, ok := err.(errors.UnsupportedError); ok {
263 lastUnsupportedError = err
264 err = readToNextPublicKey(packets)
265 } else if _, ok := err.(errors.StructuralError); ok {
266 // Skip unreadable, badly-formatted keys
267 lastUnsupportedError = err
268 err = readToNextPublicKey(packets)
269 }
270 if err == io.EOF {
271 err = nil
272 break
273 }
274 if err != nil {
275 el = nil
276 break
277 }
278 } else {
279 el = append(el, e)
280 }
281 }
282
283 if len(el) == 0 && err == nil {
284 err = lastUnsupportedError
285 }
286 return
287}
288
289// readToNextPublicKey reads packets until the start of the entity and leaves
290// the first packet of the new entity in the Reader.
291func readToNextPublicKey(packets *packet.Reader) (err error) {
292 var p packet.Packet
293 for {
294 p, err = packets.Next()
295 if err == io.EOF {
296 return
297 } else if err != nil {
298 if _, ok := err.(errors.UnsupportedError); ok {
299 err = nil
300 continue
301 }
302 return
303 }
304
305 if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
306 packets.Unread(p)
307 return
308 }
309 }
310}
311
312// ReadEntity reads an entity (public key, identities, subkeys etc) from the
313// given Reader.
314func ReadEntity(packets *packet.Reader) (*Entity, error) {
315 e := new(Entity)
316 e.Identities = make(map[string]*Identity)
317
318 p, err := packets.Next()
319 if err != nil {
320 return nil, err
321 }
322
323 var ok bool
324 if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
325 if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
326 packets.Unread(p)
327 return nil, errors.StructuralError("first packet was not a public/private key")
328 } else {
329 e.PrimaryKey = &e.PrivateKey.PublicKey
330 }
331 }
332
333 if !e.PrimaryKey.PubKeyAlgo.CanSign() {
334 return nil, errors.StructuralError("primary key cannot be used for signatures")
335 }
336
337 var current *Identity
338 var revocations []*packet.Signature
339EachPacket:
340 for {
341 p, err := packets.Next()
342 if err == io.EOF {
343 break
344 } else if err != nil {
345 return nil, err
346 }
347
348 switch pkt := p.(type) {
349 case *packet.UserId:
350 current = new(Identity)
351 current.Name = pkt.Id
352 current.UserId = pkt
353 e.Identities[pkt.Id] = current
354
355 for {
356 p, err = packets.Next()
357 if err == io.EOF {
358 return nil, io.ErrUnexpectedEOF
359 } else if err != nil {
360 return nil, err
361 }
362
363 sig, ok := p.(*packet.Signature)
364 if !ok {
365 return nil, errors.StructuralError("user ID packet not followed by self-signature")
366 }
367
368 if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId {
369 if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
370 return nil, errors.StructuralError("user ID self-signature invalid: " + err.Error())
371 }
372 current.SelfSignature = sig
373 break
374 }
375 current.Signatures = append(current.Signatures, sig)
376 }
377 case *packet.Signature:
378 if pkt.SigType == packet.SigTypeKeyRevocation {
379 revocations = append(revocations, pkt)
380 } else if pkt.SigType == packet.SigTypeDirectSignature {
381 // TODO: RFC4880 5.2.1 permits signatures
382 // directly on keys (eg. to bind additional
383 // revocation keys).
384 } else if current == nil {
385 return nil, errors.StructuralError("signature packet found before user id packet")
386 } else {
387 current.Signatures = append(current.Signatures, pkt)
388 }
389 case *packet.PrivateKey:
390 if pkt.IsSubkey == false {
391 packets.Unread(p)
392 break EachPacket
393 }
394 err = addSubkey(e, packets, &pkt.PublicKey, pkt)
395 if err != nil {
396 return nil, err
397 }
398 case *packet.PublicKey:
399 if pkt.IsSubkey == false {
400 packets.Unread(p)
401 break EachPacket
402 }
403 err = addSubkey(e, packets, pkt, nil)
404 if err != nil {
405 return nil, err
406 }
407 default:
408 // we ignore unknown packets
409 }
410 }
411
412 if len(e.Identities) == 0 {
413 return nil, errors.StructuralError("entity without any identities")
414 }
415
416 for _, revocation := range revocations {
417 err = e.PrimaryKey.VerifyRevocationSignature(revocation)
418 if err == nil {
419 e.Revocations = append(e.Revocations, revocation)
420 } else {
421 // TODO: RFC 4880 5.2.3.15 defines revocation keys.
422 return nil, errors.StructuralError("revocation signature signed by alternate key")
423 }
424 }
425
426 return e, nil
427}
428
429func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
430 var subKey Subkey
431 subKey.PublicKey = pub
432 subKey.PrivateKey = priv
433 p, err := packets.Next()
434 if err == io.EOF {
435 return io.ErrUnexpectedEOF
436 }
437 if err != nil {
438 return errors.StructuralError("subkey signature invalid: " + err.Error())
439 }
440 var ok bool
441 subKey.Sig, ok = p.(*packet.Signature)
442 if !ok {
443 return errors.StructuralError("subkey packet not followed by signature")
444 }
445 if subKey.Sig.SigType != packet.SigTypeSubkeyBinding && subKey.Sig.SigType != packet.SigTypeSubkeyRevocation {
446 return errors.StructuralError("subkey signature with wrong type")
447 }
448 err = e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, subKey.Sig)
449 if err != nil {
450 return errors.StructuralError("subkey signature invalid: " + err.Error())
451 }
452 e.Subkeys = append(e.Subkeys, subKey)
453 return nil
454}
455
456const defaultRSAKeyBits = 2048
457
458// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
459// single identity composed of the given full name, comment and email, any of
460// which may be empty but must not contain any of "()<>\x00".
461// If config is nil, sensible defaults will be used.
462func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
463 currentTime := config.Now()
464
465 bits := defaultRSAKeyBits
466 if config != nil && config.RSABits != 0 {
467 bits = config.RSABits
468 }
469
470 uid := packet.NewUserId(name, comment, email)
471 if uid == nil {
472 return nil, errors.InvalidArgumentError("user id field contained invalid characters")
473 }
474 signingPriv, err := rsa.GenerateKey(config.Random(), bits)
475 if err != nil {
476 return nil, err
477 }
478 encryptingPriv, err := rsa.GenerateKey(config.Random(), bits)
479 if err != nil {
480 return nil, err
481 }
482
483 e := &Entity{
484 PrimaryKey: packet.NewRSAPublicKey(currentTime, &signingPriv.PublicKey),
485 PrivateKey: packet.NewRSAPrivateKey(currentTime, signingPriv),
486 Identities: make(map[string]*Identity),
487 }
488 isPrimaryId := true
489 e.Identities[uid.Id] = &Identity{
490 Name: uid.Name,
491 UserId: uid,
492 SelfSignature: &packet.Signature{
493 CreationTime: currentTime,
494 SigType: packet.SigTypePositiveCert,
495 PubKeyAlgo: packet.PubKeyAlgoRSA,
496 Hash: config.Hash(),
497 IsPrimaryId: &isPrimaryId,
498 FlagsValid: true,
499 FlagSign: true,
500 FlagCertify: true,
501 IssuerKeyId: &e.PrimaryKey.KeyId,
502 },
503 }
504
505 // If the user passes in a DefaultHash via packet.Config,
506 // set the PreferredHash for the SelfSignature.
507 if config != nil && config.DefaultHash != 0 {
508 e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)}
509 }
510
511 e.Subkeys = make([]Subkey, 1)
512 e.Subkeys[0] = Subkey{
513 PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),
514 PrivateKey: packet.NewRSAPrivateKey(currentTime, encryptingPriv),
515 Sig: &packet.Signature{
516 CreationTime: currentTime,
517 SigType: packet.SigTypeSubkeyBinding,
518 PubKeyAlgo: packet.PubKeyAlgoRSA,
519 Hash: config.Hash(),
520 FlagsValid: true,
521 FlagEncryptStorage: true,
522 FlagEncryptCommunications: true,
523 IssuerKeyId: &e.PrimaryKey.KeyId,
524 },
525 }
526 e.Subkeys[0].PublicKey.IsSubkey = true
527 e.Subkeys[0].PrivateKey.IsSubkey = true
528
529 return e, nil
530}
531
532// SerializePrivate serializes an Entity, including private key material, to
533// the given Writer. For now, it must only be used on an Entity returned from
534// NewEntity.
535// If config is nil, sensible defaults will be used.
536func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
537 err = e.PrivateKey.Serialize(w)
538 if err != nil {
539 return
540 }
541 for _, ident := range e.Identities {
542 err = ident.UserId.Serialize(w)
543 if err != nil {
544 return
545 }
546 err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
547 if err != nil {
548 return
549 }
550 err = ident.SelfSignature.Serialize(w)
551 if err != nil {
552 return
553 }
554 }
555 for _, subkey := range e.Subkeys {
556 err = subkey.PrivateKey.Serialize(w)
557 if err != nil {
558 return
559 }
560 err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
561 if err != nil {
562 return
563 }
564 err = subkey.Sig.Serialize(w)
565 if err != nil {
566 return
567 }
568 }
569 return nil
570}
571
572// Serialize writes the public part of the given Entity to w. (No private
573// key material will be output).
574func (e *Entity) Serialize(w io.Writer) error {
575 err := e.PrimaryKey.Serialize(w)
576 if err != nil {
577 return err
578 }
579 for _, ident := range e.Identities {
580 err = ident.UserId.Serialize(w)
581 if err != nil {
582 return err
583 }
584 err = ident.SelfSignature.Serialize(w)
585 if err != nil {
586 return err
587 }
588 for _, sig := range ident.Signatures {
589 err = sig.Serialize(w)
590 if err != nil {
591 return err
592 }
593 }
594 }
595 for _, subkey := range e.Subkeys {
596 err = subkey.PublicKey.Serialize(w)
597 if err != nil {
598 return err
599 }
600 err = subkey.Sig.Serialize(w)
601 if err != nil {
602 return err
603 }
604 }
605 return nil
606}
607
608// SignIdentity adds a signature to e, from signer, attesting that identity is
609// associated with e. The provided identity must already be an element of
610// e.Identities and the private key of signer must have been decrypted if
611// necessary.
612// If config is nil, sensible defaults will be used.
613func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
614 if signer.PrivateKey == nil {
615 return errors.InvalidArgumentError("signing Entity must have a private key")
616 }
617 if signer.PrivateKey.Encrypted {
618 return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
619 }
620 ident, ok := e.Identities[identity]
621 if !ok {
622 return errors.InvalidArgumentError("given identity string not found in Entity")
623 }
624
625 sig := &packet.Signature{
626 SigType: packet.SigTypeGenericCert,
627 PubKeyAlgo: signer.PrivateKey.PubKeyAlgo,
628 Hash: config.Hash(),
629 CreationTime: config.Now(),
630 IssuerKeyId: &signer.PrivateKey.KeyId,
631 }
632 if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil {
633 return err
634 }
635 ident.Signatures = append(ident.Signatures, sig)
636 return nil
637}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/compressed.go b/vendor/golang.org/x/crypto/openpgp/packet/compressed.go
new file mode 100644
index 0000000..e8f0b5c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/compressed.go
@@ -0,0 +1,123 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "compress/bzip2"
9 "compress/flate"
10 "compress/zlib"
11 "golang.org/x/crypto/openpgp/errors"
12 "io"
13 "strconv"
14)
15
16// Compressed represents a compressed OpenPGP packet. The decompressed contents
17// will contain more OpenPGP packets. See RFC 4880, section 5.6.
18type Compressed struct {
19 Body io.Reader
20}
21
22const (
23 NoCompression = flate.NoCompression
24 BestSpeed = flate.BestSpeed
25 BestCompression = flate.BestCompression
26 DefaultCompression = flate.DefaultCompression
27)
28
29// CompressionConfig contains compressor configuration settings.
30type CompressionConfig struct {
31 // Level is the compression level to use. It must be set to
32 // between -1 and 9, with -1 causing the compressor to use the
33 // default compression level, 0 causing the compressor to use
34 // no compression and 1 to 9 representing increasing (better,
35 // slower) compression levels. If Level is less than -1 or
36 // more then 9, a non-nil error will be returned during
37 // encryption. See the constants above for convenient common
38 // settings for Level.
39 Level int
40}
41
42func (c *Compressed) parse(r io.Reader) error {
43 var buf [1]byte
44 _, err := readFull(r, buf[:])
45 if err != nil {
46 return err
47 }
48
49 switch buf[0] {
50 case 1:
51 c.Body = flate.NewReader(r)
52 case 2:
53 c.Body, err = zlib.NewReader(r)
54 case 3:
55 c.Body = bzip2.NewReader(r)
56 default:
57 err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
58 }
59
60 return err
61}
62
63// compressedWriterCloser represents the serialized compression stream
64// header and the compressor. Its Close() method ensures that both the
65// compressor and serialized stream header are closed. Its Write()
66// method writes to the compressor.
67type compressedWriteCloser struct {
68 sh io.Closer // Stream Header
69 c io.WriteCloser // Compressor
70}
71
72func (cwc compressedWriteCloser) Write(p []byte) (int, error) {
73 return cwc.c.Write(p)
74}
75
76func (cwc compressedWriteCloser) Close() (err error) {
77 err = cwc.c.Close()
78 if err != nil {
79 return err
80 }
81
82 return cwc.sh.Close()
83}
84
85// SerializeCompressed serializes a compressed data packet to w and
86// returns a WriteCloser to which the literal data packets themselves
87// can be written and which MUST be closed on completion. If cc is
88// nil, sensible defaults will be used to configure the compression
89// algorithm.
90func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) {
91 compressed, err := serializeStreamHeader(w, packetTypeCompressed)
92 if err != nil {
93 return
94 }
95
96 _, err = compressed.Write([]byte{uint8(algo)})
97 if err != nil {
98 return
99 }
100
101 level := DefaultCompression
102 if cc != nil {
103 level = cc.Level
104 }
105
106 var compressor io.WriteCloser
107 switch algo {
108 case CompressionZIP:
109 compressor, err = flate.NewWriter(compressed, level)
110 case CompressionZLIB:
111 compressor, err = zlib.NewWriterLevel(compressed, level)
112 default:
113 s := strconv.Itoa(int(algo))
114 err = errors.UnsupportedError("Unsupported compression algorithm: " + s)
115 }
116 if err != nil {
117 return
118 }
119
120 literaldata = compressedWriteCloser{compressed, compressor}
121
122 return
123}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/config.go b/vendor/golang.org/x/crypto/openpgp/packet/config.go
new file mode 100644
index 0000000..c76eecc
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/config.go
@@ -0,0 +1,91 @@
1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "crypto"
9 "crypto/rand"
10 "io"
11 "time"
12)
13
14// Config collects a number of parameters along with sensible defaults.
15// A nil *Config is valid and results in all default values.
16type Config struct {
17 // Rand provides the source of entropy.
18 // If nil, the crypto/rand Reader is used.
19 Rand io.Reader
20 // DefaultHash is the default hash function to be used.
21 // If zero, SHA-256 is used.
22 DefaultHash crypto.Hash
23 // DefaultCipher is the cipher to be used.
24 // If zero, AES-128 is used.
25 DefaultCipher CipherFunction
26 // Time returns the current time as the number of seconds since the
27 // epoch. If Time is nil, time.Now is used.
28 Time func() time.Time
29 // DefaultCompressionAlgo is the compression algorithm to be
30 // applied to the plaintext before encryption. If zero, no
31 // compression is done.
32 DefaultCompressionAlgo CompressionAlgo
33 // CompressionConfig configures the compression settings.
34 CompressionConfig *CompressionConfig
35 // S2KCount is only used for symmetric encryption. It
36 // determines the strength of the passphrase stretching when
37 // the said passphrase is hashed to produce a key. S2KCount
38 // should be between 1024 and 65011712, inclusive. If Config
39 // is nil or S2KCount is 0, the value 65536 used. Not all
40 // values in the above range can be represented. S2KCount will
41 // be rounded up to the next representable value if it cannot
42 // be encoded exactly. When set, it is strongly encrouraged to
43 // use a value that is at least 65536. See RFC 4880 Section
44 // 3.7.1.3.
45 S2KCount int
46 // RSABits is the number of bits in new RSA keys made with NewEntity.
47 // If zero, then 2048 bit keys are created.
48 RSABits int
49}
50
51func (c *Config) Random() io.Reader {
52 if c == nil || c.Rand == nil {
53 return rand.Reader
54 }
55 return c.Rand
56}
57
58func (c *Config) Hash() crypto.Hash {
59 if c == nil || uint(c.DefaultHash) == 0 {
60 return crypto.SHA256
61 }
62 return c.DefaultHash
63}
64
65func (c *Config) Cipher() CipherFunction {
66 if c == nil || uint8(c.DefaultCipher) == 0 {
67 return CipherAES128
68 }
69 return c.DefaultCipher
70}
71
72func (c *Config) Now() time.Time {
73 if c == nil || c.Time == nil {
74 return time.Now()
75 }
76 return c.Time()
77}
78
79func (c *Config) Compression() CompressionAlgo {
80 if c == nil {
81 return CompressionNone
82 }
83 return c.DefaultCompressionAlgo
84}
85
86func (c *Config) PasswordHashIterations() int {
87 if c == nil || c.S2KCount == 0 {
88 return 0
89 }
90 return c.S2KCount
91}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go
new file mode 100644
index 0000000..266840d
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go
@@ -0,0 +1,199 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "crypto/rsa"
9 "encoding/binary"
10 "io"
11 "math/big"
12 "strconv"
13
14 "golang.org/x/crypto/openpgp/elgamal"
15 "golang.org/x/crypto/openpgp/errors"
16)
17
18const encryptedKeyVersion = 3
19
20// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
21// section 5.1.
22type EncryptedKey struct {
23 KeyId uint64
24 Algo PublicKeyAlgorithm
25 CipherFunc CipherFunction // only valid after a successful Decrypt
26 Key []byte // only valid after a successful Decrypt
27
28 encryptedMPI1, encryptedMPI2 parsedMPI
29}
30
31func (e *EncryptedKey) parse(r io.Reader) (err error) {
32 var buf [10]byte
33 _, err = readFull(r, buf[:])
34 if err != nil {
35 return
36 }
37 if buf[0] != encryptedKeyVersion {
38 return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
39 }
40 e.KeyId = binary.BigEndian.Uint64(buf[1:9])
41 e.Algo = PublicKeyAlgorithm(buf[9])
42 switch e.Algo {
43 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
44 e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
45 case PubKeyAlgoElGamal:
46 e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
47 if err != nil {
48 return
49 }
50 e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r)
51 }
52 _, err = consumeAll(r)
53 return
54}
55
56func checksumKeyMaterial(key []byte) uint16 {
57 var checksum uint16
58 for _, v := range key {
59 checksum += uint16(v)
60 }
61 return checksum
62}
63
64// Decrypt decrypts an encrypted session key with the given private key. The
65// private key must have been decrypted first.
66// If config is nil, sensible defaults will be used.
67func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
68 var err error
69 var b []byte
70
71 // TODO(agl): use session key decryption routines here to avoid
72 // padding oracle attacks.
73 switch priv.PubKeyAlgo {
74 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
75 b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes)
76 case PubKeyAlgoElGamal:
77 c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
78 c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)
79 b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
80 default:
81 err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
82 }
83
84 if err != nil {
85 return err
86 }
87
88 e.CipherFunc = CipherFunction(b[0])
89 e.Key = b[1 : len(b)-2]
90 expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
91 checksum := checksumKeyMaterial(e.Key)
92 if checksum != expectedChecksum {
93 return errors.StructuralError("EncryptedKey checksum incorrect")
94 }
95
96 return nil
97}
98
99// Serialize writes the encrypted key packet, e, to w.
100func (e *EncryptedKey) Serialize(w io.Writer) error {
101 var mpiLen int
102 switch e.Algo {
103 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
104 mpiLen = 2 + len(e.encryptedMPI1.bytes)
105 case PubKeyAlgoElGamal:
106 mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes)
107 default:
108 return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo)))
109 }
110
111 serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen)
112
113 w.Write([]byte{encryptedKeyVersion})
114 binary.Write(w, binary.BigEndian, e.KeyId)
115 w.Write([]byte{byte(e.Algo)})
116
117 switch e.Algo {
118 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
119 writeMPIs(w, e.encryptedMPI1)
120 case PubKeyAlgoElGamal:
121 writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2)
122 default:
123 panic("internal error")
124 }
125
126 return nil
127}
128
129// SerializeEncryptedKey serializes an encrypted key packet to w that contains
130// key, encrypted to pub.
131// If config is nil, sensible defaults will be used.
132func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
133 var buf [10]byte
134 buf[0] = encryptedKeyVersion
135 binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
136 buf[9] = byte(pub.PubKeyAlgo)
137
138 keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */)
139 keyBlock[0] = byte(cipherFunc)
140 copy(keyBlock[1:], key)
141 checksum := checksumKeyMaterial(key)
142 keyBlock[1+len(key)] = byte(checksum >> 8)
143 keyBlock[1+len(key)+1] = byte(checksum)
144
145 switch pub.PubKeyAlgo {
146 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
147 return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
148 case PubKeyAlgoElGamal:
149 return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
150 case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
151 return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
152 }
153
154 return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
155}
156
157func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error {
158 cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
159 if err != nil {
160 return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
161 }
162
163 packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
164
165 err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
166 if err != nil {
167 return err
168 }
169 _, err = w.Write(header[:])
170 if err != nil {
171 return err
172 }
173 return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
174}
175
176func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
177 c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
178 if err != nil {
179 return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
180 }
181
182 packetLen := 10 /* header length */
183 packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
184 packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
185
186 err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
187 if err != nil {
188 return err
189 }
190 _, err = w.Write(header[:])
191 if err != nil {
192 return err
193 }
194 err = writeBig(w, c1)
195 if err != nil {
196 return err
197 }
198 return writeBig(w, c2)
199}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/literal.go b/vendor/golang.org/x/crypto/openpgp/packet/literal.go
new file mode 100644
index 0000000..1a9ec6e
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/literal.go
@@ -0,0 +1,89 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "encoding/binary"
9 "io"
10)
11
12// LiteralData represents an encrypted file. See RFC 4880, section 5.9.
13type LiteralData struct {
14 IsBinary bool
15 FileName string
16 Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined.
17 Body io.Reader
18}
19
20// ForEyesOnly returns whether the contents of the LiteralData have been marked
21// as especially sensitive.
22func (l *LiteralData) ForEyesOnly() bool {
23 return l.FileName == "_CONSOLE"
24}
25
26func (l *LiteralData) parse(r io.Reader) (err error) {
27 var buf [256]byte
28
29 _, err = readFull(r, buf[:2])
30 if err != nil {
31 return
32 }
33
34 l.IsBinary = buf[0] == 'b'
35 fileNameLen := int(buf[1])
36
37 _, err = readFull(r, buf[:fileNameLen])
38 if err != nil {
39 return
40 }
41
42 l.FileName = string(buf[:fileNameLen])
43
44 _, err = readFull(r, buf[:4])
45 if err != nil {
46 return
47 }
48
49 l.Time = binary.BigEndian.Uint32(buf[:4])
50 l.Body = r
51 return
52}
53
54// SerializeLiteral serializes a literal data packet to w and returns a
55// WriteCloser to which the data itself can be written and which MUST be closed
56// on completion. The fileName is truncated to 255 bytes.
57func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) {
58 var buf [4]byte
59 buf[0] = 't'
60 if isBinary {
61 buf[0] = 'b'
62 }
63 if len(fileName) > 255 {
64 fileName = fileName[:255]
65 }
66 buf[1] = byte(len(fileName))
67
68 inner, err := serializeStreamHeader(w, packetTypeLiteralData)
69 if err != nil {
70 return
71 }
72
73 _, err = inner.Write(buf[:2])
74 if err != nil {
75 return
76 }
77 _, err = inner.Write([]byte(fileName))
78 if err != nil {
79 return
80 }
81 binary.BigEndian.PutUint32(buf[:], time)
82 _, err = inner.Write(buf[:])
83 if err != nil {
84 return
85 }
86
87 plaintext = inner
88 return
89}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go
new file mode 100644
index 0000000..ce2a33a
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go
@@ -0,0 +1,143 @@
1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
6
7package packet
8
9import (
10 "crypto/cipher"
11)
12
13type ocfbEncrypter struct {
14 b cipher.Block
15 fre []byte
16 outUsed int
17}
18
19// An OCFBResyncOption determines if the "resynchronization step" of OCFB is
20// performed.
21type OCFBResyncOption bool
22
23const (
24 OCFBResync OCFBResyncOption = true
25 OCFBNoResync OCFBResyncOption = false
26)
27
28// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's
29// cipher feedback mode using the given cipher.Block, and an initial amount of
30// ciphertext. randData must be random bytes and be the same length as the
31// cipher.Block's block size. Resync determines if the "resynchronization step"
32// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on
33// this point.
34func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) {
35 blockSize := block.BlockSize()
36 if len(randData) != blockSize {
37 return nil, nil
38 }
39
40 x := &ocfbEncrypter{
41 b: block,
42 fre: make([]byte, blockSize),
43 outUsed: 0,
44 }
45 prefix := make([]byte, blockSize+2)
46
47 block.Encrypt(x.fre, x.fre)
48 for i := 0; i < blockSize; i++ {
49 prefix[i] = randData[i] ^ x.fre[i]
50 }
51
52 block.Encrypt(x.fre, prefix[:blockSize])
53 prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
54 prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
55
56 if resync {
57 block.Encrypt(x.fre, prefix[2:])
58 } else {
59 x.fre[0] = prefix[blockSize]
60 x.fre[1] = prefix[blockSize+1]
61 x.outUsed = 2
62 }
63 return x, prefix
64}
65
66func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
67 for i := 0; i < len(src); i++ {
68 if x.outUsed == len(x.fre) {
69 x.b.Encrypt(x.fre, x.fre)
70 x.outUsed = 0
71 }
72
73 x.fre[x.outUsed] ^= src[i]
74 dst[i] = x.fre[x.outUsed]
75 x.outUsed++
76 }
77}
78
79type ocfbDecrypter struct {
80 b cipher.Block
81 fre []byte
82 outUsed int
83}
84
85// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's
86// cipher feedback mode using the given cipher.Block. Prefix must be the first
87// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's
88// block size. If an incorrect key is detected then nil is returned. On
89// successful exit, blockSize+2 bytes of decrypted data are written into
90// prefix. Resync determines if the "resynchronization step" from RFC 4880,
91// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point.
92func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream {
93 blockSize := block.BlockSize()
94 if len(prefix) != blockSize+2 {
95 return nil
96 }
97
98 x := &ocfbDecrypter{
99 b: block,
100 fre: make([]byte, blockSize),
101 outUsed: 0,
102 }
103 prefixCopy := make([]byte, len(prefix))
104 copy(prefixCopy, prefix)
105
106 block.Encrypt(x.fre, x.fre)
107 for i := 0; i < blockSize; i++ {
108 prefixCopy[i] ^= x.fre[i]
109 }
110
111 block.Encrypt(x.fre, prefix[:blockSize])
112 prefixCopy[blockSize] ^= x.fre[0]
113 prefixCopy[blockSize+1] ^= x.fre[1]
114
115 if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
116 prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
117 return nil
118 }
119
120 if resync {
121 block.Encrypt(x.fre, prefix[2:])
122 } else {
123 x.fre[0] = prefix[blockSize]
124 x.fre[1] = prefix[blockSize+1]
125 x.outUsed = 2
126 }
127 copy(prefix, prefixCopy)
128 return x
129}
130
131func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
132 for i := 0; i < len(src); i++ {
133 if x.outUsed == len(x.fre) {
134 x.b.Encrypt(x.fre, x.fre)
135 x.outUsed = 0
136 }
137
138 c := src[i]
139 dst[i] = x.fre[x.outUsed] ^ src[i]
140 x.fre[x.outUsed] = c
141 x.outUsed++
142 }
143}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go b/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go
new file mode 100644
index 0000000..1713503
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go
@@ -0,0 +1,73 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "crypto"
9 "encoding/binary"
10 "golang.org/x/crypto/openpgp/errors"
11 "golang.org/x/crypto/openpgp/s2k"
12 "io"
13 "strconv"
14)
15
16// OnePassSignature represents a one-pass signature packet. See RFC 4880,
17// section 5.4.
18type OnePassSignature struct {
19 SigType SignatureType
20 Hash crypto.Hash
21 PubKeyAlgo PublicKeyAlgorithm
22 KeyId uint64
23 IsLast bool
24}
25
26const onePassSignatureVersion = 3
27
28func (ops *OnePassSignature) parse(r io.Reader) (err error) {
29 var buf [13]byte
30
31 _, err = readFull(r, buf[:])
32 if err != nil {
33 return
34 }
35 if buf[0] != onePassSignatureVersion {
36 err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
37 }
38
39 var ok bool
40 ops.Hash, ok = s2k.HashIdToHash(buf[2])
41 if !ok {
42 return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
43 }
44
45 ops.SigType = SignatureType(buf[1])
46 ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
47 ops.KeyId = binary.BigEndian.Uint64(buf[4:12])
48 ops.IsLast = buf[12] != 0
49 return
50}
51
52// Serialize marshals the given OnePassSignature to w.
53func (ops *OnePassSignature) Serialize(w io.Writer) error {
54 var buf [13]byte
55 buf[0] = onePassSignatureVersion
56 buf[1] = uint8(ops.SigType)
57 var ok bool
58 buf[2], ok = s2k.HashToHashId(ops.Hash)
59 if !ok {
60 return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
61 }
62 buf[3] = uint8(ops.PubKeyAlgo)
63 binary.BigEndian.PutUint64(buf[4:12], ops.KeyId)
64 if ops.IsLast {
65 buf[12] = 1
66 }
67
68 if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil {
69 return err
70 }
71 _, err := w.Write(buf[:])
72 return err
73}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/opaque.go b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go
new file mode 100644
index 0000000..456d807
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go
@@ -0,0 +1,162 @@
1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "bytes"
9 "io"
10 "io/ioutil"
11
12 "golang.org/x/crypto/openpgp/errors"
13)
14
15// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is
16// useful for splitting and storing the original packet contents separately,
17// handling unsupported packet types or accessing parts of the packet not yet
18// implemented by this package.
19type OpaquePacket struct {
20 // Packet type
21 Tag uint8
22 // Reason why the packet was parsed opaquely
23 Reason error
24 // Binary contents of the packet data
25 Contents []byte
26}
27
28func (op *OpaquePacket) parse(r io.Reader) (err error) {
29 op.Contents, err = ioutil.ReadAll(r)
30 return
31}
32
33// Serialize marshals the packet to a writer in its original form, including
34// the packet header.
35func (op *OpaquePacket) Serialize(w io.Writer) (err error) {
36 err = serializeHeader(w, packetType(op.Tag), len(op.Contents))
37 if err == nil {
38 _, err = w.Write(op.Contents)
39 }
40 return
41}
42
43// Parse attempts to parse the opaque contents into a structure supported by
44// this package. If the packet is not known then the result will be another
45// OpaquePacket.
46func (op *OpaquePacket) Parse() (p Packet, err error) {
47 hdr := bytes.NewBuffer(nil)
48 err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents))
49 if err != nil {
50 op.Reason = err
51 return op, err
52 }
53 p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents)))
54 if err != nil {
55 op.Reason = err
56 p = op
57 }
58 return
59}
60
61// OpaqueReader reads OpaquePackets from an io.Reader.
62type OpaqueReader struct {
63 r io.Reader
64}
65
66func NewOpaqueReader(r io.Reader) *OpaqueReader {
67 return &OpaqueReader{r: r}
68}
69
70// Read the next OpaquePacket.
71func (or *OpaqueReader) Next() (op *OpaquePacket, err error) {
72 tag, _, contents, err := readHeader(or.r)
73 if err != nil {
74 return
75 }
76 op = &OpaquePacket{Tag: uint8(tag), Reason: err}
77 err = op.parse(contents)
78 if err != nil {
79 consumeAll(contents)
80 }
81 return
82}
83
84// OpaqueSubpacket represents an unparsed OpenPGP subpacket,
85// as found in signature and user attribute packets.
86type OpaqueSubpacket struct {
87 SubType uint8
88 Contents []byte
89}
90
91// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from
92// their byte representation.
93func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) {
94 var (
95 subHeaderLen int
96 subPacket *OpaqueSubpacket
97 )
98 for len(contents) > 0 {
99 subHeaderLen, subPacket, err = nextSubpacket(contents)
100 if err != nil {
101 break
102 }
103 result = append(result, subPacket)
104 contents = contents[subHeaderLen+len(subPacket.Contents):]
105 }
106 return
107}
108
109func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) {
110 // RFC 4880, section 5.2.3.1
111 var subLen uint32
112 if len(contents) < 1 {
113 goto Truncated
114 }
115 subPacket = &OpaqueSubpacket{}
116 switch {
117 case contents[0] < 192:
118 subHeaderLen = 2 // 1 length byte, 1 subtype byte
119 if len(contents) < subHeaderLen {
120 goto Truncated
121 }
122 subLen = uint32(contents[0])
123 contents = contents[1:]
124 case contents[0] < 255:
125 subHeaderLen = 3 // 2 length bytes, 1 subtype
126 if len(contents) < subHeaderLen {
127 goto Truncated
128 }
129 subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192
130 contents = contents[2:]
131 default:
132 subHeaderLen = 6 // 5 length bytes, 1 subtype
133 if len(contents) < subHeaderLen {
134 goto Truncated
135 }
136 subLen = uint32(contents[1])<<24 |
137 uint32(contents[2])<<16 |
138 uint32(contents[3])<<8 |
139 uint32(contents[4])
140 contents = contents[5:]
141 }
142 if subLen > uint32(len(contents)) || subLen == 0 {
143 goto Truncated
144 }
145 subPacket.SubType = contents[0]
146 subPacket.Contents = contents[1:subLen]
147 return
148Truncated:
149 err = errors.StructuralError("subpacket truncated")
150 return
151}
152
153func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) {
154 buf := make([]byte, 6)
155 n := serializeSubpacketLength(buf, len(osp.Contents)+1)
156 buf[n] = osp.SubType
157 if _, err = w.Write(buf[:n+1]); err != nil {
158 return
159 }
160 _, err = w.Write(osp.Contents)
161 return
162}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet.go b/vendor/golang.org/x/crypto/openpgp/packet/packet.go
new file mode 100644
index 0000000..3eded93
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/packet.go
@@ -0,0 +1,537 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package packet implements parsing and serialization of OpenPGP packets, as
6// specified in RFC 4880.
7package packet // import "golang.org/x/crypto/openpgp/packet"
8
9import (
10 "bufio"
11 "crypto/aes"
12 "crypto/cipher"
13 "crypto/des"
14 "golang.org/x/crypto/cast5"
15 "golang.org/x/crypto/openpgp/errors"
16 "io"
17 "math/big"
18)
19
20// readFull is the same as io.ReadFull except that reading zero bytes returns
21// ErrUnexpectedEOF rather than EOF.
22func readFull(r io.Reader, buf []byte) (n int, err error) {
23 n, err = io.ReadFull(r, buf)
24 if err == io.EOF {
25 err = io.ErrUnexpectedEOF
26 }
27 return
28}
29
30// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2.
31func readLength(r io.Reader) (length int64, isPartial bool, err error) {
32 var buf [4]byte
33 _, err = readFull(r, buf[:1])
34 if err != nil {
35 return
36 }
37 switch {
38 case buf[0] < 192:
39 length = int64(buf[0])
40 case buf[0] < 224:
41 length = int64(buf[0]-192) << 8
42 _, err = readFull(r, buf[0:1])
43 if err != nil {
44 return
45 }
46 length += int64(buf[0]) + 192
47 case buf[0] < 255:
48 length = int64(1) << (buf[0] & 0x1f)
49 isPartial = true
50 default:
51 _, err = readFull(r, buf[0:4])
52 if err != nil {
53 return
54 }
55 length = int64(buf[0])<<24 |
56 int64(buf[1])<<16 |
57 int64(buf[2])<<8 |
58 int64(buf[3])
59 }
60 return
61}
62
63// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths.
64// The continuation lengths are parsed and removed from the stream and EOF is
65// returned at the end of the packet. See RFC 4880, section 4.2.2.4.
66type partialLengthReader struct {
67 r io.Reader
68 remaining int64
69 isPartial bool
70}
71
72func (r *partialLengthReader) Read(p []byte) (n int, err error) {
73 for r.remaining == 0 {
74 if !r.isPartial {
75 return 0, io.EOF
76 }
77 r.remaining, r.isPartial, err = readLength(r.r)
78 if err != nil {
79 return 0, err
80 }
81 }
82
83 toRead := int64(len(p))
84 if toRead > r.remaining {
85 toRead = r.remaining
86 }
87
88 n, err = r.r.Read(p[:int(toRead)])
89 r.remaining -= int64(n)
90 if n < int(toRead) && err == io.EOF {
91 err = io.ErrUnexpectedEOF
92 }
93 return
94}
95
96// partialLengthWriter writes a stream of data using OpenPGP partial lengths.
97// See RFC 4880, section 4.2.2.4.
98type partialLengthWriter struct {
99 w io.WriteCloser
100 lengthByte [1]byte
101}
102
103func (w *partialLengthWriter) Write(p []byte) (n int, err error) {
104 for len(p) > 0 {
105 for power := uint(14); power < 32; power-- {
106 l := 1 << power
107 if len(p) >= l {
108 w.lengthByte[0] = 224 + uint8(power)
109 _, err = w.w.Write(w.lengthByte[:])
110 if err != nil {
111 return
112 }
113 var m int
114 m, err = w.w.Write(p[:l])
115 n += m
116 if err != nil {
117 return
118 }
119 p = p[l:]
120 break
121 }
122 }
123 }
124 return
125}
126
127func (w *partialLengthWriter) Close() error {
128 w.lengthByte[0] = 0
129 _, err := w.w.Write(w.lengthByte[:])
130 if err != nil {
131 return err
132 }
133 return w.w.Close()
134}
135
136// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the
137// underlying Reader returns EOF before the limit has been reached.
138type spanReader struct {
139 r io.Reader
140 n int64
141}
142
143func (l *spanReader) Read(p []byte) (n int, err error) {
144 if l.n <= 0 {
145 return 0, io.EOF
146 }
147 if int64(len(p)) > l.n {
148 p = p[0:l.n]
149 }
150 n, err = l.r.Read(p)
151 l.n -= int64(n)
152 if l.n > 0 && err == io.EOF {
153 err = io.ErrUnexpectedEOF
154 }
155 return
156}
157
158// readHeader parses a packet header and returns an io.Reader which will return
159// the contents of the packet. See RFC 4880, section 4.2.
160func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) {
161 var buf [4]byte
162 _, err = io.ReadFull(r, buf[:1])
163 if err != nil {
164 return
165 }
166 if buf[0]&0x80 == 0 {
167 err = errors.StructuralError("tag byte does not have MSB set")
168 return
169 }
170 if buf[0]&0x40 == 0 {
171 // Old format packet
172 tag = packetType((buf[0] & 0x3f) >> 2)
173 lengthType := buf[0] & 3
174 if lengthType == 3 {
175 length = -1
176 contents = r
177 return
178 }
179 lengthBytes := 1 << lengthType
180 _, err = readFull(r, buf[0:lengthBytes])
181 if err != nil {
182 return
183 }
184 for i := 0; i < lengthBytes; i++ {
185 length <<= 8
186 length |= int64(buf[i])
187 }
188 contents = &spanReader{r, length}
189 return
190 }
191
192 // New format packet
193 tag = packetType(buf[0] & 0x3f)
194 length, isPartial, err := readLength(r)
195 if err != nil {
196 return
197 }
198 if isPartial {
199 contents = &partialLengthReader{
200 remaining: length,
201 isPartial: true,
202 r: r,
203 }
204 length = -1
205 } else {
206 contents = &spanReader{r, length}
207 }
208 return
209}
210
211// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section
212// 4.2.
213func serializeHeader(w io.Writer, ptype packetType, length int) (err error) {
214 var buf [6]byte
215 var n int
216
217 buf[0] = 0x80 | 0x40 | byte(ptype)
218 if length < 192 {
219 buf[1] = byte(length)
220 n = 2
221 } else if length < 8384 {
222 length -= 192
223 buf[1] = 192 + byte(length>>8)
224 buf[2] = byte(length)
225 n = 3
226 } else {
227 buf[1] = 255
228 buf[2] = byte(length >> 24)
229 buf[3] = byte(length >> 16)
230 buf[4] = byte(length >> 8)
231 buf[5] = byte(length)
232 n = 6
233 }
234
235 _, err = w.Write(buf[:n])
236 return
237}
238
239// serializeStreamHeader writes an OpenPGP packet header to w where the
240// length of the packet is unknown. It returns a io.WriteCloser which can be
241// used to write the contents of the packet. See RFC 4880, section 4.2.
242func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) {
243 var buf [1]byte
244 buf[0] = 0x80 | 0x40 | byte(ptype)
245 _, err = w.Write(buf[:])
246 if err != nil {
247 return
248 }
249 out = &partialLengthWriter{w: w}
250 return
251}
252
253// Packet represents an OpenPGP packet. Users are expected to try casting
254// instances of this interface to specific packet types.
255type Packet interface {
256 parse(io.Reader) error
257}
258
259// consumeAll reads from the given Reader until error, returning the number of
260// bytes read.
261func consumeAll(r io.Reader) (n int64, err error) {
262 var m int
263 var buf [1024]byte
264
265 for {
266 m, err = r.Read(buf[:])
267 n += int64(m)
268 if err == io.EOF {
269 err = nil
270 return
271 }
272 if err != nil {
273 return
274 }
275 }
276}
277
278// packetType represents the numeric ids of the different OpenPGP packet types. See
279// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2
280type packetType uint8
281
282const (
283 packetTypeEncryptedKey packetType = 1
284 packetTypeSignature packetType = 2
285 packetTypeSymmetricKeyEncrypted packetType = 3
286 packetTypeOnePassSignature packetType = 4
287 packetTypePrivateKey packetType = 5
288 packetTypePublicKey packetType = 6
289 packetTypePrivateSubkey packetType = 7
290 packetTypeCompressed packetType = 8
291 packetTypeSymmetricallyEncrypted packetType = 9
292 packetTypeLiteralData packetType = 11
293 packetTypeUserId packetType = 13
294 packetTypePublicSubkey packetType = 14
295 packetTypeUserAttribute packetType = 17
296 packetTypeSymmetricallyEncryptedMDC packetType = 18
297)
298
299// peekVersion detects the version of a public key packet about to
300// be read. A bufio.Reader at the original position of the io.Reader
301// is returned.
302func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) {
303 bufr = bufio.NewReader(r)
304 var verBuf []byte
305 if verBuf, err = bufr.Peek(1); err != nil {
306 return
307 }
308 ver = verBuf[0]
309 return
310}
311
312// Read reads a single OpenPGP packet from the given io.Reader. If there is an
313// error parsing a packet, the whole packet is consumed from the input.
314func Read(r io.Reader) (p Packet, err error) {
315 tag, _, contents, err := readHeader(r)
316 if err != nil {
317 return
318 }
319
320 switch tag {
321 case packetTypeEncryptedKey:
322 p = new(EncryptedKey)
323 case packetTypeSignature:
324 var version byte
325 // Detect signature version
326 if contents, version, err = peekVersion(contents); err != nil {
327 return
328 }
329 if version < 4 {
330 p = new(SignatureV3)
331 } else {
332 p = new(Signature)
333 }
334 case packetTypeSymmetricKeyEncrypted:
335 p = new(SymmetricKeyEncrypted)
336 case packetTypeOnePassSignature:
337 p = new(OnePassSignature)
338 case packetTypePrivateKey, packetTypePrivateSubkey:
339 pk := new(PrivateKey)
340 if tag == packetTypePrivateSubkey {
341 pk.IsSubkey = true
342 }
343 p = pk
344 case packetTypePublicKey, packetTypePublicSubkey:
345 var version byte
346 if contents, version, err = peekVersion(contents); err != nil {
347 return
348 }
349 isSubkey := tag == packetTypePublicSubkey
350 if version < 4 {
351 p = &PublicKeyV3{IsSubkey: isSubkey}
352 } else {
353 p = &PublicKey{IsSubkey: isSubkey}
354 }
355 case packetTypeCompressed:
356 p = new(Compressed)
357 case packetTypeSymmetricallyEncrypted:
358 p = new(SymmetricallyEncrypted)
359 case packetTypeLiteralData:
360 p = new(LiteralData)
361 case packetTypeUserId:
362 p = new(UserId)
363 case packetTypeUserAttribute:
364 p = new(UserAttribute)
365 case packetTypeSymmetricallyEncryptedMDC:
366 se := new(SymmetricallyEncrypted)
367 se.MDC = true
368 p = se
369 default:
370 err = errors.UnknownPacketTypeError(tag)
371 }
372 if p != nil {
373 err = p.parse(contents)
374 }
375 if err != nil {
376 consumeAll(contents)
377 }
378 return
379}
380
381// SignatureType represents the different semantic meanings of an OpenPGP
382// signature. See RFC 4880, section 5.2.1.
383type SignatureType uint8
384
385const (
386 SigTypeBinary SignatureType = 0
387 SigTypeText = 1
388 SigTypeGenericCert = 0x10
389 SigTypePersonaCert = 0x11
390 SigTypeCasualCert = 0x12
391 SigTypePositiveCert = 0x13
392 SigTypeSubkeyBinding = 0x18
393 SigTypePrimaryKeyBinding = 0x19
394 SigTypeDirectSignature = 0x1F
395 SigTypeKeyRevocation = 0x20
396 SigTypeSubkeyRevocation = 0x28
397)
398
399// PublicKeyAlgorithm represents the different public key system specified for
400// OpenPGP. See
401// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12
402type PublicKeyAlgorithm uint8
403
404const (
405 PubKeyAlgoRSA PublicKeyAlgorithm = 1
406 PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
407 PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3
408 PubKeyAlgoElGamal PublicKeyAlgorithm = 16
409 PubKeyAlgoDSA PublicKeyAlgorithm = 17
410 // RFC 6637, Section 5.
411 PubKeyAlgoECDH PublicKeyAlgorithm = 18
412 PubKeyAlgoECDSA PublicKeyAlgorithm = 19
413)
414
415// CanEncrypt returns true if it's possible to encrypt a message to a public
416// key of the given type.
417func (pka PublicKeyAlgorithm) CanEncrypt() bool {
418 switch pka {
419 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal:
420 return true
421 }
422 return false
423}
424
425// CanSign returns true if it's possible for a public key of the given type to
426// sign a message.
427func (pka PublicKeyAlgorithm) CanSign() bool {
428 switch pka {
429 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
430 return true
431 }
432 return false
433}
434
435// CipherFunction represents the different block ciphers specified for OpenPGP. See
436// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
437type CipherFunction uint8
438
439const (
440 Cipher3DES CipherFunction = 2
441 CipherCAST5 CipherFunction = 3
442 CipherAES128 CipherFunction = 7
443 CipherAES192 CipherFunction = 8
444 CipherAES256 CipherFunction = 9
445)
446
447// KeySize returns the key size, in bytes, of cipher.
448func (cipher CipherFunction) KeySize() int {
449 switch cipher {
450 case Cipher3DES:
451 return 24
452 case CipherCAST5:
453 return cast5.KeySize
454 case CipherAES128:
455 return 16
456 case CipherAES192:
457 return 24
458 case CipherAES256:
459 return 32
460 }
461 return 0
462}
463
464// blockSize returns the block size, in bytes, of cipher.
465func (cipher CipherFunction) blockSize() int {
466 switch cipher {
467 case Cipher3DES:
468 return des.BlockSize
469 case CipherCAST5:
470 return 8
471 case CipherAES128, CipherAES192, CipherAES256:
472 return 16
473 }
474 return 0
475}
476
477// new returns a fresh instance of the given cipher.
478func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
479 switch cipher {
480 case Cipher3DES:
481 block, _ = des.NewTripleDESCipher(key)
482 case CipherCAST5:
483 block, _ = cast5.NewCipher(key)
484 case CipherAES128, CipherAES192, CipherAES256:
485 block, _ = aes.NewCipher(key)
486 }
487 return
488}
489
490// readMPI reads a big integer from r. The bit length returned is the bit
491// length that was specified in r. This is preserved so that the integer can be
492// reserialized exactly.
493func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) {
494 var buf [2]byte
495 _, err = readFull(r, buf[0:])
496 if err != nil {
497 return
498 }
499 bitLength = uint16(buf[0])<<8 | uint16(buf[1])
500 numBytes := (int(bitLength) + 7) / 8
501 mpi = make([]byte, numBytes)
502 _, err = readFull(r, mpi)
503 return
504}
505
506// mpiLength returns the length of the given *big.Int when serialized as an
507// MPI.
508func mpiLength(n *big.Int) (mpiLengthInBytes int) {
509 mpiLengthInBytes = 2 /* MPI length */
510 mpiLengthInBytes += (n.BitLen() + 7) / 8
511 return
512}
513
514// writeMPI serializes a big integer to w.
515func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) {
516 _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
517 if err == nil {
518 _, err = w.Write(mpiBytes)
519 }
520 return
521}
522
523// writeBig serializes a *big.Int to w.
524func writeBig(w io.Writer, i *big.Int) error {
525 return writeMPI(w, uint16(i.BitLen()), i.Bytes())
526}
527
528// CompressionAlgo Represents the different compression algorithms
529// supported by OpenPGP (except for BZIP2, which is not currently
530// supported). See Section 9.3 of RFC 4880.
531type CompressionAlgo uint8
532
533const (
534 CompressionNone CompressionAlgo = 0
535 CompressionZIP CompressionAlgo = 1
536 CompressionZLIB CompressionAlgo = 2
537)
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/private_key.go b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go
new file mode 100644
index 0000000..34734cc
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go
@@ -0,0 +1,380 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "bytes"
9 "crypto"
10 "crypto/cipher"
11 "crypto/dsa"
12 "crypto/ecdsa"
13 "crypto/rsa"
14 "crypto/sha1"
15 "io"
16 "io/ioutil"
17 "math/big"
18 "strconv"
19 "time"
20
21 "golang.org/x/crypto/openpgp/elgamal"
22 "golang.org/x/crypto/openpgp/errors"
23 "golang.org/x/crypto/openpgp/s2k"
24)
25
26// PrivateKey represents a possibly encrypted private key. See RFC 4880,
27// section 5.5.3.
28type PrivateKey struct {
29 PublicKey
30 Encrypted bool // if true then the private key is unavailable until Decrypt has been called.
31 encryptedData []byte
32 cipher CipherFunction
33 s2k func(out, in []byte)
34 PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer.
35 sha1Checksum bool
36 iv []byte
37}
38
39func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
40 pk := new(PrivateKey)
41 pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
42 pk.PrivateKey = priv
43 return pk
44}
45
46func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
47 pk := new(PrivateKey)
48 pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
49 pk.PrivateKey = priv
50 return pk
51}
52
53func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *PrivateKey {
54 pk := new(PrivateKey)
55 pk.PublicKey = *NewElGamalPublicKey(currentTime, &priv.PublicKey)
56 pk.PrivateKey = priv
57 return pk
58}
59
60func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey {
61 pk := new(PrivateKey)
62 pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey)
63 pk.PrivateKey = priv
64 return pk
65}
66
67// NewSignerPrivateKey creates a sign-only PrivateKey from a crypto.Signer that
68// implements RSA or ECDSA.
69func NewSignerPrivateKey(currentTime time.Time, signer crypto.Signer) *PrivateKey {
70 pk := new(PrivateKey)
71 switch pubkey := signer.Public().(type) {
72 case rsa.PublicKey:
73 pk.PublicKey = *NewRSAPublicKey(currentTime, &pubkey)
74 pk.PubKeyAlgo = PubKeyAlgoRSASignOnly
75 case ecdsa.PublicKey:
76 pk.PublicKey = *NewECDSAPublicKey(currentTime, &pubkey)
77 default:
78 panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey")
79 }
80 pk.PrivateKey = signer
81 return pk
82}
83
84func (pk *PrivateKey) parse(r io.Reader) (err error) {
85 err = (&pk.PublicKey).parse(r)
86 if err != nil {
87 return
88 }
89 var buf [1]byte
90 _, err = readFull(r, buf[:])
91 if err != nil {
92 return
93 }
94
95 s2kType := buf[0]
96
97 switch s2kType {
98 case 0:
99 pk.s2k = nil
100 pk.Encrypted = false
101 case 254, 255:
102 _, err = readFull(r, buf[:])
103 if err != nil {
104 return
105 }
106 pk.cipher = CipherFunction(buf[0])
107 pk.Encrypted = true
108 pk.s2k, err = s2k.Parse(r)
109 if err != nil {
110 return
111 }
112 if s2kType == 254 {
113 pk.sha1Checksum = true
114 }
115 default:
116 return errors.UnsupportedError("deprecated s2k function in private key")
117 }
118
119 if pk.Encrypted {
120 blockSize := pk.cipher.blockSize()
121 if blockSize == 0 {
122 return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
123 }
124 pk.iv = make([]byte, blockSize)
125 _, err = readFull(r, pk.iv)
126 if err != nil {
127 return
128 }
129 }
130
131 pk.encryptedData, err = ioutil.ReadAll(r)
132 if err != nil {
133 return
134 }
135
136 if !pk.Encrypted {
137 return pk.parsePrivateKey(pk.encryptedData)
138 }
139
140 return
141}
142
143func mod64kHash(d []byte) uint16 {
144 var h uint16
145 for _, b := range d {
146 h += uint16(b)
147 }
148 return h
149}
150
151func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
152 // TODO(agl): support encrypted private keys
153 buf := bytes.NewBuffer(nil)
154 err = pk.PublicKey.serializeWithoutHeaders(buf)
155 if err != nil {
156 return
157 }
158 buf.WriteByte(0 /* no encryption */)
159
160 privateKeyBuf := bytes.NewBuffer(nil)
161
162 switch priv := pk.PrivateKey.(type) {
163 case *rsa.PrivateKey:
164 err = serializeRSAPrivateKey(privateKeyBuf, priv)
165 case *dsa.PrivateKey:
166 err = serializeDSAPrivateKey(privateKeyBuf, priv)
167 case *elgamal.PrivateKey:
168 err = serializeElGamalPrivateKey(privateKeyBuf, priv)
169 case *ecdsa.PrivateKey:
170 err = serializeECDSAPrivateKey(privateKeyBuf, priv)
171 default:
172 err = errors.InvalidArgumentError("unknown private key type")
173 }
174 if err != nil {
175 return
176 }
177
178 ptype := packetTypePrivateKey
179 contents := buf.Bytes()
180 privateKeyBytes := privateKeyBuf.Bytes()
181 if pk.IsSubkey {
182 ptype = packetTypePrivateSubkey
183 }
184 err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
185 if err != nil {
186 return
187 }
188 _, err = w.Write(contents)
189 if err != nil {
190 return
191 }
192 _, err = w.Write(privateKeyBytes)
193 if err != nil {
194 return
195 }
196
197 checksum := mod64kHash(privateKeyBytes)
198 var checksumBytes [2]byte
199 checksumBytes[0] = byte(checksum >> 8)
200 checksumBytes[1] = byte(checksum)
201 _, err = w.Write(checksumBytes[:])
202
203 return
204}
205
206func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
207 err := writeBig(w, priv.D)
208 if err != nil {
209 return err
210 }
211 err = writeBig(w, priv.Primes[1])
212 if err != nil {
213 return err
214 }
215 err = writeBig(w, priv.Primes[0])
216 if err != nil {
217 return err
218 }
219 return writeBig(w, priv.Precomputed.Qinv)
220}
221
222func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
223 return writeBig(w, priv.X)
224}
225
226func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error {
227 return writeBig(w, priv.X)
228}
229
230func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error {
231 return writeBig(w, priv.D)
232}
233
234// Decrypt decrypts an encrypted private key using a passphrase.
235func (pk *PrivateKey) Decrypt(passphrase []byte) error {
236 if !pk.Encrypted {
237 return nil
238 }
239
240 key := make([]byte, pk.cipher.KeySize())
241 pk.s2k(key, passphrase)
242 block := pk.cipher.new(key)
243 cfb := cipher.NewCFBDecrypter(block, pk.iv)
244
245 data := make([]byte, len(pk.encryptedData))
246 cfb.XORKeyStream(data, pk.encryptedData)
247
248 if pk.sha1Checksum {
249 if len(data) < sha1.Size {
250 return errors.StructuralError("truncated private key data")
251 }
252 h := sha1.New()
253 h.Write(data[:len(data)-sha1.Size])
254 sum := h.Sum(nil)
255 if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
256 return errors.StructuralError("private key checksum failure")
257 }
258 data = data[:len(data)-sha1.Size]
259 } else {
260 if len(data) < 2 {
261 return errors.StructuralError("truncated private key data")
262 }
263 var sum uint16
264 for i := 0; i < len(data)-2; i++ {
265 sum += uint16(data[i])
266 }
267 if data[len(data)-2] != uint8(sum>>8) ||
268 data[len(data)-1] != uint8(sum) {
269 return errors.StructuralError("private key checksum failure")
270 }
271 data = data[:len(data)-2]
272 }
273
274 return pk.parsePrivateKey(data)
275}
276
277func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
278 switch pk.PublicKey.PubKeyAlgo {
279 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
280 return pk.parseRSAPrivateKey(data)
281 case PubKeyAlgoDSA:
282 return pk.parseDSAPrivateKey(data)
283 case PubKeyAlgoElGamal:
284 return pk.parseElGamalPrivateKey(data)
285 case PubKeyAlgoECDSA:
286 return pk.parseECDSAPrivateKey(data)
287 }
288 panic("impossible")
289}
290
291func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
292 rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
293 rsaPriv := new(rsa.PrivateKey)
294 rsaPriv.PublicKey = *rsaPub
295
296 buf := bytes.NewBuffer(data)
297 d, _, err := readMPI(buf)
298 if err != nil {
299 return
300 }
301 p, _, err := readMPI(buf)
302 if err != nil {
303 return
304 }
305 q, _, err := readMPI(buf)
306 if err != nil {
307 return
308 }
309
310 rsaPriv.D = new(big.Int).SetBytes(d)
311 rsaPriv.Primes = make([]*big.Int, 2)
312 rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
313 rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
314 if err := rsaPriv.Validate(); err != nil {
315 return err
316 }
317 rsaPriv.Precompute()
318 pk.PrivateKey = rsaPriv
319 pk.Encrypted = false
320 pk.encryptedData = nil
321
322 return nil
323}
324
325func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
326 dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
327 dsaPriv := new(dsa.PrivateKey)
328 dsaPriv.PublicKey = *dsaPub
329
330 buf := bytes.NewBuffer(data)
331 x, _, err := readMPI(buf)
332 if err != nil {
333 return
334 }
335
336 dsaPriv.X = new(big.Int).SetBytes(x)
337 pk.PrivateKey = dsaPriv
338 pk.Encrypted = false
339 pk.encryptedData = nil
340
341 return nil
342}
343
344func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
345 pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
346 priv := new(elgamal.PrivateKey)
347 priv.PublicKey = *pub
348
349 buf := bytes.NewBuffer(data)
350 x, _, err := readMPI(buf)
351 if err != nil {
352 return
353 }
354
355 priv.X = new(big.Int).SetBytes(x)
356 pk.PrivateKey = priv
357 pk.Encrypted = false
358 pk.encryptedData = nil
359
360 return nil
361}
362
363func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
364 ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
365
366 buf := bytes.NewBuffer(data)
367 d, _, err := readMPI(buf)
368 if err != nil {
369 return
370 }
371
372 pk.PrivateKey = &ecdsa.PrivateKey{
373 PublicKey: *ecdsaPub,
374 D: new(big.Int).SetBytes(d),
375 }
376 pk.Encrypted = false
377 pk.encryptedData = nil
378
379 return nil
380}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go
new file mode 100644
index 0000000..ead2623
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go
@@ -0,0 +1,748 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "bytes"
9 "crypto"
10 "crypto/dsa"
11 "crypto/ecdsa"
12 "crypto/elliptic"
13 "crypto/rsa"
14 "crypto/sha1"
15 _ "crypto/sha256"
16 _ "crypto/sha512"
17 "encoding/binary"
18 "fmt"
19 "hash"
20 "io"
21 "math/big"
22 "strconv"
23 "time"
24
25 "golang.org/x/crypto/openpgp/elgamal"
26 "golang.org/x/crypto/openpgp/errors"
27)
28
29var (
30 // NIST curve P-256
31 oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}
32 // NIST curve P-384
33 oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22}
34 // NIST curve P-521
35 oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23}
36)
37
38const maxOIDLength = 8
39
40// ecdsaKey stores the algorithm-specific fields for ECDSA keys.
41// as defined in RFC 6637, Section 9.
42type ecdsaKey struct {
43 // oid contains the OID byte sequence identifying the elliptic curve used
44 oid []byte
45 // p contains the elliptic curve point that represents the public key
46 p parsedMPI
47}
48
49// parseOID reads the OID for the curve as defined in RFC 6637, Section 9.
50func parseOID(r io.Reader) (oid []byte, err error) {
51 buf := make([]byte, maxOIDLength)
52 if _, err = readFull(r, buf[:1]); err != nil {
53 return
54 }
55 oidLen := buf[0]
56 if int(oidLen) > len(buf) {
57 err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen)))
58 return
59 }
60 oid = buf[:oidLen]
61 _, err = readFull(r, oid)
62 return
63}
64
65func (f *ecdsaKey) parse(r io.Reader) (err error) {
66 if f.oid, err = parseOID(r); err != nil {
67 return err
68 }
69 f.p.bytes, f.p.bitLength, err = readMPI(r)
70 return
71}
72
73func (f *ecdsaKey) serialize(w io.Writer) (err error) {
74 buf := make([]byte, maxOIDLength+1)
75 buf[0] = byte(len(f.oid))
76 copy(buf[1:], f.oid)
77 if _, err = w.Write(buf[:len(f.oid)+1]); err != nil {
78 return
79 }
80 return writeMPIs(w, f.p)
81}
82
83func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) {
84 var c elliptic.Curve
85 if bytes.Equal(f.oid, oidCurveP256) {
86 c = elliptic.P256()
87 } else if bytes.Equal(f.oid, oidCurveP384) {
88 c = elliptic.P384()
89 } else if bytes.Equal(f.oid, oidCurveP521) {
90 c = elliptic.P521()
91 } else {
92 return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid))
93 }
94 x, y := elliptic.Unmarshal(c, f.p.bytes)
95 if x == nil {
96 return nil, errors.UnsupportedError("failed to parse EC point")
97 }
98 return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil
99}
100
101func (f *ecdsaKey) byteLen() int {
102 return 1 + len(f.oid) + 2 + len(f.p.bytes)
103}
104
105type kdfHashFunction byte
106type kdfAlgorithm byte
107
108// ecdhKdf stores key derivation function parameters
109// used for ECDH encryption. See RFC 6637, Section 9.
110type ecdhKdf struct {
111 KdfHash kdfHashFunction
112 KdfAlgo kdfAlgorithm
113}
114
115func (f *ecdhKdf) parse(r io.Reader) (err error) {
116 buf := make([]byte, 1)
117 if _, err = readFull(r, buf); err != nil {
118 return
119 }
120 kdfLen := int(buf[0])
121 if kdfLen < 3 {
122 return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen))
123 }
124 buf = make([]byte, kdfLen)
125 if _, err = readFull(r, buf); err != nil {
126 return
127 }
128 reserved := int(buf[0])
129 f.KdfHash = kdfHashFunction(buf[1])
130 f.KdfAlgo = kdfAlgorithm(buf[2])
131 if reserved != 0x01 {
132 return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved))
133 }
134 return
135}
136
137func (f *ecdhKdf) serialize(w io.Writer) (err error) {
138 buf := make([]byte, 4)
139 // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys.
140 buf[0] = byte(0x03) // Length of the following fields
141 buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now
142 buf[2] = byte(f.KdfHash)
143 buf[3] = byte(f.KdfAlgo)
144 _, err = w.Write(buf[:])
145 return
146}
147
148func (f *ecdhKdf) byteLen() int {
149 return 4
150}
151
152// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
153type PublicKey struct {
154 CreationTime time.Time
155 PubKeyAlgo PublicKeyAlgorithm
156 PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey
157 Fingerprint [20]byte
158 KeyId uint64
159 IsSubkey bool
160
161 n, e, p, q, g, y parsedMPI
162
163 // RFC 6637 fields
164 ec *ecdsaKey
165 ecdh *ecdhKdf
166}
167
168// signingKey provides a convenient abstraction over signature verification
169// for v3 and v4 public keys.
170type signingKey interface {
171 SerializeSignaturePrefix(io.Writer)
172 serializeWithoutHeaders(io.Writer) error
173}
174
175func fromBig(n *big.Int) parsedMPI {
176 return parsedMPI{
177 bytes: n.Bytes(),
178 bitLength: uint16(n.BitLen()),
179 }
180}
181
182// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
183func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
184 pk := &PublicKey{
185 CreationTime: creationTime,
186 PubKeyAlgo: PubKeyAlgoRSA,
187 PublicKey: pub,
188 n: fromBig(pub.N),
189 e: fromBig(big.NewInt(int64(pub.E))),
190 }
191
192 pk.setFingerPrintAndKeyId()
193 return pk
194}
195
196// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey.
197func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
198 pk := &PublicKey{
199 CreationTime: creationTime,
200 PubKeyAlgo: PubKeyAlgoDSA,
201 PublicKey: pub,
202 p: fromBig(pub.P),
203 q: fromBig(pub.Q),
204 g: fromBig(pub.G),
205 y: fromBig(pub.Y),
206 }
207
208 pk.setFingerPrintAndKeyId()
209 return pk
210}
211
212// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey.
213func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey {
214 pk := &PublicKey{
215 CreationTime: creationTime,
216 PubKeyAlgo: PubKeyAlgoElGamal,
217 PublicKey: pub,
218 p: fromBig(pub.P),
219 g: fromBig(pub.G),
220 y: fromBig(pub.Y),
221 }
222
223 pk.setFingerPrintAndKeyId()
224 return pk
225}
226
227func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey {
228 pk := &PublicKey{
229 CreationTime: creationTime,
230 PubKeyAlgo: PubKeyAlgoECDSA,
231 PublicKey: pub,
232 ec: new(ecdsaKey),
233 }
234
235 switch pub.Curve {
236 case elliptic.P256():
237 pk.ec.oid = oidCurveP256
238 case elliptic.P384():
239 pk.ec.oid = oidCurveP384
240 case elliptic.P521():
241 pk.ec.oid = oidCurveP521
242 default:
243 panic("unknown elliptic curve")
244 }
245
246 pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
247 pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes))
248
249 pk.setFingerPrintAndKeyId()
250 return pk
251}
252
253func (pk *PublicKey) parse(r io.Reader) (err error) {
254 // RFC 4880, section 5.5.2
255 var buf [6]byte
256 _, err = readFull(r, buf[:])
257 if err != nil {
258 return
259 }
260 if buf[0] != 4 {
261 return errors.UnsupportedError("public key version")
262 }
263 pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
264 pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
265 switch pk.PubKeyAlgo {
266 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
267 err = pk.parseRSA(r)
268 case PubKeyAlgoDSA:
269 err = pk.parseDSA(r)
270 case PubKeyAlgoElGamal:
271 err = pk.parseElGamal(r)
272 case PubKeyAlgoECDSA:
273 pk.ec = new(ecdsaKey)
274 if err = pk.ec.parse(r); err != nil {
275 return err
276 }
277 pk.PublicKey, err = pk.ec.newECDSA()
278 case PubKeyAlgoECDH:
279 pk.ec = new(ecdsaKey)
280 if err = pk.ec.parse(r); err != nil {
281 return
282 }
283 pk.ecdh = new(ecdhKdf)
284 if err = pk.ecdh.parse(r); err != nil {
285 return
286 }
287 // The ECDH key is stored in an ecdsa.PublicKey for convenience.
288 pk.PublicKey, err = pk.ec.newECDSA()
289 default:
290 err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
291 }
292 if err != nil {
293 return
294 }
295
296 pk.setFingerPrintAndKeyId()
297 return
298}
299
300func (pk *PublicKey) setFingerPrintAndKeyId() {
301 // RFC 4880, section 12.2
302 fingerPrint := sha1.New()
303 pk.SerializeSignaturePrefix(fingerPrint)
304 pk.serializeWithoutHeaders(fingerPrint)
305 copy(pk.Fingerprint[:], fingerPrint.Sum(nil))
306 pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
307}
308
309// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
310// section 5.5.2.
311func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
312 pk.n.bytes, pk.n.bitLength, err = readMPI(r)
313 if err != nil {
314 return
315 }
316 pk.e.bytes, pk.e.bitLength, err = readMPI(r)
317 if err != nil {
318 return
319 }
320
321 if len(pk.e.bytes) > 3 {
322 err = errors.UnsupportedError("large public exponent")
323 return
324 }
325 rsa := &rsa.PublicKey{
326 N: new(big.Int).SetBytes(pk.n.bytes),
327 E: 0,
328 }
329 for i := 0; i < len(pk.e.bytes); i++ {
330 rsa.E <<= 8
331 rsa.E |= int(pk.e.bytes[i])
332 }
333 pk.PublicKey = rsa
334 return
335}
336
337// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
338// section 5.5.2.
339func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
340 pk.p.bytes, pk.p.bitLength, err = readMPI(r)
341 if err != nil {
342 return
343 }
344 pk.q.bytes, pk.q.bitLength, err = readMPI(r)
345 if err != nil {
346 return
347 }
348 pk.g.bytes, pk.g.bitLength, err = readMPI(r)
349 if err != nil {
350 return
351 }
352 pk.y.bytes, pk.y.bitLength, err = readMPI(r)
353 if err != nil {
354 return
355 }
356
357 dsa := new(dsa.PublicKey)
358 dsa.P = new(big.Int).SetBytes(pk.p.bytes)
359 dsa.Q = new(big.Int).SetBytes(pk.q.bytes)
360 dsa.G = new(big.Int).SetBytes(pk.g.bytes)
361 dsa.Y = new(big.Int).SetBytes(pk.y.bytes)
362 pk.PublicKey = dsa
363 return
364}
365
366// parseElGamal parses ElGamal public key material from the given Reader. See
367// RFC 4880, section 5.5.2.
368func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
369 pk.p.bytes, pk.p.bitLength, err = readMPI(r)
370 if err != nil {
371 return
372 }
373 pk.g.bytes, pk.g.bitLength, err = readMPI(r)
374 if err != nil {
375 return
376 }
377 pk.y.bytes, pk.y.bitLength, err = readMPI(r)
378 if err != nil {
379 return
380 }
381
382 elgamal := new(elgamal.PublicKey)
383 elgamal.P = new(big.Int).SetBytes(pk.p.bytes)
384 elgamal.G = new(big.Int).SetBytes(pk.g.bytes)
385 elgamal.Y = new(big.Int).SetBytes(pk.y.bytes)
386 pk.PublicKey = elgamal
387 return
388}
389
390// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
391// The prefix is used when calculating a signature over this public key. See
392// RFC 4880, section 5.2.4.
393func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) {
394 var pLength uint16
395 switch pk.PubKeyAlgo {
396 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
397 pLength += 2 + uint16(len(pk.n.bytes))
398 pLength += 2 + uint16(len(pk.e.bytes))
399 case PubKeyAlgoDSA:
400 pLength += 2 + uint16(len(pk.p.bytes))
401 pLength += 2 + uint16(len(pk.q.bytes))
402 pLength += 2 + uint16(len(pk.g.bytes))
403 pLength += 2 + uint16(len(pk.y.bytes))
404 case PubKeyAlgoElGamal:
405 pLength += 2 + uint16(len(pk.p.bytes))
406 pLength += 2 + uint16(len(pk.g.bytes))
407 pLength += 2 + uint16(len(pk.y.bytes))
408 case PubKeyAlgoECDSA:
409 pLength += uint16(pk.ec.byteLen())
410 case PubKeyAlgoECDH:
411 pLength += uint16(pk.ec.byteLen())
412 pLength += uint16(pk.ecdh.byteLen())
413 default:
414 panic("unknown public key algorithm")
415 }
416 pLength += 6
417 h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
418 return
419}
420
421func (pk *PublicKey) Serialize(w io.Writer) (err error) {
422 length := 6 // 6 byte header
423
424 switch pk.PubKeyAlgo {
425 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
426 length += 2 + len(pk.n.bytes)
427 length += 2 + len(pk.e.bytes)
428 case PubKeyAlgoDSA:
429 length += 2 + len(pk.p.bytes)
430 length += 2 + len(pk.q.bytes)
431 length += 2 + len(pk.g.bytes)
432 length += 2 + len(pk.y.bytes)
433 case PubKeyAlgoElGamal:
434 length += 2 + len(pk.p.bytes)
435 length += 2 + len(pk.g.bytes)
436 length += 2 + len(pk.y.bytes)
437 case PubKeyAlgoECDSA:
438 length += pk.ec.byteLen()
439 case PubKeyAlgoECDH:
440 length += pk.ec.byteLen()
441 length += pk.ecdh.byteLen()
442 default:
443 panic("unknown public key algorithm")
444 }
445
446 packetType := packetTypePublicKey
447 if pk.IsSubkey {
448 packetType = packetTypePublicSubkey
449 }
450 err = serializeHeader(w, packetType, length)
451 if err != nil {
452 return
453 }
454 return pk.serializeWithoutHeaders(w)
455}
456
457// serializeWithoutHeaders marshals the PublicKey to w in the form of an
458// OpenPGP public key packet, not including the packet header.
459func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
460 var buf [6]byte
461 buf[0] = 4
462 t := uint32(pk.CreationTime.Unix())
463 buf[1] = byte(t >> 24)
464 buf[2] = byte(t >> 16)
465 buf[3] = byte(t >> 8)
466 buf[4] = byte(t)
467 buf[5] = byte(pk.PubKeyAlgo)
468
469 _, err = w.Write(buf[:])
470 if err != nil {
471 return
472 }
473
474 switch pk.PubKeyAlgo {
475 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
476 return writeMPIs(w, pk.n, pk.e)
477 case PubKeyAlgoDSA:
478 return writeMPIs(w, pk.p, pk.q, pk.g, pk.y)
479 case PubKeyAlgoElGamal:
480 return writeMPIs(w, pk.p, pk.g, pk.y)
481 case PubKeyAlgoECDSA:
482 return pk.ec.serialize(w)
483 case PubKeyAlgoECDH:
484 if err = pk.ec.serialize(w); err != nil {
485 return
486 }
487 return pk.ecdh.serialize(w)
488 }
489 return errors.InvalidArgumentError("bad public-key algorithm")
490}
491
492// CanSign returns true iff this public key can generate signatures
493func (pk *PublicKey) CanSign() bool {
494 return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal
495}
496
497// VerifySignature returns nil iff sig is a valid signature, made by this
498// public key, of the data hashed into signed. signed is mutated by this call.
499func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
500 if !pk.CanSign() {
501 return errors.InvalidArgumentError("public key cannot generate signatures")
502 }
503
504 signed.Write(sig.HashSuffix)
505 hashBytes := signed.Sum(nil)
506
507 if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
508 return errors.SignatureError("hash tag doesn't match")
509 }
510
511 if pk.PubKeyAlgo != sig.PubKeyAlgo {
512 return errors.InvalidArgumentError("public key and signature use different algorithms")
513 }
514
515 switch pk.PubKeyAlgo {
516 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
517 rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
518 err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes)
519 if err != nil {
520 return errors.SignatureError("RSA verification failure")
521 }
522 return nil
523 case PubKeyAlgoDSA:
524 dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
525 // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
526 subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
527 if len(hashBytes) > subgroupSize {
528 hashBytes = hashBytes[:subgroupSize]
529 }
530 if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
531 return errors.SignatureError("DSA verification failure")
532 }
533 return nil
534 case PubKeyAlgoECDSA:
535 ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
536 if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) {
537 return errors.SignatureError("ECDSA verification failure")
538 }
539 return nil
540 default:
541 return errors.SignatureError("Unsupported public key algorithm used in signature")
542 }
543}
544
545// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
546// public key, of the data hashed into signed. signed is mutated by this call.
547func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
548 if !pk.CanSign() {
549 return errors.InvalidArgumentError("public key cannot generate signatures")
550 }
551
552 suffix := make([]byte, 5)
553 suffix[0] = byte(sig.SigType)
554 binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
555 signed.Write(suffix)
556 hashBytes := signed.Sum(nil)
557
558 if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
559 return errors.SignatureError("hash tag doesn't match")
560 }
561
562 if pk.PubKeyAlgo != sig.PubKeyAlgo {
563 return errors.InvalidArgumentError("public key and signature use different algorithms")
564 }
565
566 switch pk.PubKeyAlgo {
567 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
568 rsaPublicKey := pk.PublicKey.(*rsa.PublicKey)
569 if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
570 return errors.SignatureError("RSA verification failure")
571 }
572 return
573 case PubKeyAlgoDSA:
574 dsaPublicKey := pk.PublicKey.(*dsa.PublicKey)
575 // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
576 subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
577 if len(hashBytes) > subgroupSize {
578 hashBytes = hashBytes[:subgroupSize]
579 }
580 if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) {
581 return errors.SignatureError("DSA verification failure")
582 }
583 return nil
584 default:
585 panic("shouldn't happen")
586 }
587}
588
589// keySignatureHash returns a Hash of the message that needs to be signed for
590// pk to assert a subkey relationship to signed.
591func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
592 if !hashFunc.Available() {
593 return nil, errors.UnsupportedError("hash function")
594 }
595 h = hashFunc.New()
596
597 // RFC 4880, section 5.2.4
598 pk.SerializeSignaturePrefix(h)
599 pk.serializeWithoutHeaders(h)
600 signed.SerializeSignaturePrefix(h)
601 signed.serializeWithoutHeaders(h)
602 return
603}
604
605// VerifyKeySignature returns nil iff sig is a valid signature, made by this
606// public key, of signed.
607func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error {
608 h, err := keySignatureHash(pk, signed, sig.Hash)
609 if err != nil {
610 return err
611 }
612 if err = pk.VerifySignature(h, sig); err != nil {
613 return err
614 }
615
616 if sig.FlagSign {
617 // Signing subkeys must be cross-signed. See
618 // https://www.gnupg.org/faq/subkey-cross-certify.html.
619 if sig.EmbeddedSignature == nil {
620 return errors.StructuralError("signing subkey is missing cross-signature")
621 }
622 // Verify the cross-signature. This is calculated over the same
623 // data as the main signature, so we cannot just recursively
624 // call signed.VerifyKeySignature(...)
625 if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil {
626 return errors.StructuralError("error while hashing for cross-signature: " + err.Error())
627 }
628 if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil {
629 return errors.StructuralError("error while verifying cross-signature: " + err.Error())
630 }
631 }
632
633 return nil
634}
635
636func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
637 if !hashFunc.Available() {
638 return nil, errors.UnsupportedError("hash function")
639 }
640 h = hashFunc.New()
641
642 // RFC 4880, section 5.2.4
643 pk.SerializeSignaturePrefix(h)
644 pk.serializeWithoutHeaders(h)
645
646 return
647}
648
649// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
650// public key.
651func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
652 h, err := keyRevocationHash(pk, sig.Hash)
653 if err != nil {
654 return err
655 }
656 return pk.VerifySignature(h, sig)
657}
658
659// userIdSignatureHash returns a Hash of the message that needs to be signed
660// to assert that pk is a valid key for id.
661func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) {
662 if !hashFunc.Available() {
663 return nil, errors.UnsupportedError("hash function")
664 }
665 h = hashFunc.New()
666
667 // RFC 4880, section 5.2.4
668 pk.SerializeSignaturePrefix(h)
669 pk.serializeWithoutHeaders(h)
670
671 var buf [5]byte
672 buf[0] = 0xb4
673 buf[1] = byte(len(id) >> 24)
674 buf[2] = byte(len(id) >> 16)
675 buf[3] = byte(len(id) >> 8)
676 buf[4] = byte(len(id))
677 h.Write(buf[:])
678 h.Write([]byte(id))
679
680 return
681}
682
683// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
684// public key, that id is the identity of pub.
685func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) {
686 h, err := userIdSignatureHash(id, pub, sig.Hash)
687 if err != nil {
688 return err
689 }
690 return pk.VerifySignature(h, sig)
691}
692
693// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
694// public key, that id is the identity of pub.
695func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) {
696 h, err := userIdSignatureV3Hash(id, pub, sig.Hash)
697 if err != nil {
698 return err
699 }
700 return pk.VerifySignatureV3(h, sig)
701}
702
703// KeyIdString returns the public key's fingerprint in capital hex
704// (e.g. "6C7EE1B8621CC013").
705func (pk *PublicKey) KeyIdString() string {
706 return fmt.Sprintf("%X", pk.Fingerprint[12:20])
707}
708
709// KeyIdShortString returns the short form of public key's fingerprint
710// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
711func (pk *PublicKey) KeyIdShortString() string {
712 return fmt.Sprintf("%X", pk.Fingerprint[16:20])
713}
714
715// A parsedMPI is used to store the contents of a big integer, along with the
716// bit length that was specified in the original input. This allows the MPI to
717// be reserialized exactly.
718type parsedMPI struct {
719 bytes []byte
720 bitLength uint16
721}
722
723// writeMPIs is a utility function for serializing several big integers to the
724// given Writer.
725func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) {
726 for _, mpi := range mpis {
727 err = writeMPI(w, mpi.bitLength, mpi.bytes)
728 if err != nil {
729 return
730 }
731 }
732 return
733}
734
735// BitLength returns the bit length for the given public key.
736func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
737 switch pk.PubKeyAlgo {
738 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
739 bitLength = pk.n.bitLength
740 case PubKeyAlgoDSA:
741 bitLength = pk.p.bitLength
742 case PubKeyAlgoElGamal:
743 bitLength = pk.p.bitLength
744 default:
745 err = errors.InvalidArgumentError("bad public-key algorithm")
746 }
747 return
748}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go
new file mode 100644
index 0000000..5daf7b6
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go
@@ -0,0 +1,279 @@
1// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "crypto"
9 "crypto/md5"
10 "crypto/rsa"
11 "encoding/binary"
12 "fmt"
13 "hash"
14 "io"
15 "math/big"
16 "strconv"
17 "time"
18
19 "golang.org/x/crypto/openpgp/errors"
20)
21
22// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and
23// should not be used for signing or encrypting. They are supported here only for
24// parsing version 3 key material and validating signatures.
25// See RFC 4880, section 5.5.2.
26type PublicKeyV3 struct {
27 CreationTime time.Time
28 DaysToExpire uint16
29 PubKeyAlgo PublicKeyAlgorithm
30 PublicKey *rsa.PublicKey
31 Fingerprint [16]byte
32 KeyId uint64
33 IsSubkey bool
34
35 n, e parsedMPI
36}
37
38// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey.
39// Included here for testing purposes only. RFC 4880, section 5.5.2:
40// "an implementation MUST NOT generate a V3 key, but MAY accept it."
41func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 {
42 pk := &PublicKeyV3{
43 CreationTime: creationTime,
44 PublicKey: pub,
45 n: fromBig(pub.N),
46 e: fromBig(big.NewInt(int64(pub.E))),
47 }
48
49 pk.setFingerPrintAndKeyId()
50 return pk
51}
52
53func (pk *PublicKeyV3) parse(r io.Reader) (err error) {
54 // RFC 4880, section 5.5.2
55 var buf [8]byte
56 if _, err = readFull(r, buf[:]); err != nil {
57 return
58 }
59 if buf[0] < 2 || buf[0] > 3 {
60 return errors.UnsupportedError("public key version")
61 }
62 pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
63 pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7])
64 pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7])
65 switch pk.PubKeyAlgo {
66 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
67 err = pk.parseRSA(r)
68 default:
69 err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
70 }
71 if err != nil {
72 return
73 }
74
75 pk.setFingerPrintAndKeyId()
76 return
77}
78
79func (pk *PublicKeyV3) setFingerPrintAndKeyId() {
80 // RFC 4880, section 12.2
81 fingerPrint := md5.New()
82 fingerPrint.Write(pk.n.bytes)
83 fingerPrint.Write(pk.e.bytes)
84 fingerPrint.Sum(pk.Fingerprint[:0])
85 pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:])
86}
87
88// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
89// section 5.5.2.
90func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) {
91 if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil {
92 return
93 }
94 if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil {
95 return
96 }
97
98 // RFC 4880 Section 12.2 requires the low 8 bytes of the
99 // modulus to form the key id.
100 if len(pk.n.bytes) < 8 {
101 return errors.StructuralError("v3 public key modulus is too short")
102 }
103 if len(pk.e.bytes) > 3 {
104 err = errors.UnsupportedError("large public exponent")
105 return
106 }
107 rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)}
108 for i := 0; i < len(pk.e.bytes); i++ {
109 rsa.E <<= 8
110 rsa.E |= int(pk.e.bytes[i])
111 }
112 pk.PublicKey = rsa
113 return
114}
115
116// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
117// The prefix is used when calculating a signature over this public key. See
118// RFC 4880, section 5.2.4.
119func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) {
120 var pLength uint16
121 switch pk.PubKeyAlgo {
122 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
123 pLength += 2 + uint16(len(pk.n.bytes))
124 pLength += 2 + uint16(len(pk.e.bytes))
125 default:
126 panic("unknown public key algorithm")
127 }
128 pLength += 6
129 w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)})
130 return
131}
132
133func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) {
134 length := 8 // 8 byte header
135
136 switch pk.PubKeyAlgo {
137 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
138 length += 2 + len(pk.n.bytes)
139 length += 2 + len(pk.e.bytes)
140 default:
141 panic("unknown public key algorithm")
142 }
143
144 packetType := packetTypePublicKey
145 if pk.IsSubkey {
146 packetType = packetTypePublicSubkey
147 }
148 if err = serializeHeader(w, packetType, length); err != nil {
149 return
150 }
151 return pk.serializeWithoutHeaders(w)
152}
153
154// serializeWithoutHeaders marshals the PublicKey to w in the form of an
155// OpenPGP public key packet, not including the packet header.
156func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) {
157 var buf [8]byte
158 // Version 3
159 buf[0] = 3
160 // Creation time
161 t := uint32(pk.CreationTime.Unix())
162 buf[1] = byte(t >> 24)
163 buf[2] = byte(t >> 16)
164 buf[3] = byte(t >> 8)
165 buf[4] = byte(t)
166 // Days to expire
167 buf[5] = byte(pk.DaysToExpire >> 8)
168 buf[6] = byte(pk.DaysToExpire)
169 // Public key algorithm
170 buf[7] = byte(pk.PubKeyAlgo)
171
172 if _, err = w.Write(buf[:]); err != nil {
173 return
174 }
175
176 switch pk.PubKeyAlgo {
177 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
178 return writeMPIs(w, pk.n, pk.e)
179 }
180 return errors.InvalidArgumentError("bad public-key algorithm")
181}
182
183// CanSign returns true iff this public key can generate signatures
184func (pk *PublicKeyV3) CanSign() bool {
185 return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly
186}
187
188// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
189// public key, of the data hashed into signed. signed is mutated by this call.
190func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) {
191 if !pk.CanSign() {
192 return errors.InvalidArgumentError("public key cannot generate signatures")
193 }
194
195 suffix := make([]byte, 5)
196 suffix[0] = byte(sig.SigType)
197 binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix()))
198 signed.Write(suffix)
199 hashBytes := signed.Sum(nil)
200
201 if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
202 return errors.SignatureError("hash tag doesn't match")
203 }
204
205 if pk.PubKeyAlgo != sig.PubKeyAlgo {
206 return errors.InvalidArgumentError("public key and signature use different algorithms")
207 }
208
209 switch pk.PubKeyAlgo {
210 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
211 if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil {
212 return errors.SignatureError("RSA verification failure")
213 }
214 return
215 default:
216 // V3 public keys only support RSA.
217 panic("shouldn't happen")
218 }
219}
220
221// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this
222// public key, that id is the identity of pub.
223func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) {
224 h, err := userIdSignatureV3Hash(id, pk, sig.Hash)
225 if err != nil {
226 return err
227 }
228 return pk.VerifySignatureV3(h, sig)
229}
230
231// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this
232// public key, of signed.
233func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) {
234 h, err := keySignatureHash(pk, signed, sig.Hash)
235 if err != nil {
236 return err
237 }
238 return pk.VerifySignatureV3(h, sig)
239}
240
241// userIdSignatureV3Hash returns a Hash of the message that needs to be signed
242// to assert that pk is a valid key for id.
243func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) {
244 if !hfn.Available() {
245 return nil, errors.UnsupportedError("hash function")
246 }
247 h = hfn.New()
248
249 // RFC 4880, section 5.2.4
250 pk.SerializeSignaturePrefix(h)
251 pk.serializeWithoutHeaders(h)
252
253 h.Write([]byte(id))
254
255 return
256}
257
258// KeyIdString returns the public key's fingerprint in capital hex
259// (e.g. "6C7EE1B8621CC013").
260func (pk *PublicKeyV3) KeyIdString() string {
261 return fmt.Sprintf("%X", pk.KeyId)
262}
263
264// KeyIdShortString returns the short form of public key's fingerprint
265// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
266func (pk *PublicKeyV3) KeyIdShortString() string {
267 return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF)
268}
269
270// BitLength returns the bit length for the given public key.
271func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) {
272 switch pk.PubKeyAlgo {
273 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
274 bitLength = pk.n.bitLength
275 default:
276 err = errors.InvalidArgumentError("bad public-key algorithm")
277 }
278 return
279}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/reader.go b/vendor/golang.org/x/crypto/openpgp/packet/reader.go
new file mode 100644
index 0000000..34bc7c6
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/reader.go
@@ -0,0 +1,76 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "golang.org/x/crypto/openpgp/errors"
9 "io"
10)
11
12// Reader reads packets from an io.Reader and allows packets to be 'unread' so
13// that they result from the next call to Next.
14type Reader struct {
15 q []Packet
16 readers []io.Reader
17}
18
19// New io.Readers are pushed when a compressed or encrypted packet is processed
20// and recursively treated as a new source of packets. However, a carefully
21// crafted packet can trigger an infinite recursive sequence of packets. See
22// http://mumble.net/~campbell/misc/pgp-quine
23// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402
24// This constant limits the number of recursive packets that may be pushed.
25const maxReaders = 32
26
27// Next returns the most recently unread Packet, or reads another packet from
28// the top-most io.Reader. Unknown packet types are skipped.
29func (r *Reader) Next() (p Packet, err error) {
30 if len(r.q) > 0 {
31 p = r.q[len(r.q)-1]
32 r.q = r.q[:len(r.q)-1]
33 return
34 }
35
36 for len(r.readers) > 0 {
37 p, err = Read(r.readers[len(r.readers)-1])
38 if err == nil {
39 return
40 }
41 if err == io.EOF {
42 r.readers = r.readers[:len(r.readers)-1]
43 continue
44 }
45 if _, ok := err.(errors.UnknownPacketTypeError); !ok {
46 return nil, err
47 }
48 }
49
50 return nil, io.EOF
51}
52
53// Push causes the Reader to start reading from a new io.Reader. When an EOF
54// error is seen from the new io.Reader, it is popped and the Reader continues
55// to read from the next most recent io.Reader. Push returns a StructuralError
56// if pushing the reader would exceed the maximum recursion level, otherwise it
57// returns nil.
58func (r *Reader) Push(reader io.Reader) (err error) {
59 if len(r.readers) >= maxReaders {
60 return errors.StructuralError("too many layers of packets")
61 }
62 r.readers = append(r.readers, reader)
63 return nil
64}
65
66// Unread causes the given Packet to be returned from the next call to Next.
67func (r *Reader) Unread(p Packet) {
68 r.q = append(r.q, p)
69}
70
71func NewReader(r io.Reader) *Reader {
72 return &Reader{
73 q: nil,
74 readers: []io.Reader{r},
75 }
76}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature.go b/vendor/golang.org/x/crypto/openpgp/packet/signature.go
new file mode 100644
index 0000000..6ce0cbe
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/signature.go
@@ -0,0 +1,731 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "bytes"
9 "crypto"
10 "crypto/dsa"
11 "crypto/ecdsa"
12 "encoding/asn1"
13 "encoding/binary"
14 "hash"
15 "io"
16 "math/big"
17 "strconv"
18 "time"
19
20 "golang.org/x/crypto/openpgp/errors"
21 "golang.org/x/crypto/openpgp/s2k"
22)
23
24const (
25 // See RFC 4880, section 5.2.3.21 for details.
26 KeyFlagCertify = 1 << iota
27 KeyFlagSign
28 KeyFlagEncryptCommunications
29 KeyFlagEncryptStorage
30)
31
32// Signature represents a signature. See RFC 4880, section 5.2.
33type Signature struct {
34 SigType SignatureType
35 PubKeyAlgo PublicKeyAlgorithm
36 Hash crypto.Hash
37
38 // HashSuffix is extra data that is hashed in after the signed data.
39 HashSuffix []byte
40 // HashTag contains the first two bytes of the hash for fast rejection
41 // of bad signed data.
42 HashTag [2]byte
43 CreationTime time.Time
44
45 RSASignature parsedMPI
46 DSASigR, DSASigS parsedMPI
47 ECDSASigR, ECDSASigS parsedMPI
48
49 // rawSubpackets contains the unparsed subpackets, in order.
50 rawSubpackets []outputSubpacket
51
52 // The following are optional so are nil when not included in the
53 // signature.
54
55 SigLifetimeSecs, KeyLifetimeSecs *uint32
56 PreferredSymmetric, PreferredHash, PreferredCompression []uint8
57 IssuerKeyId *uint64
58 IsPrimaryId *bool
59
60 // FlagsValid is set if any flags were given. See RFC 4880, section
61 // 5.2.3.21 for details.
62 FlagsValid bool
63 FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool
64
65 // RevocationReason is set if this signature has been revoked.
66 // See RFC 4880, section 5.2.3.23 for details.
67 RevocationReason *uint8
68 RevocationReasonText string
69
70 // MDC is set if this signature has a feature packet that indicates
71 // support for MDC subpackets.
72 MDC bool
73
74 // EmbeddedSignature, if non-nil, is a signature of the parent key, by
75 // this key. This prevents an attacker from claiming another's signing
76 // subkey as their own.
77 EmbeddedSignature *Signature
78
79 outSubpackets []outputSubpacket
80}
81
82func (sig *Signature) parse(r io.Reader) (err error) {
83 // RFC 4880, section 5.2.3
84 var buf [5]byte
85 _, err = readFull(r, buf[:1])
86 if err != nil {
87 return
88 }
89 if buf[0] != 4 {
90 err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
91 return
92 }
93
94 _, err = readFull(r, buf[:5])
95 if err != nil {
96 return
97 }
98 sig.SigType = SignatureType(buf[0])
99 sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
100 switch sig.PubKeyAlgo {
101 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA:
102 default:
103 err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
104 return
105 }
106
107 var ok bool
108 sig.Hash, ok = s2k.HashIdToHash(buf[2])
109 if !ok {
110 return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
111 }
112
113 hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4])
114 l := 6 + hashedSubpacketsLength
115 sig.HashSuffix = make([]byte, l+6)
116 sig.HashSuffix[0] = 4
117 copy(sig.HashSuffix[1:], buf[:5])
118 hashedSubpackets := sig.HashSuffix[6:l]
119 _, err = readFull(r, hashedSubpackets)
120 if err != nil {
121 return
122 }
123 // See RFC 4880, section 5.2.4
124 trailer := sig.HashSuffix[l:]
125 trailer[0] = 4
126 trailer[1] = 0xff
127 trailer[2] = uint8(l >> 24)
128 trailer[3] = uint8(l >> 16)
129 trailer[4] = uint8(l >> 8)
130 trailer[5] = uint8(l)
131
132 err = parseSignatureSubpackets(sig, hashedSubpackets, true)
133 if err != nil {
134 return
135 }
136
137 _, err = readFull(r, buf[:2])
138 if err != nil {
139 return
140 }
141 unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1])
142 unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
143 _, err = readFull(r, unhashedSubpackets)
144 if err != nil {
145 return
146 }
147 err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
148 if err != nil {
149 return
150 }
151
152 _, err = readFull(r, sig.HashTag[:2])
153 if err != nil {
154 return
155 }
156
157 switch sig.PubKeyAlgo {
158 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
159 sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
160 case PubKeyAlgoDSA:
161 sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r)
162 if err == nil {
163 sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
164 }
165 case PubKeyAlgoECDSA:
166 sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r)
167 if err == nil {
168 sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r)
169 }
170 default:
171 panic("unreachable")
172 }
173 return
174}
175
176// parseSignatureSubpackets parses subpackets of the main signature packet. See
177// RFC 4880, section 5.2.3.1.
178func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) {
179 for len(subpackets) > 0 {
180 subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
181 if err != nil {
182 return
183 }
184 }
185
186 if sig.CreationTime.IsZero() {
187 err = errors.StructuralError("no creation time in signature")
188 }
189
190 return
191}
192
193type signatureSubpacketType uint8
194
195const (
196 creationTimeSubpacket signatureSubpacketType = 2
197 signatureExpirationSubpacket signatureSubpacketType = 3
198 keyExpirationSubpacket signatureSubpacketType = 9
199 prefSymmetricAlgosSubpacket signatureSubpacketType = 11
200 issuerSubpacket signatureSubpacketType = 16
201 prefHashAlgosSubpacket signatureSubpacketType = 21
202 prefCompressionSubpacket signatureSubpacketType = 22
203 primaryUserIdSubpacket signatureSubpacketType = 25
204 keyFlagsSubpacket signatureSubpacketType = 27
205 reasonForRevocationSubpacket signatureSubpacketType = 29
206 featuresSubpacket signatureSubpacketType = 30
207 embeddedSignatureSubpacket signatureSubpacketType = 32
208)
209
210// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
211func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) {
212 // RFC 4880, section 5.2.3.1
213 var (
214 length uint32
215 packetType signatureSubpacketType
216 isCritical bool
217 )
218 switch {
219 case subpacket[0] < 192:
220 length = uint32(subpacket[0])
221 subpacket = subpacket[1:]
222 case subpacket[0] < 255:
223 if len(subpacket) < 2 {
224 goto Truncated
225 }
226 length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
227 subpacket = subpacket[2:]
228 default:
229 if len(subpacket) < 5 {
230 goto Truncated
231 }
232 length = uint32(subpacket[1])<<24 |
233 uint32(subpacket[2])<<16 |
234 uint32(subpacket[3])<<8 |
235 uint32(subpacket[4])
236 subpacket = subpacket[5:]
237 }
238 if length > uint32(len(subpacket)) {
239 goto Truncated
240 }
241 rest = subpacket[length:]
242 subpacket = subpacket[:length]
243 if len(subpacket) == 0 {
244 err = errors.StructuralError("zero length signature subpacket")
245 return
246 }
247 packetType = signatureSubpacketType(subpacket[0] & 0x7f)
248 isCritical = subpacket[0]&0x80 == 0x80
249 subpacket = subpacket[1:]
250 sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
251 switch packetType {
252 case creationTimeSubpacket:
253 if !isHashed {
254 err = errors.StructuralError("signature creation time in non-hashed area")
255 return
256 }
257 if len(subpacket) != 4 {
258 err = errors.StructuralError("signature creation time not four bytes")
259 return
260 }
261 t := binary.BigEndian.Uint32(subpacket)
262 sig.CreationTime = time.Unix(int64(t), 0)
263 case signatureExpirationSubpacket:
264 // Signature expiration time, section 5.2.3.10
265 if !isHashed {
266 return
267 }
268 if len(subpacket) != 4 {
269 err = errors.StructuralError("expiration subpacket with bad length")
270 return
271 }
272 sig.SigLifetimeSecs = new(uint32)
273 *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
274 case keyExpirationSubpacket:
275 // Key expiration time, section 5.2.3.6
276 if !isHashed {
277 return
278 }
279 if len(subpacket) != 4 {
280 err = errors.StructuralError("key expiration subpacket with bad length")
281 return
282 }
283 sig.KeyLifetimeSecs = new(uint32)
284 *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
285 case prefSymmetricAlgosSubpacket:
286 // Preferred symmetric algorithms, section 5.2.3.7
287 if !isHashed {
288 return
289 }
290 sig.PreferredSymmetric = make([]byte, len(subpacket))
291 copy(sig.PreferredSymmetric, subpacket)
292 case issuerSubpacket:
293 // Issuer, section 5.2.3.5
294 if len(subpacket) != 8 {
295 err = errors.StructuralError("issuer subpacket with bad length")
296 return
297 }
298 sig.IssuerKeyId = new(uint64)
299 *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
300 case prefHashAlgosSubpacket:
301 // Preferred hash algorithms, section 5.2.3.8
302 if !isHashed {
303 return
304 }
305 sig.PreferredHash = make([]byte, len(subpacket))
306 copy(sig.PreferredHash, subpacket)
307 case prefCompressionSubpacket:
308 // Preferred compression algorithms, section 5.2.3.9
309 if !isHashed {
310 return
311 }
312 sig.PreferredCompression = make([]byte, len(subpacket))
313 copy(sig.PreferredCompression, subpacket)
314 case primaryUserIdSubpacket:
315 // Primary User ID, section 5.2.3.19
316 if !isHashed {
317 return
318 }
319 if len(subpacket) != 1 {
320 err = errors.StructuralError("primary user id subpacket with bad length")
321 return
322 }
323 sig.IsPrimaryId = new(bool)
324 if subpacket[0] > 0 {
325 *sig.IsPrimaryId = true
326 }
327 case keyFlagsSubpacket:
328 // Key flags, section 5.2.3.21
329 if !isHashed {
330 return
331 }
332 if len(subpacket) == 0 {
333 err = errors.StructuralError("empty key flags subpacket")
334 return
335 }
336 sig.FlagsValid = true
337 if subpacket[0]&KeyFlagCertify != 0 {
338 sig.FlagCertify = true
339 }
340 if subpacket[0]&KeyFlagSign != 0 {
341 sig.FlagSign = true
342 }
343 if subpacket[0]&KeyFlagEncryptCommunications != 0 {
344 sig.FlagEncryptCommunications = true
345 }
346 if subpacket[0]&KeyFlagEncryptStorage != 0 {
347 sig.FlagEncryptStorage = true
348 }
349 case reasonForRevocationSubpacket:
350 // Reason For Revocation, section 5.2.3.23
351 if !isHashed {
352 return
353 }
354 if len(subpacket) == 0 {
355 err = errors.StructuralError("empty revocation reason subpacket")
356 return
357 }
358 sig.RevocationReason = new(uint8)
359 *sig.RevocationReason = subpacket[0]
360 sig.RevocationReasonText = string(subpacket[1:])
361 case featuresSubpacket:
362 // Features subpacket, section 5.2.3.24 specifies a very general
363 // mechanism for OpenPGP implementations to signal support for new
364 // features. In practice, the subpacket is used exclusively to
365 // indicate support for MDC-protected encryption.
366 sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1
367 case embeddedSignatureSubpacket:
368 // Only usage is in signatures that cross-certify
369 // signing subkeys. section 5.2.3.26 describes the
370 // format, with its usage described in section 11.1
371 if sig.EmbeddedSignature != nil {
372 err = errors.StructuralError("Cannot have multiple embedded signatures")
373 return
374 }
375 sig.EmbeddedSignature = new(Signature)
376 // Embedded signatures are required to be v4 signatures see
377 // section 12.1. However, we only parse v4 signatures in this
378 // file anyway.
379 if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil {
380 return nil, err
381 }
382 if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding {
383 return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType)))
384 }
385 default:
386 if isCritical {
387 err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
388 return
389 }
390 }
391 return
392
393Truncated:
394 err = errors.StructuralError("signature subpacket truncated")
395 return
396}
397
398// subpacketLengthLength returns the length, in bytes, of an encoded length value.
399func subpacketLengthLength(length int) int {
400 if length < 192 {
401 return 1
402 }
403 if length < 16320 {
404 return 2
405 }
406 return 5
407}
408
409// serializeSubpacketLength marshals the given length into to.
410func serializeSubpacketLength(to []byte, length int) int {
411 // RFC 4880, Section 4.2.2.
412 if length < 192 {
413 to[0] = byte(length)
414 return 1
415 }
416 if length < 16320 {
417 length -= 192
418 to[0] = byte((length >> 8) + 192)
419 to[1] = byte(length)
420 return 2
421 }
422 to[0] = 255
423 to[1] = byte(length >> 24)
424 to[2] = byte(length >> 16)
425 to[3] = byte(length >> 8)
426 to[4] = byte(length)
427 return 5
428}
429
430// subpacketsLength returns the serialized length, in bytes, of the given
431// subpackets.
432func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
433 for _, subpacket := range subpackets {
434 if subpacket.hashed == hashed {
435 length += subpacketLengthLength(len(subpacket.contents) + 1)
436 length += 1 // type byte
437 length += len(subpacket.contents)
438 }
439 }
440 return
441}
442
443// serializeSubpackets marshals the given subpackets into to.
444func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
445 for _, subpacket := range subpackets {
446 if subpacket.hashed == hashed {
447 n := serializeSubpacketLength(to, len(subpacket.contents)+1)
448 to[n] = byte(subpacket.subpacketType)
449 to = to[1+n:]
450 n = copy(to, subpacket.contents)
451 to = to[n:]
452 }
453 }
454 return
455}
456
457// KeyExpired returns whether sig is a self-signature of a key that has
458// expired.
459func (sig *Signature) KeyExpired(currentTime time.Time) bool {
460 if sig.KeyLifetimeSecs == nil {
461 return false
462 }
463 expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
464 return currentTime.After(expiry)
465}
466
467// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
468func (sig *Signature) buildHashSuffix() (err error) {
469 hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
470
471 var ok bool
472 l := 6 + hashedSubpacketsLen
473 sig.HashSuffix = make([]byte, l+6)
474 sig.HashSuffix[0] = 4
475 sig.HashSuffix[1] = uint8(sig.SigType)
476 sig.HashSuffix[2] = uint8(sig.PubKeyAlgo)
477 sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash)
478 if !ok {
479 sig.HashSuffix = nil
480 return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
481 }
482 sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8)
483 sig.HashSuffix[5] = byte(hashedSubpacketsLen)
484 serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true)
485 trailer := sig.HashSuffix[l:]
486 trailer[0] = 4
487 trailer[1] = 0xff
488 trailer[2] = byte(l >> 24)
489 trailer[3] = byte(l >> 16)
490 trailer[4] = byte(l >> 8)
491 trailer[5] = byte(l)
492 return
493}
494
495func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
496 err = sig.buildHashSuffix()
497 if err != nil {
498 return
499 }
500
501 h.Write(sig.HashSuffix)
502 digest = h.Sum(nil)
503 copy(sig.HashTag[:], digest)
504 return
505}
506
507// Sign signs a message with a private key. The hash, h, must contain
508// the hash of the message to be signed and will be mutated by this function.
509// On success, the signature is stored in sig. Call Serialize to write it out.
510// If config is nil, sensible defaults will be used.
511func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
512 sig.outSubpackets = sig.buildSubpackets()
513 digest, err := sig.signPrepareHash(h)
514 if err != nil {
515 return
516 }
517
518 switch priv.PubKeyAlgo {
519 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
520 // supports both *rsa.PrivateKey and crypto.Signer
521 sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
522 sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
523 case PubKeyAlgoDSA:
524 dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
525
526 // Need to truncate hashBytes to match FIPS 186-3 section 4.6.
527 subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
528 if len(digest) > subgroupSize {
529 digest = digest[:subgroupSize]
530 }
531 r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
532 if err == nil {
533 sig.DSASigR.bytes = r.Bytes()
534 sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes))
535 sig.DSASigS.bytes = s.Bytes()
536 sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
537 }
538 case PubKeyAlgoECDSA:
539 var r, s *big.Int
540 if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok {
541 // direct support, avoid asn1 wrapping/unwrapping
542 r, s, err = ecdsa.Sign(config.Random(), pk, digest)
543 } else {
544 var b []byte
545 b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, nil)
546 if err == nil {
547 r, s, err = unwrapECDSASig(b)
548 }
549 }
550 if err == nil {
551 sig.ECDSASigR = fromBig(r)
552 sig.ECDSASigS = fromBig(s)
553 }
554 default:
555 err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
556 }
557
558 return
559}
560
561// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA
562// signature.
563func unwrapECDSASig(b []byte) (r, s *big.Int, err error) {
564 var ecsdaSig struct {
565 R, S *big.Int
566 }
567 _, err = asn1.Unmarshal(b, &ecsdaSig)
568 if err != nil {
569 return
570 }
571 return ecsdaSig.R, ecsdaSig.S, nil
572}
573
574// SignUserId computes a signature from priv, asserting that pub is a valid
575// key for the identity id. On success, the signature is stored in sig. Call
576// Serialize to write it out.
577// If config is nil, sensible defaults will be used.
578func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
579 h, err := userIdSignatureHash(id, pub, sig.Hash)
580 if err != nil {
581 return err
582 }
583 return sig.Sign(h, priv, config)
584}
585
586// SignKey computes a signature from priv, asserting that pub is a subkey. On
587// success, the signature is stored in sig. Call Serialize to write it out.
588// If config is nil, sensible defaults will be used.
589func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
590 h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash)
591 if err != nil {
592 return err
593 }
594 return sig.Sign(h, priv, config)
595}
596
597// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
598// called first.
599func (sig *Signature) Serialize(w io.Writer) (err error) {
600 if len(sig.outSubpackets) == 0 {
601 sig.outSubpackets = sig.rawSubpackets
602 }
603 if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil {
604 return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
605 }
606
607 sigLength := 0
608 switch sig.PubKeyAlgo {
609 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
610 sigLength = 2 + len(sig.RSASignature.bytes)
611 case PubKeyAlgoDSA:
612 sigLength = 2 + len(sig.DSASigR.bytes)
613 sigLength += 2 + len(sig.DSASigS.bytes)
614 case PubKeyAlgoECDSA:
615 sigLength = 2 + len(sig.ECDSASigR.bytes)
616 sigLength += 2 + len(sig.ECDSASigS.bytes)
617 default:
618 panic("impossible")
619 }
620
621 unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
622 length := len(sig.HashSuffix) - 6 /* trailer not included */ +
623 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
624 2 /* hash tag */ + sigLength
625 err = serializeHeader(w, packetTypeSignature, length)
626 if err != nil {
627 return
628 }
629
630 _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6])
631 if err != nil {
632 return
633 }
634
635 unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen)
636 unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
637 unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
638 serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
639
640 _, err = w.Write(unhashedSubpackets)
641 if err != nil {
642 return
643 }
644 _, err = w.Write(sig.HashTag[:])
645 if err != nil {
646 return
647 }
648
649 switch sig.PubKeyAlgo {
650 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
651 err = writeMPIs(w, sig.RSASignature)
652 case PubKeyAlgoDSA:
653 err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
654 case PubKeyAlgoECDSA:
655 err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS)
656 default:
657 panic("impossible")
658 }
659 return
660}
661
662// outputSubpacket represents a subpacket to be marshaled.
663type outputSubpacket struct {
664 hashed bool // true if this subpacket is in the hashed area.
665 subpacketType signatureSubpacketType
666 isCritical bool
667 contents []byte
668}
669
670func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) {
671 creationTime := make([]byte, 4)
672 binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
673 subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime})
674
675 if sig.IssuerKeyId != nil {
676 keyId := make([]byte, 8)
677 binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
678 subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId})
679 }
680
681 if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
682 sigLifetime := make([]byte, 4)
683 binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
684 subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
685 }
686
687 // Key flags may only appear in self-signatures or certification signatures.
688
689 if sig.FlagsValid {
690 var flags byte
691 if sig.FlagCertify {
692 flags |= KeyFlagCertify
693 }
694 if sig.FlagSign {
695 flags |= KeyFlagSign
696 }
697 if sig.FlagEncryptCommunications {
698 flags |= KeyFlagEncryptCommunications
699 }
700 if sig.FlagEncryptStorage {
701 flags |= KeyFlagEncryptStorage
702 }
703 subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}})
704 }
705
706 // The following subpackets may only appear in self-signatures
707
708 if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
709 keyLifetime := make([]byte, 4)
710 binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
711 subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
712 }
713
714 if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
715 subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
716 }
717
718 if len(sig.PreferredSymmetric) > 0 {
719 subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
720 }
721
722 if len(sig.PreferredHash) > 0 {
723 subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
724 }
725
726 if len(sig.PreferredCompression) > 0 {
727 subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
728 }
729
730 return
731}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go
new file mode 100644
index 0000000..6edff88
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go
@@ -0,0 +1,146 @@
1// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "crypto"
9 "encoding/binary"
10 "fmt"
11 "io"
12 "strconv"
13 "time"
14
15 "golang.org/x/crypto/openpgp/errors"
16 "golang.org/x/crypto/openpgp/s2k"
17)
18
19// SignatureV3 represents older version 3 signatures. These signatures are less secure
20// than version 4 and should not be used to create new signatures. They are included
21// here for backwards compatibility to read and validate with older key material.
22// See RFC 4880, section 5.2.2.
23type SignatureV3 struct {
24 SigType SignatureType
25 CreationTime time.Time
26 IssuerKeyId uint64
27 PubKeyAlgo PublicKeyAlgorithm
28 Hash crypto.Hash
29 HashTag [2]byte
30
31 RSASignature parsedMPI
32 DSASigR, DSASigS parsedMPI
33}
34
35func (sig *SignatureV3) parse(r io.Reader) (err error) {
36 // RFC 4880, section 5.2.2
37 var buf [8]byte
38 if _, err = readFull(r, buf[:1]); err != nil {
39 return
40 }
41 if buf[0] < 2 || buf[0] > 3 {
42 err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
43 return
44 }
45 if _, err = readFull(r, buf[:1]); err != nil {
46 return
47 }
48 if buf[0] != 5 {
49 err = errors.UnsupportedError(
50 "invalid hashed material length " + strconv.Itoa(int(buf[0])))
51 return
52 }
53
54 // Read hashed material: signature type + creation time
55 if _, err = readFull(r, buf[:5]); err != nil {
56 return
57 }
58 sig.SigType = SignatureType(buf[0])
59 t := binary.BigEndian.Uint32(buf[1:5])
60 sig.CreationTime = time.Unix(int64(t), 0)
61
62 // Eight-octet Key ID of signer.
63 if _, err = readFull(r, buf[:8]); err != nil {
64 return
65 }
66 sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:])
67
68 // Public-key and hash algorithm
69 if _, err = readFull(r, buf[:2]); err != nil {
70 return
71 }
72 sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0])
73 switch sig.PubKeyAlgo {
74 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA:
75 default:
76 err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
77 return
78 }
79 var ok bool
80 if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok {
81 return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
82 }
83
84 // Two-octet field holding left 16 bits of signed hash value.
85 if _, err = readFull(r, sig.HashTag[:2]); err != nil {
86 return
87 }
88
89 switch sig.PubKeyAlgo {
90 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
91 sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r)
92 case PubKeyAlgoDSA:
93 if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil {
94 return
95 }
96 sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r)
97 default:
98 panic("unreachable")
99 }
100 return
101}
102
103// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
104// called first.
105func (sig *SignatureV3) Serialize(w io.Writer) (err error) {
106 buf := make([]byte, 8)
107
108 // Write the sig type and creation time
109 buf[0] = byte(sig.SigType)
110 binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix()))
111 if _, err = w.Write(buf[:5]); err != nil {
112 return
113 }
114
115 // Write the issuer long key ID
116 binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId)
117 if _, err = w.Write(buf[:8]); err != nil {
118 return
119 }
120
121 // Write public key algorithm, hash ID, and hash value
122 buf[0] = byte(sig.PubKeyAlgo)
123 hashId, ok := s2k.HashToHashId(sig.Hash)
124 if !ok {
125 return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash))
126 }
127 buf[1] = hashId
128 copy(buf[2:4], sig.HashTag[:])
129 if _, err = w.Write(buf[:4]); err != nil {
130 return
131 }
132
133 if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil {
134 return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
135 }
136
137 switch sig.PubKeyAlgo {
138 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
139 err = writeMPIs(w, sig.RSASignature)
140 case PubKeyAlgoDSA:
141 err = writeMPIs(w, sig.DSASigR, sig.DSASigS)
142 default:
143 panic("impossible")
144 }
145 return
146}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go
new file mode 100644
index 0000000..744c2d2
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go
@@ -0,0 +1,155 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "bytes"
9 "crypto/cipher"
10 "io"
11 "strconv"
12
13 "golang.org/x/crypto/openpgp/errors"
14 "golang.org/x/crypto/openpgp/s2k"
15)
16
17// This is the largest session key that we'll support. Since no 512-bit cipher
18// has even been seriously used, this is comfortably large.
19const maxSessionKeySizeInBytes = 64
20
21// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
22// 4880, section 5.3.
23type SymmetricKeyEncrypted struct {
24 CipherFunc CipherFunction
25 s2k func(out, in []byte)
26 encryptedKey []byte
27}
28
29const symmetricKeyEncryptedVersion = 4
30
31func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
32 // RFC 4880, section 5.3.
33 var buf [2]byte
34 if _, err := readFull(r, buf[:]); err != nil {
35 return err
36 }
37 if buf[0] != symmetricKeyEncryptedVersion {
38 return errors.UnsupportedError("SymmetricKeyEncrypted version")
39 }
40 ske.CipherFunc = CipherFunction(buf[1])
41
42 if ske.CipherFunc.KeySize() == 0 {
43 return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1])))
44 }
45
46 var err error
47 ske.s2k, err = s2k.Parse(r)
48 if err != nil {
49 return err
50 }
51
52 encryptedKey := make([]byte, maxSessionKeySizeInBytes)
53 // The session key may follow. We just have to try and read to find
54 // out. If it exists then we limit it to maxSessionKeySizeInBytes.
55 n, err := readFull(r, encryptedKey)
56 if err != nil && err != io.ErrUnexpectedEOF {
57 return err
58 }
59
60 if n != 0 {
61 if n == maxSessionKeySizeInBytes {
62 return errors.UnsupportedError("oversized encrypted session key")
63 }
64 ske.encryptedKey = encryptedKey[:n]
65 }
66
67 return nil
68}
69
70// Decrypt attempts to decrypt an encrypted session key and returns the key and
71// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data
72// packet.
73func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) {
74 key := make([]byte, ske.CipherFunc.KeySize())
75 ske.s2k(key, passphrase)
76
77 if len(ske.encryptedKey) == 0 {
78 return key, ske.CipherFunc, nil
79 }
80
81 // the IV is all zeros
82 iv := make([]byte, ske.CipherFunc.blockSize())
83 c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
84 plaintextKey := make([]byte, len(ske.encryptedKey))
85 c.XORKeyStream(plaintextKey, ske.encryptedKey)
86 cipherFunc := CipherFunction(plaintextKey[0])
87 if cipherFunc.blockSize() == 0 {
88 return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
89 }
90 plaintextKey = plaintextKey[1:]
91 if l, cipherKeySize := len(plaintextKey), cipherFunc.KeySize(); l != cipherFunc.KeySize() {
92 return nil, cipherFunc, errors.StructuralError("length of decrypted key (" + strconv.Itoa(l) + ") " +
93 "not equal to cipher keysize (" + strconv.Itoa(cipherKeySize) + ")")
94 }
95 return plaintextKey, cipherFunc, nil
96}
97
98// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The
99// packet contains a random session key, encrypted by a key derived from the
100// given passphrase. The session key is returned and must be passed to
101// SerializeSymmetricallyEncrypted.
102// If config is nil, sensible defaults will be used.
103func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) {
104 cipherFunc := config.Cipher()
105 keySize := cipherFunc.KeySize()
106 if keySize == 0 {
107 return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc)))
108 }
109
110 s2kBuf := new(bytes.Buffer)
111 keyEncryptingKey := make([]byte, keySize)
112 // s2k.Serialize salts and stretches the passphrase, and writes the
113 // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
114 err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()})
115 if err != nil {
116 return
117 }
118 s2kBytes := s2kBuf.Bytes()
119
120 packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
121 err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
122 if err != nil {
123 return
124 }
125
126 var buf [2]byte
127 buf[0] = symmetricKeyEncryptedVersion
128 buf[1] = byte(cipherFunc)
129 _, err = w.Write(buf[:])
130 if err != nil {
131 return
132 }
133 _, err = w.Write(s2kBytes)
134 if err != nil {
135 return
136 }
137
138 sessionKey := make([]byte, keySize)
139 _, err = io.ReadFull(config.Random(), sessionKey)
140 if err != nil {
141 return
142 }
143 iv := make([]byte, cipherFunc.blockSize())
144 c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
145 encryptedCipherAndKey := make([]byte, keySize+1)
146 c.XORKeyStream(encryptedCipherAndKey, buf[1:])
147 c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
148 _, err = w.Write(encryptedCipherAndKey)
149 if err != nil {
150 return
151 }
152
153 key = sessionKey
154 return
155}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go
new file mode 100644
index 0000000..6126030
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go
@@ -0,0 +1,290 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "crypto/cipher"
9 "crypto/sha1"
10 "crypto/subtle"
11 "golang.org/x/crypto/openpgp/errors"
12 "hash"
13 "io"
14 "strconv"
15)
16
17// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
18// encrypted contents will consist of more OpenPGP packets. See RFC 4880,
19// sections 5.7 and 5.13.
20type SymmetricallyEncrypted struct {
21 MDC bool // true iff this is a type 18 packet and thus has an embedded MAC.
22 contents io.Reader
23 prefix []byte
24}
25
26const symmetricallyEncryptedVersion = 1
27
28func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
29 if se.MDC {
30 // See RFC 4880, section 5.13.
31 var buf [1]byte
32 _, err := readFull(r, buf[:])
33 if err != nil {
34 return err
35 }
36 if buf[0] != symmetricallyEncryptedVersion {
37 return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
38 }
39 }
40 se.contents = r
41 return nil
42}
43
44// Decrypt returns a ReadCloser, from which the decrypted contents of the
45// packet can be read. An incorrect key can, with high probability, be detected
46// immediately and this will result in a KeyIncorrect error being returned.
47func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) {
48 keySize := c.KeySize()
49 if keySize == 0 {
50 return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c)))
51 }
52 if len(key) != keySize {
53 return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
54 }
55
56 if se.prefix == nil {
57 se.prefix = make([]byte, c.blockSize()+2)
58 _, err := readFull(se.contents, se.prefix)
59 if err != nil {
60 return nil, err
61 }
62 } else if len(se.prefix) != c.blockSize()+2 {
63 return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths")
64 }
65
66 ocfbResync := OCFBResync
67 if se.MDC {
68 // MDC packets use a different form of OCFB mode.
69 ocfbResync = OCFBNoResync
70 }
71
72 s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
73 if s == nil {
74 return nil, errors.ErrKeyIncorrect
75 }
76
77 plaintext := cipher.StreamReader{S: s, R: se.contents}
78
79 if se.MDC {
80 // MDC packets have an embedded hash that we need to check.
81 h := sha1.New()
82 h.Write(se.prefix)
83 return &seMDCReader{in: plaintext, h: h}, nil
84 }
85
86 // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser.
87 return seReader{plaintext}, nil
88}
89
90// seReader wraps an io.Reader with a no-op Close method.
91type seReader struct {
92 in io.Reader
93}
94
95func (ser seReader) Read(buf []byte) (int, error) {
96 return ser.in.Read(buf)
97}
98
99func (ser seReader) Close() error {
100 return nil
101}
102
103const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
104
105// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
106// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
107// MDC packet containing a hash of the previous contents which is checked
108// against the running hash. See RFC 4880, section 5.13.
109type seMDCReader struct {
110 in io.Reader
111 h hash.Hash
112 trailer [mdcTrailerSize]byte
113 scratch [mdcTrailerSize]byte
114 trailerUsed int
115 error bool
116 eof bool
117}
118
119func (ser *seMDCReader) Read(buf []byte) (n int, err error) {
120 if ser.error {
121 err = io.ErrUnexpectedEOF
122 return
123 }
124 if ser.eof {
125 err = io.EOF
126 return
127 }
128
129 // If we haven't yet filled the trailer buffer then we must do that
130 // first.
131 for ser.trailerUsed < mdcTrailerSize {
132 n, err = ser.in.Read(ser.trailer[ser.trailerUsed:])
133 ser.trailerUsed += n
134 if err == io.EOF {
135 if ser.trailerUsed != mdcTrailerSize {
136 n = 0
137 err = io.ErrUnexpectedEOF
138 ser.error = true
139 return
140 }
141 ser.eof = true
142 n = 0
143 return
144 }
145
146 if err != nil {
147 n = 0
148 return
149 }
150 }
151
152 // If it's a short read then we read into a temporary buffer and shift
153 // the data into the caller's buffer.
154 if len(buf) <= mdcTrailerSize {
155 n, err = readFull(ser.in, ser.scratch[:len(buf)])
156 copy(buf, ser.trailer[:n])
157 ser.h.Write(buf[:n])
158 copy(ser.trailer[:], ser.trailer[n:])
159 copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:])
160 if n < len(buf) {
161 ser.eof = true
162 err = io.EOF
163 }
164 return
165 }
166
167 n, err = ser.in.Read(buf[mdcTrailerSize:])
168 copy(buf, ser.trailer[:])
169 ser.h.Write(buf[:n])
170 copy(ser.trailer[:], buf[n:])
171
172 if err == io.EOF {
173 ser.eof = true
174 }
175 return
176}
177
178// This is a new-format packet tag byte for a type 19 (MDC) packet.
179const mdcPacketTagByte = byte(0x80) | 0x40 | 19
180
181func (ser *seMDCReader) Close() error {
182 if ser.error {
183 return errors.SignatureError("error during reading")
184 }
185
186 for !ser.eof {
187 // We haven't seen EOF so we need to read to the end
188 var buf [1024]byte
189 _, err := ser.Read(buf[:])
190 if err == io.EOF {
191 break
192 }
193 if err != nil {
194 return errors.SignatureError("error during reading")
195 }
196 }
197
198 if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
199 return errors.SignatureError("MDC packet not found")
200 }
201 ser.h.Write(ser.trailer[:2])
202
203 final := ser.h.Sum(nil)
204 if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
205 return errors.SignatureError("hash mismatch")
206 }
207 return nil
208}
209
210// An seMDCWriter writes through to an io.WriteCloser while maintains a running
211// hash of the data written. On close, it emits an MDC packet containing the
212// running hash.
213type seMDCWriter struct {
214 w io.WriteCloser
215 h hash.Hash
216}
217
218func (w *seMDCWriter) Write(buf []byte) (n int, err error) {
219 w.h.Write(buf)
220 return w.w.Write(buf)
221}
222
223func (w *seMDCWriter) Close() (err error) {
224 var buf [mdcTrailerSize]byte
225
226 buf[0] = mdcPacketTagByte
227 buf[1] = sha1.Size
228 w.h.Write(buf[:2])
229 digest := w.h.Sum(nil)
230 copy(buf[2:], digest)
231
232 _, err = w.w.Write(buf[:])
233 if err != nil {
234 return
235 }
236 return w.w.Close()
237}
238
239// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
240type noOpCloser struct {
241 w io.Writer
242}
243
244func (c noOpCloser) Write(data []byte) (n int, err error) {
245 return c.w.Write(data)
246}
247
248func (c noOpCloser) Close() error {
249 return nil
250}
251
252// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
253// to w and returns a WriteCloser to which the to-be-encrypted packets can be
254// written.
255// If config is nil, sensible defaults will be used.
256func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) {
257 if c.KeySize() != len(key) {
258 return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length")
259 }
260 writeCloser := noOpCloser{w}
261 ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC)
262 if err != nil {
263 return
264 }
265
266 _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion})
267 if err != nil {
268 return
269 }
270
271 block := c.new(key)
272 blockSize := block.BlockSize()
273 iv := make([]byte, blockSize)
274 _, err = config.Random().Read(iv)
275 if err != nil {
276 return
277 }
278 s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync)
279 _, err = ciphertext.Write(prefix)
280 if err != nil {
281 return
282 }
283 plaintext := cipher.StreamWriter{S: s, W: ciphertext}
284
285 h := sha1.New()
286 h.Write(iv)
287 h.Write(iv[blockSize-2:])
288 contents = &seMDCWriter{w: plaintext, h: h}
289 return
290}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go b/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go
new file mode 100644
index 0000000..96a2b38
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go
@@ -0,0 +1,91 @@
1// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "bytes"
9 "image"
10 "image/jpeg"
11 "io"
12 "io/ioutil"
13)
14
15const UserAttrImageSubpacket = 1
16
17// UserAttribute is capable of storing other types of data about a user
18// beyond name, email and a text comment. In practice, user attributes are typically used
19// to store a signed thumbnail photo JPEG image of the user.
20// See RFC 4880, section 5.12.
21type UserAttribute struct {
22 Contents []*OpaqueSubpacket
23}
24
25// NewUserAttributePhoto creates a user attribute packet
26// containing the given images.
27func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) {
28 uat = new(UserAttribute)
29 for _, photo := range photos {
30 var buf bytes.Buffer
31 // RFC 4880, Section 5.12.1.
32 data := []byte{
33 0x10, 0x00, // Little-endian image header length (16 bytes)
34 0x01, // Image header version 1
35 0x01, // JPEG
36 0, 0, 0, 0, // 12 reserved octets, must be all zero.
37 0, 0, 0, 0,
38 0, 0, 0, 0}
39 if _, err = buf.Write(data); err != nil {
40 return
41 }
42 if err = jpeg.Encode(&buf, photo, nil); err != nil {
43 return
44 }
45 uat.Contents = append(uat.Contents, &OpaqueSubpacket{
46 SubType: UserAttrImageSubpacket,
47 Contents: buf.Bytes()})
48 }
49 return
50}
51
52// NewUserAttribute creates a new user attribute packet containing the given subpackets.
53func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute {
54 return &UserAttribute{Contents: contents}
55}
56
57func (uat *UserAttribute) parse(r io.Reader) (err error) {
58 // RFC 4880, section 5.13
59 b, err := ioutil.ReadAll(r)
60 if err != nil {
61 return
62 }
63 uat.Contents, err = OpaqueSubpackets(b)
64 return
65}
66
67// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including
68// header.
69func (uat *UserAttribute) Serialize(w io.Writer) (err error) {
70 var buf bytes.Buffer
71 for _, sp := range uat.Contents {
72 sp.Serialize(&buf)
73 }
74 if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil {
75 return err
76 }
77 _, err = w.Write(buf.Bytes())
78 return
79}
80
81// ImageData returns zero or more byte slices, each containing
82// JPEG File Interchange Format (JFIF), for each photo in the
83// the user attribute packet.
84func (uat *UserAttribute) ImageData() (imageData [][]byte) {
85 for _, sp := range uat.Contents {
86 if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 {
87 imageData = append(imageData, sp.Contents[16:])
88 }
89 }
90 return
91}
diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userid.go b/vendor/golang.org/x/crypto/openpgp/packet/userid.go
new file mode 100644
index 0000000..d6bea7d
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/packet/userid.go
@@ -0,0 +1,160 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package packet
6
7import (
8 "io"
9 "io/ioutil"
10 "strings"
11)
12
13// UserId contains text that is intended to represent the name and email
14// address of the key holder. See RFC 4880, section 5.11. By convention, this
15// takes the form "Full Name (Comment) <email@example.com>"
16type UserId struct {
17 Id string // By convention, this takes the form "Full Name (Comment) <email@example.com>" which is split out in the fields below.
18
19 Name, Comment, Email string
20}
21
22func hasInvalidCharacters(s string) bool {
23 for _, c := range s {
24 switch c {
25 case '(', ')', '<', '>', 0:
26 return true
27 }
28 }
29 return false
30}
31
32// NewUserId returns a UserId or nil if any of the arguments contain invalid
33// characters. The invalid characters are '\x00', '(', ')', '<' and '>'
34func NewUserId(name, comment, email string) *UserId {
35 // RFC 4880 doesn't deal with the structure of userid strings; the
36 // name, comment and email form is just a convention. However, there's
37 // no convention about escaping the metacharacters and GPG just refuses
38 // to create user ids where, say, the name contains a '('. We mirror
39 // this behaviour.
40
41 if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) {
42 return nil
43 }
44
45 uid := new(UserId)
46 uid.Name, uid.Comment, uid.Email = name, comment, email
47 uid.Id = name
48 if len(comment) > 0 {
49 if len(uid.Id) > 0 {
50 uid.Id += " "
51 }
52 uid.Id += "("
53 uid.Id += comment
54 uid.Id += ")"
55 }
56 if len(email) > 0 {
57 if len(uid.Id) > 0 {
58 uid.Id += " "
59 }
60 uid.Id += "<"
61 uid.Id += email
62 uid.Id += ">"
63 }
64 return uid
65}
66
67func (uid *UserId) parse(r io.Reader) (err error) {
68 // RFC 4880, section 5.11
69 b, err := ioutil.ReadAll(r)
70 if err != nil {
71 return
72 }
73 uid.Id = string(b)
74 uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id)
75 return
76}
77
78// Serialize marshals uid to w in the form of an OpenPGP packet, including
79// header.
80func (uid *UserId) Serialize(w io.Writer) error {
81 err := serializeHeader(w, packetTypeUserId, len(uid.Id))
82 if err != nil {
83 return err
84 }
85 _, err = w.Write([]byte(uid.Id))
86 return err
87}
88
89// parseUserId extracts the name, comment and email from a user id string that
90// is formatted as "Full Name (Comment) <email@example.com>".
91func parseUserId(id string) (name, comment, email string) {
92 var n, c, e struct {
93 start, end int
94 }
95 var state int
96
97 for offset, rune := range id {
98 switch state {
99 case 0:
100 // Entering name
101 n.start = offset
102 state = 1
103 fallthrough
104 case 1:
105 // In name
106 if rune == '(' {
107 state = 2
108 n.end = offset
109 } else if rune == '<' {
110 state = 5
111 n.end = offset
112 }
113 case 2:
114 // Entering comment
115 c.start = offset
116 state = 3
117 fallthrough
118 case 3:
119 // In comment
120 if rune == ')' {
121 state = 4
122 c.end = offset
123 }
124 case 4:
125 // Between comment and email
126 if rune == '<' {
127 state = 5
128 }
129 case 5:
130 // Entering email
131 e.start = offset
132 state = 6
133 fallthrough
134 case 6:
135 // In email
136 if rune == '>' {
137 state = 7
138 e.end = offset
139 }
140 default:
141 // After email
142 }
143 }
144 switch state {
145 case 1:
146 // ended in the name
147 n.end = len(id)
148 case 3:
149 // ended in comment
150 c.end = len(id)
151 case 6:
152 // ended in email
153 e.end = len(id)
154 }
155
156 name = strings.TrimSpace(id[n.start:n.end])
157 comment = strings.TrimSpace(id[c.start:c.end])
158 email = strings.TrimSpace(id[e.start:e.end])
159 return
160}
diff --git a/vendor/golang.org/x/crypto/openpgp/read.go b/vendor/golang.org/x/crypto/openpgp/read.go
new file mode 100644
index 0000000..6ec664f
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/read.go
@@ -0,0 +1,442 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package openpgp implements high level operations on OpenPGP messages.
6package openpgp // import "golang.org/x/crypto/openpgp"
7
8import (
9 "crypto"
10 _ "crypto/sha256"
11 "hash"
12 "io"
13 "strconv"
14
15 "golang.org/x/crypto/openpgp/armor"
16 "golang.org/x/crypto/openpgp/errors"
17 "golang.org/x/crypto/openpgp/packet"
18)
19
20// SignatureType is the armor type for a PGP signature.
21var SignatureType = "PGP SIGNATURE"
22
23// readArmored reads an armored block with the given type.
24func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) {
25 block, err := armor.Decode(r)
26 if err != nil {
27 return
28 }
29
30 if block.Type != expectedType {
31 return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
32 }
33
34 return block.Body, nil
35}
36
37// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
38// signed message.
39type MessageDetails struct {
40 IsEncrypted bool // true if the message was encrypted.
41 EncryptedToKeyIds []uint64 // the list of recipient key ids.
42 IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message.
43 DecryptedWith Key // the private key used to decrypt the message, if any.
44 IsSigned bool // true if the message is signed.
45 SignedByKeyId uint64 // the key id of the signer, if any.
46 SignedBy *Key // the key of the signer, if available.
47 LiteralData *packet.LiteralData // the metadata of the contents
48 UnverifiedBody io.Reader // the contents of the message.
49
50 // If IsSigned is true and SignedBy is non-zero then the signature will
51 // be verified as UnverifiedBody is read. The signature cannot be
52 // checked until the whole of UnverifiedBody is read so UnverifiedBody
53 // must be consumed until EOF before the data can be trusted. Even if a
54 // message isn't signed (or the signer is unknown) the data may contain
55 // an authentication code that is only checked once UnverifiedBody has
56 // been consumed. Once EOF has been seen, the following fields are
57 // valid. (An authentication code failure is reported as a
58 // SignatureError error when reading from UnverifiedBody.)
59 SignatureError error // nil if the signature is good.
60 Signature *packet.Signature // the signature packet itself, if v4 (default)
61 SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature
62
63 decrypted io.ReadCloser
64}
65
66// A PromptFunction is used as a callback by functions that may need to decrypt
67// a private key, or prompt for a passphrase. It is called with a list of
68// acceptable, encrypted private keys and a boolean that indicates whether a
69// passphrase is usable. It should either decrypt a private key or return a
70// passphrase to try. If the decrypted private key or given passphrase isn't
71// correct, the function will be called again, forever. Any error returned will
72// be passed up.
73type PromptFunction func(keys []Key, symmetric bool) ([]byte, error)
74
75// A keyEnvelopePair is used to store a private key with the envelope that
76// contains a symmetric key, encrypted with that key.
77type keyEnvelopePair struct {
78 key Key
79 encryptedKey *packet.EncryptedKey
80}
81
82// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
83// The given KeyRing should contain both public keys (for signature
84// verification) and, possibly encrypted, private keys for decrypting.
85// If config is nil, sensible defaults will be used.
86func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) {
87 var p packet.Packet
88
89 var symKeys []*packet.SymmetricKeyEncrypted
90 var pubKeys []keyEnvelopePair
91 var se *packet.SymmetricallyEncrypted
92
93 packets := packet.NewReader(r)
94 md = new(MessageDetails)
95 md.IsEncrypted = true
96
97 // The message, if encrypted, starts with a number of packets
98 // containing an encrypted decryption key. The decryption key is either
99 // encrypted to a public key, or with a passphrase. This loop
100 // collects these packets.
101ParsePackets:
102 for {
103 p, err = packets.Next()
104 if err != nil {
105 return nil, err
106 }
107 switch p := p.(type) {
108 case *packet.SymmetricKeyEncrypted:
109 // This packet contains the decryption key encrypted with a passphrase.
110 md.IsSymmetricallyEncrypted = true
111 symKeys = append(symKeys, p)
112 case *packet.EncryptedKey:
113 // This packet contains the decryption key encrypted to a public key.
114 md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
115 switch p.Algo {
116 case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal:
117 break
118 default:
119 continue
120 }
121 var keys []Key
122 if p.KeyId == 0 {
123 keys = keyring.DecryptionKeys()
124 } else {
125 keys = keyring.KeysById(p.KeyId)
126 }
127 for _, k := range keys {
128 pubKeys = append(pubKeys, keyEnvelopePair{k, p})
129 }
130 case *packet.SymmetricallyEncrypted:
131 se = p
132 break ParsePackets
133 case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
134 // This message isn't encrypted.
135 if len(symKeys) != 0 || len(pubKeys) != 0 {
136 return nil, errors.StructuralError("key material not followed by encrypted message")
137 }
138 packets.Unread(p)
139 return readSignedMessage(packets, nil, keyring)
140 }
141 }
142
143 var candidates []Key
144 var decrypted io.ReadCloser
145
146 // Now that we have the list of encrypted keys we need to decrypt at
147 // least one of them or, if we cannot, we need to call the prompt
148 // function so that it can decrypt a key or give us a passphrase.
149FindKey:
150 for {
151 // See if any of the keys already have a private key available
152 candidates = candidates[:0]
153 candidateFingerprints := make(map[string]bool)
154
155 for _, pk := range pubKeys {
156 if pk.key.PrivateKey == nil {
157 continue
158 }
159 if !pk.key.PrivateKey.Encrypted {
160 if len(pk.encryptedKey.Key) == 0 {
161 pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
162 }
163 if len(pk.encryptedKey.Key) == 0 {
164 continue
165 }
166 decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
167 if err != nil && err != errors.ErrKeyIncorrect {
168 return nil, err
169 }
170 if decrypted != nil {
171 md.DecryptedWith = pk.key
172 break FindKey
173 }
174 } else {
175 fpr := string(pk.key.PublicKey.Fingerprint[:])
176 if v := candidateFingerprints[fpr]; v {
177 continue
178 }
179 candidates = append(candidates, pk.key)
180 candidateFingerprints[fpr] = true
181 }
182 }
183
184 if len(candidates) == 0 && len(symKeys) == 0 {
185 return nil, errors.ErrKeyIncorrect
186 }
187
188 if prompt == nil {
189 return nil, errors.ErrKeyIncorrect
190 }
191
192 passphrase, err := prompt(candidates, len(symKeys) != 0)
193 if err != nil {
194 return nil, err
195 }
196
197 // Try the symmetric passphrase first
198 if len(symKeys) != 0 && passphrase != nil {
199 for _, s := range symKeys {
200 key, cipherFunc, err := s.Decrypt(passphrase)
201 if err == nil {
202 decrypted, err = se.Decrypt(cipherFunc, key)
203 if err != nil && err != errors.ErrKeyIncorrect {
204 return nil, err
205 }
206 if decrypted != nil {
207 break FindKey
208 }
209 }
210
211 }
212 }
213 }
214
215 md.decrypted = decrypted
216 if err := packets.Push(decrypted); err != nil {
217 return nil, err
218 }
219 return readSignedMessage(packets, md, keyring)
220}
221
222// readSignedMessage reads a possibly signed message if mdin is non-zero then
223// that structure is updated and returned. Otherwise a fresh MessageDetails is
224// used.
225func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) {
226 if mdin == nil {
227 mdin = new(MessageDetails)
228 }
229 md = mdin
230
231 var p packet.Packet
232 var h hash.Hash
233 var wrappedHash hash.Hash
234FindLiteralData:
235 for {
236 p, err = packets.Next()
237 if err != nil {
238 return nil, err
239 }
240 switch p := p.(type) {
241 case *packet.Compressed:
242 if err := packets.Push(p.Body); err != nil {
243 return nil, err
244 }
245 case *packet.OnePassSignature:
246 if !p.IsLast {
247 return nil, errors.UnsupportedError("nested signatures")
248 }
249
250 h, wrappedHash, err = hashForSignature(p.Hash, p.SigType)
251 if err != nil {
252 md = nil
253 return
254 }
255
256 md.IsSigned = true
257 md.SignedByKeyId = p.KeyId
258 keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
259 if len(keys) > 0 {
260 md.SignedBy = &keys[0]
261 }
262 case *packet.LiteralData:
263 md.LiteralData = p
264 break FindLiteralData
265 }
266 }
267
268 if md.SignedBy != nil {
269 md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md}
270 } else if md.decrypted != nil {
271 md.UnverifiedBody = checkReader{md}
272 } else {
273 md.UnverifiedBody = md.LiteralData.Body
274 }
275
276 return md, nil
277}
278
279// hashForSignature returns a pair of hashes that can be used to verify a
280// signature. The signature may specify that the contents of the signed message
281// should be preprocessed (i.e. to normalize line endings). Thus this function
282// returns two hashes. The second should be used to hash the message itself and
283// performs any needed preprocessing.
284func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) {
285 if !hashId.Available() {
286 return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId)))
287 }
288 h := hashId.New()
289
290 switch sigType {
291 case packet.SigTypeBinary:
292 return h, h, nil
293 case packet.SigTypeText:
294 return h, NewCanonicalTextHash(h), nil
295 }
296
297 return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
298}
299
300// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
301// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
302// MDC checks.
303type checkReader struct {
304 md *MessageDetails
305}
306
307func (cr checkReader) Read(buf []byte) (n int, err error) {
308 n, err = cr.md.LiteralData.Body.Read(buf)
309 if err == io.EOF {
310 mdcErr := cr.md.decrypted.Close()
311 if mdcErr != nil {
312 err = mdcErr
313 }
314 }
315 return
316}
317
318// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
319// the data as it is read. When it sees an EOF from the underlying io.Reader
320// it parses and checks a trailing Signature packet and triggers any MDC checks.
321type signatureCheckReader struct {
322 packets *packet.Reader
323 h, wrappedHash hash.Hash
324 md *MessageDetails
325}
326
327func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
328 n, err = scr.md.LiteralData.Body.Read(buf)
329 scr.wrappedHash.Write(buf[:n])
330 if err == io.EOF {
331 var p packet.Packet
332 p, scr.md.SignatureError = scr.packets.Next()
333 if scr.md.SignatureError != nil {
334 return
335 }
336
337 var ok bool
338 if scr.md.Signature, ok = p.(*packet.Signature); ok {
339 scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
340 } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok {
341 scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3)
342 } else {
343 scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
344 return
345 }
346
347 // The SymmetricallyEncrypted packet, if any, might have an
348 // unsigned hash of its own. In order to check this we need to
349 // close that Reader.
350 if scr.md.decrypted != nil {
351 mdcErr := scr.md.decrypted.Close()
352 if mdcErr != nil {
353 err = mdcErr
354 }
355 }
356 }
357 return
358}
359
360// CheckDetachedSignature takes a signed file and a detached signature and
361// returns the signer if the signature is valid. If the signer isn't known,
362// ErrUnknownIssuer is returned.
363func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
364 var issuerKeyId uint64
365 var hashFunc crypto.Hash
366 var sigType packet.SignatureType
367 var keys []Key
368 var p packet.Packet
369
370 packets := packet.NewReader(signature)
371 for {
372 p, err = packets.Next()
373 if err == io.EOF {
374 return nil, errors.ErrUnknownIssuer
375 }
376 if err != nil {
377 return nil, err
378 }
379
380 switch sig := p.(type) {
381 case *packet.Signature:
382 if sig.IssuerKeyId == nil {
383 return nil, errors.StructuralError("signature doesn't have an issuer")
384 }
385 issuerKeyId = *sig.IssuerKeyId
386 hashFunc = sig.Hash
387 sigType = sig.SigType
388 case *packet.SignatureV3:
389 issuerKeyId = sig.IssuerKeyId
390 hashFunc = sig.Hash
391 sigType = sig.SigType
392 default:
393 return nil, errors.StructuralError("non signature packet found")
394 }
395
396 keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign)
397 if len(keys) > 0 {
398 break
399 }
400 }
401
402 if len(keys) == 0 {
403 panic("unreachable")
404 }
405
406 h, wrappedHash, err := hashForSignature(hashFunc, sigType)
407 if err != nil {
408 return nil, err
409 }
410
411 if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF {
412 return nil, err
413 }
414
415 for _, key := range keys {
416 switch sig := p.(type) {
417 case *packet.Signature:
418 err = key.PublicKey.VerifySignature(h, sig)
419 case *packet.SignatureV3:
420 err = key.PublicKey.VerifySignatureV3(h, sig)
421 default:
422 panic("unreachable")
423 }
424
425 if err == nil {
426 return key.Entity, nil
427 }
428 }
429
430 return nil, err
431}
432
433// CheckArmoredDetachedSignature performs the same actions as
434// CheckDetachedSignature but expects the signature to be armored.
435func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) {
436 body, err := readArmored(signature, SignatureType)
437 if err != nil {
438 return
439 }
440
441 return CheckDetachedSignature(keyring, signed, body)
442}
diff --git a/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go
new file mode 100644
index 0000000..4b9a44c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go
@@ -0,0 +1,273 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package s2k implements the various OpenPGP string-to-key transforms as
6// specified in RFC 4800 section 3.7.1.
7package s2k // import "golang.org/x/crypto/openpgp/s2k"
8
9import (
10 "crypto"
11 "hash"
12 "io"
13 "strconv"
14
15 "golang.org/x/crypto/openpgp/errors"
16)
17
18// Config collects configuration parameters for s2k key-stretching
19// transformatioms. A nil *Config is valid and results in all default
20// values. Currently, Config is used only by the Serialize function in
21// this package.
22type Config struct {
23 // Hash is the default hash function to be used. If
24 // nil, SHA1 is used.
25 Hash crypto.Hash
26 // S2KCount is only used for symmetric encryption. It
27 // determines the strength of the passphrase stretching when
28 // the said passphrase is hashed to produce a key. S2KCount
29 // should be between 1024 and 65011712, inclusive. If Config
30 // is nil or S2KCount is 0, the value 65536 used. Not all
31 // values in the above range can be represented. S2KCount will
32 // be rounded up to the next representable value if it cannot
33 // be encoded exactly. When set, it is strongly encrouraged to
34 // use a value that is at least 65536. See RFC 4880 Section
35 // 3.7.1.3.
36 S2KCount int
37}
38
39func (c *Config) hash() crypto.Hash {
40 if c == nil || uint(c.Hash) == 0 {
41 // SHA1 is the historical default in this package.
42 return crypto.SHA1
43 }
44
45 return c.Hash
46}
47
48func (c *Config) encodedCount() uint8 {
49 if c == nil || c.S2KCount == 0 {
50 return 96 // The common case. Correspoding to 65536
51 }
52
53 i := c.S2KCount
54 switch {
55 // Behave like GPG. Should we make 65536 the lowest value used?
56 case i < 1024:
57 i = 1024
58 case i > 65011712:
59 i = 65011712
60 }
61
62 return encodeCount(i)
63}
64
65// encodeCount converts an iterative "count" in the range 1024 to
66// 65011712, inclusive, to an encoded count. The return value is the
67// octet that is actually stored in the GPG file. encodeCount panics
68// if i is not in the above range (encodedCount above takes care to
69// pass i in the correct range). See RFC 4880 Section 3.7.7.1.
70func encodeCount(i int) uint8 {
71 if i < 1024 || i > 65011712 {
72 panic("count arg i outside the required range")
73 }
74
75 for encoded := 0; encoded < 256; encoded++ {
76 count := decodeCount(uint8(encoded))
77 if count >= i {
78 return uint8(encoded)
79 }
80 }
81
82 return 255
83}
84
85// decodeCount returns the s2k mode 3 iterative "count" corresponding to
86// the encoded octet c.
87func decodeCount(c uint8) int {
88 return (16 + int(c&15)) << (uint32(c>>4) + 6)
89}
90
91// Simple writes to out the result of computing the Simple S2K function (RFC
92// 4880, section 3.7.1.1) using the given hash and input passphrase.
93func Simple(out []byte, h hash.Hash, in []byte) {
94 Salted(out, h, in, nil)
95}
96
97var zero [1]byte
98
99// Salted writes to out the result of computing the Salted S2K function (RFC
100// 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
101func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
102 done := 0
103 var digest []byte
104
105 for i := 0; done < len(out); i++ {
106 h.Reset()
107 for j := 0; j < i; j++ {
108 h.Write(zero[:])
109 }
110 h.Write(salt)
111 h.Write(in)
112 digest = h.Sum(digest[:0])
113 n := copy(out[done:], digest)
114 done += n
115 }
116}
117
118// Iterated writes to out the result of computing the Iterated and Salted S2K
119// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase,
120// salt and iteration count.
121func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
122 combined := make([]byte, len(in)+len(salt))
123 copy(combined, salt)
124 copy(combined[len(salt):], in)
125
126 if count < len(combined) {
127 count = len(combined)
128 }
129
130 done := 0
131 var digest []byte
132 for i := 0; done < len(out); i++ {
133 h.Reset()
134 for j := 0; j < i; j++ {
135 h.Write(zero[:])
136 }
137 written := 0
138 for written < count {
139 if written+len(combined) > count {
140 todo := count - written
141 h.Write(combined[:todo])
142 written = count
143 } else {
144 h.Write(combined)
145 written += len(combined)
146 }
147 }
148 digest = h.Sum(digest[:0])
149 n := copy(out[done:], digest)
150 done += n
151 }
152}
153
154// Parse reads a binary specification for a string-to-key transformation from r
155// and returns a function which performs that transform.
156func Parse(r io.Reader) (f func(out, in []byte), err error) {
157 var buf [9]byte
158
159 _, err = io.ReadFull(r, buf[:2])
160 if err != nil {
161 return
162 }
163
164 hash, ok := HashIdToHash(buf[1])
165 if !ok {
166 return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1])))
167 }
168 if !hash.Available() {
169 return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash)))
170 }
171 h := hash.New()
172
173 switch buf[0] {
174 case 0:
175 f := func(out, in []byte) {
176 Simple(out, h, in)
177 }
178 return f, nil
179 case 1:
180 _, err = io.ReadFull(r, buf[:8])
181 if err != nil {
182 return
183 }
184 f := func(out, in []byte) {
185 Salted(out, h, in, buf[:8])
186 }
187 return f, nil
188 case 3:
189 _, err = io.ReadFull(r, buf[:9])
190 if err != nil {
191 return
192 }
193 count := decodeCount(buf[8])
194 f := func(out, in []byte) {
195 Iterated(out, h, in, buf[:8], count)
196 }
197 return f, nil
198 }
199
200 return nil, errors.UnsupportedError("S2K function")
201}
202
203// Serialize salts and stretches the given passphrase and writes the
204// resulting key into key. It also serializes an S2K descriptor to
205// w. The key stretching can be configured with c, which may be
206// nil. In that case, sensible defaults will be used.
207func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error {
208 var buf [11]byte
209 buf[0] = 3 /* iterated and salted */
210 buf[1], _ = HashToHashId(c.hash())
211 salt := buf[2:10]
212 if _, err := io.ReadFull(rand, salt); err != nil {
213 return err
214 }
215 encodedCount := c.encodedCount()
216 count := decodeCount(encodedCount)
217 buf[10] = encodedCount
218 if _, err := w.Write(buf[:]); err != nil {
219 return err
220 }
221
222 Iterated(key, c.hash().New(), passphrase, salt, count)
223 return nil
224}
225
226// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with
227// Go's crypto.Hash type. See RFC 4880, section 9.4.
228var hashToHashIdMapping = []struct {
229 id byte
230 hash crypto.Hash
231 name string
232}{
233 {1, crypto.MD5, "MD5"},
234 {2, crypto.SHA1, "SHA1"},
235 {3, crypto.RIPEMD160, "RIPEMD160"},
236 {8, crypto.SHA256, "SHA256"},
237 {9, crypto.SHA384, "SHA384"},
238 {10, crypto.SHA512, "SHA512"},
239 {11, crypto.SHA224, "SHA224"},
240}
241
242// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
243// hash id.
244func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
245 for _, m := range hashToHashIdMapping {
246 if m.id == id {
247 return m.hash, true
248 }
249 }
250 return 0, false
251}
252
253// HashIdToString returns the name of the hash function corresponding to the
254// given OpenPGP hash id.
255func HashIdToString(id byte) (name string, ok bool) {
256 for _, m := range hashToHashIdMapping {
257 if m.id == id {
258 return m.name, true
259 }
260 }
261
262 return "", false
263}
264
265// HashIdToHash returns an OpenPGP hash id which corresponds the given Hash.
266func HashToHashId(h crypto.Hash) (id byte, ok bool) {
267 for _, m := range hashToHashIdMapping {
268 if m.hash == h {
269 return m.id, true
270 }
271 }
272 return 0, false
273}
diff --git a/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/golang.org/x/crypto/openpgp/write.go
new file mode 100644
index 0000000..65a304c
--- /dev/null
+++ b/vendor/golang.org/x/crypto/openpgp/write.go
@@ -0,0 +1,378 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package openpgp
6
7import (
8 "crypto"
9 "hash"
10 "io"
11 "strconv"
12 "time"
13
14 "golang.org/x/crypto/openpgp/armor"
15 "golang.org/x/crypto/openpgp/errors"
16 "golang.org/x/crypto/openpgp/packet"
17 "golang.org/x/crypto/openpgp/s2k"
18)
19
20// DetachSign signs message with the private key from signer (which must
21// already have been decrypted) and writes the signature to w.
22// If config is nil, sensible defaults will be used.
23func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
24 return detachSign(w, signer, message, packet.SigTypeBinary, config)
25}
26
27// ArmoredDetachSign signs message with the private key from signer (which
28// must already have been decrypted) and writes an armored signature to w.
29// If config is nil, sensible defaults will be used.
30func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) {
31 return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config)
32}
33
34// DetachSignText signs message (after canonicalising the line endings) with
35// the private key from signer (which must already have been decrypted) and
36// writes the signature to w.
37// If config is nil, sensible defaults will be used.
38func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
39 return detachSign(w, signer, message, packet.SigTypeText, config)
40}
41
42// ArmoredDetachSignText signs message (after canonicalising the line endings)
43// with the private key from signer (which must already have been decrypted)
44// and writes an armored signature to w.
45// If config is nil, sensible defaults will be used.
46func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
47 return armoredDetachSign(w, signer, message, packet.SigTypeText, config)
48}
49
50func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
51 out, err := armor.Encode(w, SignatureType, nil)
52 if err != nil {
53 return
54 }
55 err = detachSign(out, signer, message, sigType, config)
56 if err != nil {
57 return
58 }
59 return out.Close()
60}
61
62func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
63 if signer.PrivateKey == nil {
64 return errors.InvalidArgumentError("signing key doesn't have a private key")
65 }
66 if signer.PrivateKey.Encrypted {
67 return errors.InvalidArgumentError("signing key is encrypted")
68 }
69
70 sig := new(packet.Signature)
71 sig.SigType = sigType
72 sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo
73 sig.Hash = config.Hash()
74 sig.CreationTime = config.Now()
75 sig.IssuerKeyId = &signer.PrivateKey.KeyId
76
77 h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType)
78 if err != nil {
79 return
80 }
81 io.Copy(wrappedHash, message)
82
83 err = sig.Sign(h, signer.PrivateKey, config)
84 if err != nil {
85 return
86 }
87
88 return sig.Serialize(w)
89}
90
91// FileHints contains metadata about encrypted files. This metadata is, itself,
92// encrypted.
93type FileHints struct {
94 // IsBinary can be set to hint that the contents are binary data.
95 IsBinary bool
96 // FileName hints at the name of the file that should be written. It's
97 // truncated to 255 bytes if longer. It may be empty to suggest that the
98 // file should not be written to disk. It may be equal to "_CONSOLE" to
99 // suggest the data should not be written to disk.
100 FileName string
101 // ModTime contains the modification time of the file, or the zero time if not applicable.
102 ModTime time.Time
103}
104
105// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase.
106// The resulting WriteCloser must be closed after the contents of the file have
107// been written.
108// If config is nil, sensible defaults will be used.
109func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
110 if hints == nil {
111 hints = &FileHints{}
112 }
113
114 key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config)
115 if err != nil {
116 return
117 }
118 w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config)
119 if err != nil {
120 return
121 }
122
123 literaldata := w
124 if algo := config.Compression(); algo != packet.CompressionNone {
125 var compConfig *packet.CompressionConfig
126 if config != nil {
127 compConfig = config.CompressionConfig
128 }
129 literaldata, err = packet.SerializeCompressed(w, algo, compConfig)
130 if err != nil {
131 return
132 }
133 }
134
135 var epochSeconds uint32
136 if !hints.ModTime.IsZero() {
137 epochSeconds = uint32(hints.ModTime.Unix())
138 }
139 return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds)
140}
141
142// intersectPreferences mutates and returns a prefix of a that contains only
143// the values in the intersection of a and b. The order of a is preserved.
144func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) {
145 var j int
146 for _, v := range a {
147 for _, v2 := range b {
148 if v == v2 {
149 a[j] = v
150 j++
151 break
152 }
153 }
154 }
155
156 return a[:j]
157}
158
159func hashToHashId(h crypto.Hash) uint8 {
160 v, ok := s2k.HashToHashId(h)
161 if !ok {
162 panic("tried to convert unknown hash")
163 }
164 return v
165}
166
167// Encrypt encrypts a message to a number of recipients and, optionally, signs
168// it. hints contains optional information, that is also encrypted, that aids
169// the recipients in processing the message. The resulting WriteCloser must
170// be closed after the contents of the file have been written.
171// If config is nil, sensible defaults will be used.
172func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
173 var signer *packet.PrivateKey
174 if signed != nil {
175 signKey, ok := signed.signingKey(config.Now())
176 if !ok {
177 return nil, errors.InvalidArgumentError("no valid signing keys")
178 }
179 signer = signKey.PrivateKey
180 if signer == nil {
181 return nil, errors.InvalidArgumentError("no private key in signing key")
182 }
183 if signer.Encrypted {
184 return nil, errors.InvalidArgumentError("signing key must be decrypted")
185 }
186 }
187
188 // These are the possible ciphers that we'll use for the message.
189 candidateCiphers := []uint8{
190 uint8(packet.CipherAES128),
191 uint8(packet.CipherAES256),
192 uint8(packet.CipherCAST5),
193 }
194 // These are the possible hash functions that we'll use for the signature.
195 candidateHashes := []uint8{
196 hashToHashId(crypto.SHA256),
197 hashToHashId(crypto.SHA512),
198 hashToHashId(crypto.SHA1),
199 hashToHashId(crypto.RIPEMD160),
200 }
201 // In the event that a recipient doesn't specify any supported ciphers
202 // or hash functions, these are the ones that we assume that every
203 // implementation supports.
204 defaultCiphers := candidateCiphers[len(candidateCiphers)-1:]
205 defaultHashes := candidateHashes[len(candidateHashes)-1:]
206
207 encryptKeys := make([]Key, len(to))
208 for i := range to {
209 var ok bool
210 encryptKeys[i], ok = to[i].encryptionKey(config.Now())
211 if !ok {
212 return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys")
213 }
214
215 sig := to[i].primaryIdentity().SelfSignature
216
217 preferredSymmetric := sig.PreferredSymmetric
218 if len(preferredSymmetric) == 0 {
219 preferredSymmetric = defaultCiphers
220 }
221 preferredHashes := sig.PreferredHash
222 if len(preferredHashes) == 0 {
223 preferredHashes = defaultHashes
224 }
225 candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric)
226 candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
227 }
228
229 if len(candidateCiphers) == 0 || len(candidateHashes) == 0 {
230 return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms")
231 }
232
233 cipher := packet.CipherFunction(candidateCiphers[0])
234 // If the cipher specified by config is a candidate, we'll use that.
235 configuredCipher := config.Cipher()
236 for _, c := range candidateCiphers {
237 cipherFunc := packet.CipherFunction(c)
238 if cipherFunc == configuredCipher {
239 cipher = cipherFunc
240 break
241 }
242 }
243
244 var hash crypto.Hash
245 for _, hashId := range candidateHashes {
246 if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() {
247 hash = h
248 break
249 }
250 }
251
252 // If the hash specified by config is a candidate, we'll use that.
253 if configuredHash := config.Hash(); configuredHash.Available() {
254 for _, hashId := range candidateHashes {
255 if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash {
256 hash = h
257 break
258 }
259 }
260 }
261
262 if hash == 0 {
263 hashId := candidateHashes[0]
264 name, ok := s2k.HashIdToString(hashId)
265 if !ok {
266 name = "#" + strconv.Itoa(int(hashId))
267 }
268 return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)")
269 }
270
271 symKey := make([]byte, cipher.KeySize())
272 if _, err := io.ReadFull(config.Random(), symKey); err != nil {
273 return nil, err
274 }
275
276 for _, key := range encryptKeys {
277 if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil {
278 return nil, err
279 }
280 }
281
282 encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config)
283 if err != nil {
284 return
285 }
286
287 if signer != nil {
288 ops := &packet.OnePassSignature{
289 SigType: packet.SigTypeBinary,
290 Hash: hash,
291 PubKeyAlgo: signer.PubKeyAlgo,
292 KeyId: signer.KeyId,
293 IsLast: true,
294 }
295 if err := ops.Serialize(encryptedData); err != nil {
296 return nil, err
297 }
298 }
299
300 if hints == nil {
301 hints = &FileHints{}
302 }
303
304 w := encryptedData
305 if signer != nil {
306 // If we need to write a signature packet after the literal
307 // data then we need to stop literalData from closing
308 // encryptedData.
309 w = noOpCloser{encryptedData}
310
311 }
312 var epochSeconds uint32
313 if !hints.ModTime.IsZero() {
314 epochSeconds = uint32(hints.ModTime.Unix())
315 }
316 literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds)
317 if err != nil {
318 return nil, err
319 }
320
321 if signer != nil {
322 return signatureWriter{encryptedData, literalData, hash, hash.New(), signer, config}, nil
323 }
324 return literalData, nil
325}
326
327// signatureWriter hashes the contents of a message while passing it along to
328// literalData. When closed, it closes literalData, writes a signature packet
329// to encryptedData and then also closes encryptedData.
330type signatureWriter struct {
331 encryptedData io.WriteCloser
332 literalData io.WriteCloser
333 hashType crypto.Hash
334 h hash.Hash
335 signer *packet.PrivateKey
336 config *packet.Config
337}
338
339func (s signatureWriter) Write(data []byte) (int, error) {
340 s.h.Write(data)
341 return s.literalData.Write(data)
342}
343
344func (s signatureWriter) Close() error {
345 sig := &packet.Signature{
346 SigType: packet.SigTypeBinary,
347 PubKeyAlgo: s.signer.PubKeyAlgo,
348 Hash: s.hashType,
349 CreationTime: s.config.Now(),
350 IssuerKeyId: &s.signer.KeyId,
351 }
352
353 if err := sig.Sign(s.h, s.signer, s.config); err != nil {
354 return err
355 }
356 if err := s.literalData.Close(); err != nil {
357 return err
358 }
359 if err := sig.Serialize(s.encryptedData); err != nil {
360 return err
361 }
362 return s.encryptedData.Close()
363}
364
365// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
366// TODO: we have two of these in OpenPGP packages alone. This probably needs
367// to be promoted somewhere more common.
368type noOpCloser struct {
369 w io.Writer
370}
371
372func (c noOpCloser) Write(data []byte) (n int, err error) {
373 return c.w.Write(data)
374}
375
376func (c noOpCloser) Close() error {
377 return nil
378}
diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/net/LICENSE
@@ -0,0 +1,27 @@
1Copyright (c) 2009 The Go Authors. All rights reserved.
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are
5met:
6
7 * Redistributions of source code must retain the above copyright
8notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10copyright notice, this list of conditions and the following disclaimer
11in the documentation and/or other materials provided with the
12distribution.
13 * Neither the name of Google Inc. nor the names of its
14contributors may be used to endorse or promote products derived from
15this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/net/PATENTS b/vendor/golang.org/x/net/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/net/PATENTS
@@ -0,0 +1,22 @@
1Additional IP Rights Grant (Patents)
2
3"This implementation" means the copyrightable works distributed by
4Google as part of the Go project.
5
6Google hereby grants to You a perpetual, worldwide, non-exclusive,
7no-charge, royalty-free, irrevocable (except as stated in this section)
8patent license to make, have made, use, offer to sell, sell, import,
9transfer and otherwise run, modify and propagate the contents of this
10implementation of Go, where such license applies only to those patent
11claims, both currently owned or controlled by Google and acquired in
12the future, licensable by Google that are necessarily infringed by this
13implementation of Go. This grant does not include claims that would be
14infringed only as a consequence of further modification of this
15implementation. If you or your agent or exclusive licensee institute or
16order or agree to the institution of patent litigation against any
17entity (including a cross-claim or counterclaim in a lawsuit) alleging
18that this implementation of Go or any code incorporated within this
19implementation of Go constitutes direct or contributory patent
20infringement, or inducement of patent infringement, then any patent
21rights granted to you under this License for this implementation of Go
22shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/net/html/atom/atom.go b/vendor/golang.org/x/net/html/atom/atom.go
new file mode 100644
index 0000000..cd0a8ac
--- /dev/null
+++ b/vendor/golang.org/x/net/html/atom/atom.go
@@ -0,0 +1,78 @@
1// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package atom provides integer codes (also known as atoms) for a fixed set of
6// frequently occurring HTML strings: tag names and attribute keys such as "p"
7// and "id".
8//
9// Sharing an atom's name between all elements with the same tag can result in
10// fewer string allocations when tokenizing and parsing HTML. Integer
11// comparisons are also generally faster than string comparisons.
12//
13// The value of an atom's particular code is not guaranteed to stay the same
14// between versions of this package. Neither is any ordering guaranteed:
15// whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to
16// be dense. The only guarantees are that e.g. looking up "div" will yield
17// atom.Div, calling atom.Div.String will return "div", and atom.Div != 0.
18package atom // import "golang.org/x/net/html/atom"
19
20// Atom is an integer code for a string. The zero value maps to "".
21type Atom uint32
22
23// String returns the atom's name.
24func (a Atom) String() string {
25 start := uint32(a >> 8)
26 n := uint32(a & 0xff)
27 if start+n > uint32(len(atomText)) {
28 return ""
29 }
30 return atomText[start : start+n]
31}
32
33func (a Atom) string() string {
34 return atomText[a>>8 : a>>8+a&0xff]
35}
36
37// fnv computes the FNV hash with an arbitrary starting value h.
38func fnv(h uint32, s []byte) uint32 {
39 for i := range s {
40 h ^= uint32(s[i])
41 h *= 16777619
42 }
43 return h
44}
45
46func match(s string, t []byte) bool {
47 for i, c := range t {
48 if s[i] != c {
49 return false
50 }
51 }
52 return true
53}
54
55// Lookup returns the atom whose name is s. It returns zero if there is no
56// such atom. The lookup is case sensitive.
57func Lookup(s []byte) Atom {
58 if len(s) == 0 || len(s) > maxAtomLen {
59 return 0
60 }
61 h := fnv(hash0, s)
62 if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
63 return a
64 }
65 if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
66 return a
67 }
68 return 0
69}
70
71// String returns a string whose contents are equal to s. In that sense, it is
72// equivalent to string(s) but may be more efficient.
73func String(s []byte) string {
74 if a := Lookup(s); a != 0 {
75 return a.String()
76 }
77 return string(s)
78}
diff --git a/vendor/golang.org/x/net/html/atom/table.go b/vendor/golang.org/x/net/html/atom/table.go
new file mode 100644
index 0000000..2605ba3
--- /dev/null
+++ b/vendor/golang.org/x/net/html/atom/table.go
@@ -0,0 +1,713 @@
1// generated by go run gen.go; DO NOT EDIT
2
3package atom
4
5const (
6 A Atom = 0x1
7 Abbr Atom = 0x4
8 Accept Atom = 0x2106
9 AcceptCharset Atom = 0x210e
10 Accesskey Atom = 0x3309
11 Action Atom = 0x1f606
12 Address Atom = 0x4f307
13 Align Atom = 0x1105
14 Alt Atom = 0x4503
15 Annotation Atom = 0x1670a
16 AnnotationXml Atom = 0x1670e
17 Applet Atom = 0x2b306
18 Area Atom = 0x2fa04
19 Article Atom = 0x38807
20 Aside Atom = 0x8305
21 Async Atom = 0x7b05
22 Audio Atom = 0xa605
23 Autocomplete Atom = 0x1fc0c
24 Autofocus Atom = 0xb309
25 Autoplay Atom = 0xce08
26 B Atom = 0x101
27 Base Atom = 0xd604
28 Basefont Atom = 0xd608
29 Bdi Atom = 0x1a03
30 Bdo Atom = 0xe703
31 Bgsound Atom = 0x11807
32 Big Atom = 0x12403
33 Blink Atom = 0x12705
34 Blockquote Atom = 0x12c0a
35 Body Atom = 0x2f04
36 Br Atom = 0x202
37 Button Atom = 0x13606
38 Canvas Atom = 0x7f06
39 Caption Atom = 0x1bb07
40 Center Atom = 0x5b506
41 Challenge Atom = 0x21f09
42 Charset Atom = 0x2807
43 Checked Atom = 0x32807
44 Cite Atom = 0x3c804
45 Class Atom = 0x4de05
46 Code Atom = 0x14904
47 Col Atom = 0x15003
48 Colgroup Atom = 0x15008
49 Color Atom = 0x15d05
50 Cols Atom = 0x16204
51 Colspan Atom = 0x16207
52 Command Atom = 0x17507
53 Content Atom = 0x42307
54 Contenteditable Atom = 0x4230f
55 Contextmenu Atom = 0x3310b
56 Controls Atom = 0x18808
57 Coords Atom = 0x19406
58 Crossorigin Atom = 0x19f0b
59 Data Atom = 0x44a04
60 Datalist Atom = 0x44a08
61 Datetime Atom = 0x23c08
62 Dd Atom = 0x26702
63 Default Atom = 0x8607
64 Defer Atom = 0x14b05
65 Del Atom = 0x3ef03
66 Desc Atom = 0x4db04
67 Details Atom = 0x4807
68 Dfn Atom = 0x6103
69 Dialog Atom = 0x1b06
70 Dir Atom = 0x6903
71 Dirname Atom = 0x6907
72 Disabled Atom = 0x10c08
73 Div Atom = 0x11303
74 Dl Atom = 0x11e02
75 Download Atom = 0x40008
76 Draggable Atom = 0x17b09
77 Dropzone Atom = 0x39108
78 Dt Atom = 0x50902
79 Em Atom = 0x6502
80 Embed Atom = 0x6505
81 Enctype Atom = 0x21107
82 Face Atom = 0x5b304
83 Fieldset Atom = 0x1b008
84 Figcaption Atom = 0x1b80a
85 Figure Atom = 0x1cc06
86 Font Atom = 0xda04
87 Footer Atom = 0x8d06
88 For Atom = 0x1d803
89 ForeignObject Atom = 0x1d80d
90 Foreignobject Atom = 0x1e50d
91 Form Atom = 0x1f204
92 Formaction Atom = 0x1f20a
93 Formenctype Atom = 0x20d0b
94 Formmethod Atom = 0x2280a
95 Formnovalidate Atom = 0x2320e
96 Formtarget Atom = 0x2470a
97 Frame Atom = 0x9a05
98 Frameset Atom = 0x9a08
99 H1 Atom = 0x26e02
100 H2 Atom = 0x29402
101 H3 Atom = 0x2a702
102 H4 Atom = 0x2e902
103 H5 Atom = 0x2f302
104 H6 Atom = 0x50b02
105 Head Atom = 0x2d504
106 Header Atom = 0x2d506
107 Headers Atom = 0x2d507
108 Height Atom = 0x25106
109 Hgroup Atom = 0x25906
110 Hidden Atom = 0x26506
111 High Atom = 0x26b04
112 Hr Atom = 0x27002
113 Href Atom = 0x27004
114 Hreflang Atom = 0x27008
115 Html Atom = 0x25504
116 HttpEquiv Atom = 0x2780a
117 I Atom = 0x601
118 Icon Atom = 0x42204
119 Id Atom = 0x8502
120 Iframe Atom = 0x29606
121 Image Atom = 0x29c05
122 Img Atom = 0x2a103
123 Input Atom = 0x3e805
124 Inputmode Atom = 0x3e809
125 Ins Atom = 0x1a803
126 Isindex Atom = 0x2a907
127 Ismap Atom = 0x2b005
128 Itemid Atom = 0x33c06
129 Itemprop Atom = 0x3c908
130 Itemref Atom = 0x5ad07
131 Itemscope Atom = 0x2b909
132 Itemtype Atom = 0x2c308
133 Kbd Atom = 0x1903
134 Keygen Atom = 0x3906
135 Keytype Atom = 0x53707
136 Kind Atom = 0x10904
137 Label Atom = 0xf005
138 Lang Atom = 0x27404
139 Legend Atom = 0x18206
140 Li Atom = 0x1202
141 Link Atom = 0x12804
142 List Atom = 0x44e04
143 Listing Atom = 0x44e07
144 Loop Atom = 0xf404
145 Low Atom = 0x11f03
146 Malignmark Atom = 0x100a
147 Manifest Atom = 0x5f108
148 Map Atom = 0x2b203
149 Mark Atom = 0x1604
150 Marquee Atom = 0x2cb07
151 Math Atom = 0x2d204
152 Max Atom = 0x2e103
153 Maxlength Atom = 0x2e109
154 Media Atom = 0x6e05
155 Mediagroup Atom = 0x6e0a
156 Menu Atom = 0x33804
157 Menuitem Atom = 0x33808
158 Meta Atom = 0x45d04
159 Meter Atom = 0x24205
160 Method Atom = 0x22c06
161 Mglyph Atom = 0x2a206
162 Mi Atom = 0x2eb02
163 Min Atom = 0x2eb03
164 Minlength Atom = 0x2eb09
165 Mn Atom = 0x23502
166 Mo Atom = 0x3ed02
167 Ms Atom = 0x2bc02
168 Mtext Atom = 0x2f505
169 Multiple Atom = 0x30308
170 Muted Atom = 0x30b05
171 Name Atom = 0x6c04
172 Nav Atom = 0x3e03
173 Nobr Atom = 0x5704
174 Noembed Atom = 0x6307
175 Noframes Atom = 0x9808
176 Noscript Atom = 0x3d208
177 Novalidate Atom = 0x2360a
178 Object Atom = 0x1ec06
179 Ol Atom = 0xc902
180 Onabort Atom = 0x13a07
181 Onafterprint Atom = 0x1c00c
182 Onautocomplete Atom = 0x1fa0e
183 Onautocompleteerror Atom = 0x1fa13
184 Onbeforeprint Atom = 0x6040d
185 Onbeforeunload Atom = 0x4e70e
186 Onblur Atom = 0xaa06
187 Oncancel Atom = 0xe908
188 Oncanplay Atom = 0x28509
189 Oncanplaythrough Atom = 0x28510
190 Onchange Atom = 0x3a708
191 Onclick Atom = 0x31007
192 Onclose Atom = 0x31707
193 Oncontextmenu Atom = 0x32f0d
194 Oncuechange Atom = 0x3420b
195 Ondblclick Atom = 0x34d0a
196 Ondrag Atom = 0x35706
197 Ondragend Atom = 0x35709
198 Ondragenter Atom = 0x3600b
199 Ondragleave Atom = 0x36b0b
200 Ondragover Atom = 0x3760a
201 Ondragstart Atom = 0x3800b
202 Ondrop Atom = 0x38f06
203 Ondurationchange Atom = 0x39f10
204 Onemptied Atom = 0x39609
205 Onended Atom = 0x3af07
206 Onerror Atom = 0x3b607
207 Onfocus Atom = 0x3bd07
208 Onhashchange Atom = 0x3da0c
209 Oninput Atom = 0x3e607
210 Oninvalid Atom = 0x3f209
211 Onkeydown Atom = 0x3fb09
212 Onkeypress Atom = 0x4080a
213 Onkeyup Atom = 0x41807
214 Onlanguagechange Atom = 0x43210
215 Onload Atom = 0x44206
216 Onloadeddata Atom = 0x4420c
217 Onloadedmetadata Atom = 0x45510
218 Onloadstart Atom = 0x46b0b
219 Onmessage Atom = 0x47609
220 Onmousedown Atom = 0x47f0b
221 Onmousemove Atom = 0x48a0b
222 Onmouseout Atom = 0x4950a
223 Onmouseover Atom = 0x4a20b
224 Onmouseup Atom = 0x4ad09
225 Onmousewheel Atom = 0x4b60c
226 Onoffline Atom = 0x4c209
227 Ononline Atom = 0x4cb08
228 Onpagehide Atom = 0x4d30a
229 Onpageshow Atom = 0x4fe0a
230 Onpause Atom = 0x50d07
231 Onplay Atom = 0x51706
232 Onplaying Atom = 0x51709
233 Onpopstate Atom = 0x5200a
234 Onprogress Atom = 0x52a0a
235 Onratechange Atom = 0x53e0c
236 Onreset Atom = 0x54a07
237 Onresize Atom = 0x55108
238 Onscroll Atom = 0x55f08
239 Onseeked Atom = 0x56708
240 Onseeking Atom = 0x56f09
241 Onselect Atom = 0x57808
242 Onshow Atom = 0x58206
243 Onsort Atom = 0x58b06
244 Onstalled Atom = 0x59509
245 Onstorage Atom = 0x59e09
246 Onsubmit Atom = 0x5a708
247 Onsuspend Atom = 0x5bb09
248 Ontimeupdate Atom = 0xdb0c
249 Ontoggle Atom = 0x5c408
250 Onunload Atom = 0x5cc08
251 Onvolumechange Atom = 0x5d40e
252 Onwaiting Atom = 0x5e209
253 Open Atom = 0x3cf04
254 Optgroup Atom = 0xf608
255 Optimum Atom = 0x5eb07
256 Option Atom = 0x60006
257 Output Atom = 0x49c06
258 P Atom = 0xc01
259 Param Atom = 0xc05
260 Pattern Atom = 0x5107
261 Ping Atom = 0x7704
262 Placeholder Atom = 0xc30b
263 Plaintext Atom = 0xfd09
264 Poster Atom = 0x15706
265 Pre Atom = 0x25e03
266 Preload Atom = 0x25e07
267 Progress Atom = 0x52c08
268 Prompt Atom = 0x5fa06
269 Public Atom = 0x41e06
270 Q Atom = 0x13101
271 Radiogroup Atom = 0x30a
272 Readonly Atom = 0x2fb08
273 Rel Atom = 0x25f03
274 Required Atom = 0x1d008
275 Reversed Atom = 0x5a08
276 Rows Atom = 0x9204
277 Rowspan Atom = 0x9207
278 Rp Atom = 0x1c602
279 Rt Atom = 0x13f02
280 Ruby Atom = 0xaf04
281 S Atom = 0x2c01
282 Samp Atom = 0x4e04
283 Sandbox Atom = 0xbb07
284 Scope Atom = 0x2bd05
285 Scoped Atom = 0x2bd06
286 Script Atom = 0x3d406
287 Seamless Atom = 0x31c08
288 Section Atom = 0x4e207
289 Select Atom = 0x57a06
290 Selected Atom = 0x57a08
291 Shape Atom = 0x4f905
292 Size Atom = 0x55504
293 Sizes Atom = 0x55505
294 Small Atom = 0x18f05
295 Sortable Atom = 0x58d08
296 Sorted Atom = 0x19906
297 Source Atom = 0x1aa06
298 Spacer Atom = 0x2db06
299 Span Atom = 0x9504
300 Spellcheck Atom = 0x3230a
301 Src Atom = 0x3c303
302 Srcdoc Atom = 0x3c306
303 Srclang Atom = 0x41107
304 Start Atom = 0x38605
305 Step Atom = 0x5f704
306 Strike Atom = 0x53306
307 Strong Atom = 0x55906
308 Style Atom = 0x61105
309 Sub Atom = 0x5a903
310 Summary Atom = 0x61607
311 Sup Atom = 0x61d03
312 Svg Atom = 0x62003
313 System Atom = 0x62306
314 Tabindex Atom = 0x46308
315 Table Atom = 0x42d05
316 Target Atom = 0x24b06
317 Tbody Atom = 0x2e05
318 Td Atom = 0x4702
319 Template Atom = 0x62608
320 Textarea Atom = 0x2f608
321 Tfoot Atom = 0x8c05
322 Th Atom = 0x22e02
323 Thead Atom = 0x2d405
324 Time Atom = 0xdd04
325 Title Atom = 0xa105
326 Tr Atom = 0x10502
327 Track Atom = 0x10505
328 Translate Atom = 0x14009
329 Tt Atom = 0x5302
330 Type Atom = 0x21404
331 Typemustmatch Atom = 0x2140d
332 U Atom = 0xb01
333 Ul Atom = 0x8a02
334 Usemap Atom = 0x51106
335 Value Atom = 0x4005
336 Var Atom = 0x11503
337 Video Atom = 0x28105
338 Wbr Atom = 0x12103
339 Width Atom = 0x50705
340 Wrap Atom = 0x58704
341 Xmp Atom = 0xc103
342)
343
344const hash0 = 0xc17da63e
345
346const maxAtomLen = 19
347
348var table = [1 << 9]Atom{
349 0x1: 0x48a0b, // onmousemove
350 0x2: 0x5e209, // onwaiting
351 0x3: 0x1fa13, // onautocompleteerror
352 0x4: 0x5fa06, // prompt
353 0x7: 0x5eb07, // optimum
354 0x8: 0x1604, // mark
355 0xa: 0x5ad07, // itemref
356 0xb: 0x4fe0a, // onpageshow
357 0xc: 0x57a06, // select
358 0xd: 0x17b09, // draggable
359 0xe: 0x3e03, // nav
360 0xf: 0x17507, // command
361 0x11: 0xb01, // u
362 0x14: 0x2d507, // headers
363 0x15: 0x44a08, // datalist
364 0x17: 0x4e04, // samp
365 0x1a: 0x3fb09, // onkeydown
366 0x1b: 0x55f08, // onscroll
367 0x1c: 0x15003, // col
368 0x20: 0x3c908, // itemprop
369 0x21: 0x2780a, // http-equiv
370 0x22: 0x61d03, // sup
371 0x24: 0x1d008, // required
372 0x2b: 0x25e07, // preload
373 0x2c: 0x6040d, // onbeforeprint
374 0x2d: 0x3600b, // ondragenter
375 0x2e: 0x50902, // dt
376 0x2f: 0x5a708, // onsubmit
377 0x30: 0x27002, // hr
378 0x31: 0x32f0d, // oncontextmenu
379 0x33: 0x29c05, // image
380 0x34: 0x50d07, // onpause
381 0x35: 0x25906, // hgroup
382 0x36: 0x7704, // ping
383 0x37: 0x57808, // onselect
384 0x3a: 0x11303, // div
385 0x3b: 0x1fa0e, // onautocomplete
386 0x40: 0x2eb02, // mi
387 0x41: 0x31c08, // seamless
388 0x42: 0x2807, // charset
389 0x43: 0x8502, // id
390 0x44: 0x5200a, // onpopstate
391 0x45: 0x3ef03, // del
392 0x46: 0x2cb07, // marquee
393 0x47: 0x3309, // accesskey
394 0x49: 0x8d06, // footer
395 0x4a: 0x44e04, // list
396 0x4b: 0x2b005, // ismap
397 0x51: 0x33804, // menu
398 0x52: 0x2f04, // body
399 0x55: 0x9a08, // frameset
400 0x56: 0x54a07, // onreset
401 0x57: 0x12705, // blink
402 0x58: 0xa105, // title
403 0x59: 0x38807, // article
404 0x5b: 0x22e02, // th
405 0x5d: 0x13101, // q
406 0x5e: 0x3cf04, // open
407 0x5f: 0x2fa04, // area
408 0x61: 0x44206, // onload
409 0x62: 0xda04, // font
410 0x63: 0xd604, // base
411 0x64: 0x16207, // colspan
412 0x65: 0x53707, // keytype
413 0x66: 0x11e02, // dl
414 0x68: 0x1b008, // fieldset
415 0x6a: 0x2eb03, // min
416 0x6b: 0x11503, // var
417 0x6f: 0x2d506, // header
418 0x70: 0x13f02, // rt
419 0x71: 0x15008, // colgroup
420 0x72: 0x23502, // mn
421 0x74: 0x13a07, // onabort
422 0x75: 0x3906, // keygen
423 0x76: 0x4c209, // onoffline
424 0x77: 0x21f09, // challenge
425 0x78: 0x2b203, // map
426 0x7a: 0x2e902, // h4
427 0x7b: 0x3b607, // onerror
428 0x7c: 0x2e109, // maxlength
429 0x7d: 0x2f505, // mtext
430 0x7e: 0xbb07, // sandbox
431 0x7f: 0x58b06, // onsort
432 0x80: 0x100a, // malignmark
433 0x81: 0x45d04, // meta
434 0x82: 0x7b05, // async
435 0x83: 0x2a702, // h3
436 0x84: 0x26702, // dd
437 0x85: 0x27004, // href
438 0x86: 0x6e0a, // mediagroup
439 0x87: 0x19406, // coords
440 0x88: 0x41107, // srclang
441 0x89: 0x34d0a, // ondblclick
442 0x8a: 0x4005, // value
443 0x8c: 0xe908, // oncancel
444 0x8e: 0x3230a, // spellcheck
445 0x8f: 0x9a05, // frame
446 0x91: 0x12403, // big
447 0x94: 0x1f606, // action
448 0x95: 0x6903, // dir
449 0x97: 0x2fb08, // readonly
450 0x99: 0x42d05, // table
451 0x9a: 0x61607, // summary
452 0x9b: 0x12103, // wbr
453 0x9c: 0x30a, // radiogroup
454 0x9d: 0x6c04, // name
455 0x9f: 0x62306, // system
456 0xa1: 0x15d05, // color
457 0xa2: 0x7f06, // canvas
458 0xa3: 0x25504, // html
459 0xa5: 0x56f09, // onseeking
460 0xac: 0x4f905, // shape
461 0xad: 0x25f03, // rel
462 0xae: 0x28510, // oncanplaythrough
463 0xaf: 0x3760a, // ondragover
464 0xb0: 0x62608, // template
465 0xb1: 0x1d80d, // foreignObject
466 0xb3: 0x9204, // rows
467 0xb6: 0x44e07, // listing
468 0xb7: 0x49c06, // output
469 0xb9: 0x3310b, // contextmenu
470 0xbb: 0x11f03, // low
471 0xbc: 0x1c602, // rp
472 0xbd: 0x5bb09, // onsuspend
473 0xbe: 0x13606, // button
474 0xbf: 0x4db04, // desc
475 0xc1: 0x4e207, // section
476 0xc2: 0x52a0a, // onprogress
477 0xc3: 0x59e09, // onstorage
478 0xc4: 0x2d204, // math
479 0xc5: 0x4503, // alt
480 0xc7: 0x8a02, // ul
481 0xc8: 0x5107, // pattern
482 0xc9: 0x4b60c, // onmousewheel
483 0xca: 0x35709, // ondragend
484 0xcb: 0xaf04, // ruby
485 0xcc: 0xc01, // p
486 0xcd: 0x31707, // onclose
487 0xce: 0x24205, // meter
488 0xcf: 0x11807, // bgsound
489 0xd2: 0x25106, // height
490 0xd4: 0x101, // b
491 0xd5: 0x2c308, // itemtype
492 0xd8: 0x1bb07, // caption
493 0xd9: 0x10c08, // disabled
494 0xdb: 0x33808, // menuitem
495 0xdc: 0x62003, // svg
496 0xdd: 0x18f05, // small
497 0xde: 0x44a04, // data
498 0xe0: 0x4cb08, // ononline
499 0xe1: 0x2a206, // mglyph
500 0xe3: 0x6505, // embed
501 0xe4: 0x10502, // tr
502 0xe5: 0x46b0b, // onloadstart
503 0xe7: 0x3c306, // srcdoc
504 0xeb: 0x5c408, // ontoggle
505 0xed: 0xe703, // bdo
506 0xee: 0x4702, // td
507 0xef: 0x8305, // aside
508 0xf0: 0x29402, // h2
509 0xf1: 0x52c08, // progress
510 0xf2: 0x12c0a, // blockquote
511 0xf4: 0xf005, // label
512 0xf5: 0x601, // i
513 0xf7: 0x9207, // rowspan
514 0xfb: 0x51709, // onplaying
515 0xfd: 0x2a103, // img
516 0xfe: 0xf608, // optgroup
517 0xff: 0x42307, // content
518 0x101: 0x53e0c, // onratechange
519 0x103: 0x3da0c, // onhashchange
520 0x104: 0x4807, // details
521 0x106: 0x40008, // download
522 0x109: 0x14009, // translate
523 0x10b: 0x4230f, // contenteditable
524 0x10d: 0x36b0b, // ondragleave
525 0x10e: 0x2106, // accept
526 0x10f: 0x57a08, // selected
527 0x112: 0x1f20a, // formaction
528 0x113: 0x5b506, // center
529 0x115: 0x45510, // onloadedmetadata
530 0x116: 0x12804, // link
531 0x117: 0xdd04, // time
532 0x118: 0x19f0b, // crossorigin
533 0x119: 0x3bd07, // onfocus
534 0x11a: 0x58704, // wrap
535 0x11b: 0x42204, // icon
536 0x11d: 0x28105, // video
537 0x11e: 0x4de05, // class
538 0x121: 0x5d40e, // onvolumechange
539 0x122: 0xaa06, // onblur
540 0x123: 0x2b909, // itemscope
541 0x124: 0x61105, // style
542 0x127: 0x41e06, // public
543 0x129: 0x2320e, // formnovalidate
544 0x12a: 0x58206, // onshow
545 0x12c: 0x51706, // onplay
546 0x12d: 0x3c804, // cite
547 0x12e: 0x2bc02, // ms
548 0x12f: 0xdb0c, // ontimeupdate
549 0x130: 0x10904, // kind
550 0x131: 0x2470a, // formtarget
551 0x135: 0x3af07, // onended
552 0x136: 0x26506, // hidden
553 0x137: 0x2c01, // s
554 0x139: 0x2280a, // formmethod
555 0x13a: 0x3e805, // input
556 0x13c: 0x50b02, // h6
557 0x13d: 0xc902, // ol
558 0x13e: 0x3420b, // oncuechange
559 0x13f: 0x1e50d, // foreignobject
560 0x143: 0x4e70e, // onbeforeunload
561 0x144: 0x2bd05, // scope
562 0x145: 0x39609, // onemptied
563 0x146: 0x14b05, // defer
564 0x147: 0xc103, // xmp
565 0x148: 0x39f10, // ondurationchange
566 0x149: 0x1903, // kbd
567 0x14c: 0x47609, // onmessage
568 0x14d: 0x60006, // option
569 0x14e: 0x2eb09, // minlength
570 0x14f: 0x32807, // checked
571 0x150: 0xce08, // autoplay
572 0x152: 0x202, // br
573 0x153: 0x2360a, // novalidate
574 0x156: 0x6307, // noembed
575 0x159: 0x31007, // onclick
576 0x15a: 0x47f0b, // onmousedown
577 0x15b: 0x3a708, // onchange
578 0x15e: 0x3f209, // oninvalid
579 0x15f: 0x2bd06, // scoped
580 0x160: 0x18808, // controls
581 0x161: 0x30b05, // muted
582 0x162: 0x58d08, // sortable
583 0x163: 0x51106, // usemap
584 0x164: 0x1b80a, // figcaption
585 0x165: 0x35706, // ondrag
586 0x166: 0x26b04, // high
587 0x168: 0x3c303, // src
588 0x169: 0x15706, // poster
589 0x16b: 0x1670e, // annotation-xml
590 0x16c: 0x5f704, // step
591 0x16d: 0x4, // abbr
592 0x16e: 0x1b06, // dialog
593 0x170: 0x1202, // li
594 0x172: 0x3ed02, // mo
595 0x175: 0x1d803, // for
596 0x176: 0x1a803, // ins
597 0x178: 0x55504, // size
598 0x179: 0x43210, // onlanguagechange
599 0x17a: 0x8607, // default
600 0x17b: 0x1a03, // bdi
601 0x17c: 0x4d30a, // onpagehide
602 0x17d: 0x6907, // dirname
603 0x17e: 0x21404, // type
604 0x17f: 0x1f204, // form
605 0x181: 0x28509, // oncanplay
606 0x182: 0x6103, // dfn
607 0x183: 0x46308, // tabindex
608 0x186: 0x6502, // em
609 0x187: 0x27404, // lang
610 0x189: 0x39108, // dropzone
611 0x18a: 0x4080a, // onkeypress
612 0x18b: 0x23c08, // datetime
613 0x18c: 0x16204, // cols
614 0x18d: 0x1, // a
615 0x18e: 0x4420c, // onloadeddata
616 0x190: 0xa605, // audio
617 0x192: 0x2e05, // tbody
618 0x193: 0x22c06, // method
619 0x195: 0xf404, // loop
620 0x196: 0x29606, // iframe
621 0x198: 0x2d504, // head
622 0x19e: 0x5f108, // manifest
623 0x19f: 0xb309, // autofocus
624 0x1a0: 0x14904, // code
625 0x1a1: 0x55906, // strong
626 0x1a2: 0x30308, // multiple
627 0x1a3: 0xc05, // param
628 0x1a6: 0x21107, // enctype
629 0x1a7: 0x5b304, // face
630 0x1a8: 0xfd09, // plaintext
631 0x1a9: 0x26e02, // h1
632 0x1aa: 0x59509, // onstalled
633 0x1ad: 0x3d406, // script
634 0x1ae: 0x2db06, // spacer
635 0x1af: 0x55108, // onresize
636 0x1b0: 0x4a20b, // onmouseover
637 0x1b1: 0x5cc08, // onunload
638 0x1b2: 0x56708, // onseeked
639 0x1b4: 0x2140d, // typemustmatch
640 0x1b5: 0x1cc06, // figure
641 0x1b6: 0x4950a, // onmouseout
642 0x1b7: 0x25e03, // pre
643 0x1b8: 0x50705, // width
644 0x1b9: 0x19906, // sorted
645 0x1bb: 0x5704, // nobr
646 0x1be: 0x5302, // tt
647 0x1bf: 0x1105, // align
648 0x1c0: 0x3e607, // oninput
649 0x1c3: 0x41807, // onkeyup
650 0x1c6: 0x1c00c, // onafterprint
651 0x1c7: 0x210e, // accept-charset
652 0x1c8: 0x33c06, // itemid
653 0x1c9: 0x3e809, // inputmode
654 0x1cb: 0x53306, // strike
655 0x1cc: 0x5a903, // sub
656 0x1cd: 0x10505, // track
657 0x1ce: 0x38605, // start
658 0x1d0: 0xd608, // basefont
659 0x1d6: 0x1aa06, // source
660 0x1d7: 0x18206, // legend
661 0x1d8: 0x2d405, // thead
662 0x1da: 0x8c05, // tfoot
663 0x1dd: 0x1ec06, // object
664 0x1de: 0x6e05, // media
665 0x1df: 0x1670a, // annotation
666 0x1e0: 0x20d0b, // formenctype
667 0x1e2: 0x3d208, // noscript
668 0x1e4: 0x55505, // sizes
669 0x1e5: 0x1fc0c, // autocomplete
670 0x1e6: 0x9504, // span
671 0x1e7: 0x9808, // noframes
672 0x1e8: 0x24b06, // target
673 0x1e9: 0x38f06, // ondrop
674 0x1ea: 0x2b306, // applet
675 0x1ec: 0x5a08, // reversed
676 0x1f0: 0x2a907, // isindex
677 0x1f3: 0x27008, // hreflang
678 0x1f5: 0x2f302, // h5
679 0x1f6: 0x4f307, // address
680 0x1fa: 0x2e103, // max
681 0x1fb: 0xc30b, // placeholder
682 0x1fc: 0x2f608, // textarea
683 0x1fe: 0x4ad09, // onmouseup
684 0x1ff: 0x3800b, // ondragstart
685}
686
687const atomText = "abbradiogrouparamalignmarkbdialogaccept-charsetbodyaccesskey" +
688 "genavaluealtdetailsampatternobreversedfnoembedirnamediagroup" +
689 "ingasyncanvasidefaultfooterowspanoframesetitleaudionblurubya" +
690 "utofocusandboxmplaceholderautoplaybasefontimeupdatebdoncance" +
691 "labelooptgrouplaintextrackindisabledivarbgsoundlowbrbigblink" +
692 "blockquotebuttonabortranslatecodefercolgroupostercolorcolspa" +
693 "nnotation-xmlcommandraggablegendcontrolsmallcoordsortedcross" +
694 "originsourcefieldsetfigcaptionafterprintfigurequiredforeignO" +
695 "bjectforeignobjectformactionautocompleteerrorformenctypemust" +
696 "matchallengeformmethodformnovalidatetimeterformtargetheightm" +
697 "lhgroupreloadhiddenhigh1hreflanghttp-equivideoncanplaythroug" +
698 "h2iframeimageimglyph3isindexismappletitemscopeditemtypemarqu" +
699 "eematheaderspacermaxlength4minlength5mtextareadonlymultiplem" +
700 "utedonclickoncloseamlesspellcheckedoncontextmenuitemidoncuec" +
701 "hangeondblclickondragendondragenterondragleaveondragoverondr" +
702 "agstarticleondropzonemptiedondurationchangeonendedonerroronf" +
703 "ocusrcdocitempropenoscriptonhashchangeoninputmodeloninvalido" +
704 "nkeydownloadonkeypressrclangonkeyupublicontenteditableonlang" +
705 "uagechangeonloadeddatalistingonloadedmetadatabindexonloadsta" +
706 "rtonmessageonmousedownonmousemoveonmouseoutputonmouseoveronm" +
707 "ouseuponmousewheelonofflineononlineonpagehidesclassectionbef" +
708 "oreunloaddresshapeonpageshowidth6onpausemaponplayingonpopsta" +
709 "teonprogresstrikeytypeonratechangeonresetonresizestrongonscr" +
710 "ollonseekedonseekingonselectedonshowraponsortableonstalledon" +
711 "storageonsubmitemrefacenteronsuspendontoggleonunloadonvolume" +
712 "changeonwaitingoptimumanifestepromptoptionbeforeprintstylesu" +
713 "mmarysupsvgsystemplate"
diff --git a/vendor/golang.org/x/net/html/const.go b/vendor/golang.org/x/net/html/const.go
new file mode 100644
index 0000000..52f651f
--- /dev/null
+++ b/vendor/golang.org/x/net/html/const.go
@@ -0,0 +1,102 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package html
6
7// Section 12.2.3.2 of the HTML5 specification says "The following elements
8// have varying levels of special parsing rules".
9// https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements
10var isSpecialElementMap = map[string]bool{
11 "address": true,
12 "applet": true,
13 "area": true,
14 "article": true,
15 "aside": true,
16 "base": true,
17 "basefont": true,
18 "bgsound": true,
19 "blockquote": true,
20 "body": true,
21 "br": true,
22 "button": true,
23 "caption": true,
24 "center": true,
25 "col": true,
26 "colgroup": true,
27 "dd": true,
28 "details": true,
29 "dir": true,
30 "div": true,
31 "dl": true,
32 "dt": true,
33 "embed": true,
34 "fieldset": true,
35 "figcaption": true,
36 "figure": true,
37 "footer": true,
38 "form": true,
39 "frame": true,
40 "frameset": true,
41 "h1": true,
42 "h2": true,
43 "h3": true,
44 "h4": true,
45 "h5": true,
46 "h6": true,
47 "head": true,
48 "header": true,
49 "hgroup": true,
50 "hr": true,
51 "html": true,
52 "iframe": true,
53 "img": true,
54 "input": true,
55 "isindex": true,
56 "li": true,
57 "link": true,
58 "listing": true,
59 "marquee": true,
60 "menu": true,
61 "meta": true,
62 "nav": true,
63 "noembed": true,
64 "noframes": true,
65 "noscript": true,
66 "object": true,
67 "ol": true,
68 "p": true,
69 "param": true,
70 "plaintext": true,
71 "pre": true,
72 "script": true,
73 "section": true,
74 "select": true,
75 "source": true,
76 "style": true,
77 "summary": true,
78 "table": true,
79 "tbody": true,
80 "td": true,
81 "template": true,
82 "textarea": true,
83 "tfoot": true,
84 "th": true,
85 "thead": true,
86 "title": true,
87 "tr": true,
88 "track": true,
89 "ul": true,
90 "wbr": true,
91 "xmp": true,
92}
93
94func isSpecialElement(element *Node) bool {
95 switch element.Namespace {
96 case "", "html":
97 return isSpecialElementMap[element.Data]
98 case "svg":
99 return element.Data == "foreignObject"
100 }
101 return false
102}
diff --git a/vendor/golang.org/x/net/html/doc.go b/vendor/golang.org/x/net/html/doc.go
new file mode 100644
index 0000000..94f4968
--- /dev/null
+++ b/vendor/golang.org/x/net/html/doc.go
@@ -0,0 +1,106 @@
1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5/*
6Package html implements an HTML5-compliant tokenizer and parser.
7
8Tokenization is done by creating a Tokenizer for an io.Reader r. It is the
9caller's responsibility to ensure that r provides UTF-8 encoded HTML.
10
11 z := html.NewTokenizer(r)
12
13Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(),
14which parses the next token and returns its type, or an error:
15
16 for {
17 tt := z.Next()
18 if tt == html.ErrorToken {
19 // ...
20 return ...
21 }
22 // Process the current token.
23 }
24
25There are two APIs for retrieving the current token. The high-level API is to
26call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs
27allow optionally calling Raw after Next but before Token, Text, TagName, or
28TagAttr. In EBNF notation, the valid call sequence per token is:
29
30 Next {Raw} [ Token | Text | TagName {TagAttr} ]
31
32Token returns an independent data structure that completely describes a token.
33Entities (such as "&lt;") are unescaped, tag names and attribute keys are
34lower-cased, and attributes are collected into a []Attribute. For example:
35
36 for {
37 if z.Next() == html.ErrorToken {
38 // Returning io.EOF indicates success.
39 return z.Err()
40 }
41 emitToken(z.Token())
42 }
43
44The low-level API performs fewer allocations and copies, but the contents of
45the []byte values returned by Text, TagName and TagAttr may change on the next
46call to Next. For example, to extract an HTML page's anchor text:
47
48 depth := 0
49 for {
50 tt := z.Next()
51 switch tt {
52 case ErrorToken:
53 return z.Err()
54 case TextToken:
55 if depth > 0 {
56 // emitBytes should copy the []byte it receives,
57 // if it doesn't process it immediately.
58 emitBytes(z.Text())
59 }
60 case StartTagToken, EndTagToken:
61 tn, _ := z.TagName()
62 if len(tn) == 1 && tn[0] == 'a' {
63 if tt == StartTagToken {
64 depth++
65 } else {
66 depth--
67 }
68 }
69 }
70 }
71
72Parsing is done by calling Parse with an io.Reader, which returns the root of
73the parse tree (the document element) as a *Node. It is the caller's
74responsibility to ensure that the Reader provides UTF-8 encoded HTML. For
75example, to process each anchor node in depth-first order:
76
77 doc, err := html.Parse(r)
78 if err != nil {
79 // ...
80 }
81 var f func(*html.Node)
82 f = func(n *html.Node) {
83 if n.Type == html.ElementNode && n.Data == "a" {
84 // Do something with n...
85 }
86 for c := n.FirstChild; c != nil; c = c.NextSibling {
87 f(c)
88 }
89 }
90 f(doc)
91
92The relevant specifications include:
93https://html.spec.whatwg.org/multipage/syntax.html and
94https://html.spec.whatwg.org/multipage/syntax.html#tokenization
95*/
96package html // import "golang.org/x/net/html"
97
98// The tokenization algorithm implemented by this package is not a line-by-line
99// transliteration of the relatively verbose state-machine in the WHATWG
100// specification. A more direct approach is used instead, where the program
101// counter implies the state, such as whether it is tokenizing a tag or a text
102// node. Specification compliance is verified by checking expected and actual
103// outputs over a test suite rather than aiming for algorithmic fidelity.
104
105// TODO(nigeltao): Does a DOM API belong in this package or a separate one?
106// TODO(nigeltao): How does parsing interact with a JavaScript engine?
diff --git a/vendor/golang.org/x/net/html/doctype.go b/vendor/golang.org/x/net/html/doctype.go
new file mode 100644
index 0000000..c484e5a
--- /dev/null
+++ b/vendor/golang.org/x/net/html/doctype.go
@@ -0,0 +1,156 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package html
6
7import (
8 "strings"
9)
10
11// parseDoctype parses the data from a DoctypeToken into a name,
12// public identifier, and system identifier. It returns a Node whose Type
13// is DoctypeNode, whose Data is the name, and which has attributes
14// named "system" and "public" for the two identifiers if they were present.
15// quirks is whether the document should be parsed in "quirks mode".
16func parseDoctype(s string) (n *Node, quirks bool) {
17 n = &Node{Type: DoctypeNode}
18
19 // Find the name.
20 space := strings.IndexAny(s, whitespace)
21 if space == -1 {
22 space = len(s)
23 }
24 n.Data = s[:space]
25 // The comparison to "html" is case-sensitive.
26 if n.Data != "html" {
27 quirks = true
28 }
29 n.Data = strings.ToLower(n.Data)
30 s = strings.TrimLeft(s[space:], whitespace)
31
32 if len(s) < 6 {
33 // It can't start with "PUBLIC" or "SYSTEM".
34 // Ignore the rest of the string.
35 return n, quirks || s != ""
36 }
37
38 key := strings.ToLower(s[:6])
39 s = s[6:]
40 for key == "public" || key == "system" {
41 s = strings.TrimLeft(s, whitespace)
42 if s == "" {
43 break
44 }
45 quote := s[0]
46 if quote != '"' && quote != '\'' {
47 break
48 }
49 s = s[1:]
50 q := strings.IndexRune(s, rune(quote))
51 var id string
52 if q == -1 {
53 id = s
54 s = ""
55 } else {
56 id = s[:q]
57 s = s[q+1:]
58 }
59 n.Attr = append(n.Attr, Attribute{Key: key, Val: id})
60 if key == "public" {
61 key = "system"
62 } else {
63 key = ""
64 }
65 }
66
67 if key != "" || s != "" {
68 quirks = true
69 } else if len(n.Attr) > 0 {
70 if n.Attr[0].Key == "public" {
71 public := strings.ToLower(n.Attr[0].Val)
72 switch public {
73 case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html":
74 quirks = true
75 default:
76 for _, q := range quirkyIDs {
77 if strings.HasPrefix(public, q) {
78 quirks = true
79 break
80 }
81 }
82 }
83 // The following two public IDs only cause quirks mode if there is no system ID.
84 if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") ||
85 strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) {
86 quirks = true
87 }
88 }
89 if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" &&
90 strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" {
91 quirks = true
92 }
93 }
94
95 return n, quirks
96}
97
98// quirkyIDs is a list of public doctype identifiers that cause a document
99// to be interpreted in quirks mode. The identifiers should be in lower case.
100var quirkyIDs = []string{
101 "+//silmaril//dtd html pro v0r11 19970101//",
102 "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
103 "-//as//dtd html 3.0 aswedit + extensions//",
104 "-//ietf//dtd html 2.0 level 1//",
105 "-//ietf//dtd html 2.0 level 2//",
106 "-//ietf//dtd html 2.0 strict level 1//",
107 "-//ietf//dtd html 2.0 strict level 2//",
108 "-//ietf//dtd html 2.0 strict//",
109 "-//ietf//dtd html 2.0//",
110 "-//ietf//dtd html 2.1e//",
111 "-//ietf//dtd html 3.0//",
112 "-//ietf//dtd html 3.2 final//",
113 "-//ietf//dtd html 3.2//",
114 "-//ietf//dtd html 3//",
115 "-//ietf//dtd html level 0//",
116 "-//ietf//dtd html level 1//",
117 "-//ietf//dtd html level 2//",
118 "-//ietf//dtd html level 3//",
119 "-//ietf//dtd html strict level 0//",
120 "-//ietf//dtd html strict level 1//",
121 "-//ietf//dtd html strict level 2//",
122 "-//ietf//dtd html strict level 3//",
123 "-//ietf//dtd html strict//",
124 "-//ietf//dtd html//",
125 "-//metrius//dtd metrius presentational//",
126 "-//microsoft//dtd internet explorer 2.0 html strict//",
127 "-//microsoft//dtd internet explorer 2.0 html//",
128 "-//microsoft//dtd internet explorer 2.0 tables//",
129 "-//microsoft//dtd internet explorer 3.0 html strict//",
130 "-//microsoft//dtd internet explorer 3.0 html//",
131 "-//microsoft//dtd internet explorer 3.0 tables//",
132 "-//netscape comm. corp.//dtd html//",
133 "-//netscape comm. corp.//dtd strict html//",
134 "-//o'reilly and associates//dtd html 2.0//",
135 "-//o'reilly and associates//dtd html extended 1.0//",
136 "-//o'reilly and associates//dtd html extended relaxed 1.0//",
137 "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//",
138 "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
139 "-//spyglass//dtd html 2.0 extended//",
140 "-//sq//dtd html 2.0 hotmetal + extensions//",
141 "-//sun microsystems corp.//dtd hotjava html//",
142 "-//sun microsystems corp.//dtd hotjava strict html//",
143 "-//w3c//dtd html 3 1995-03-24//",
144 "-//w3c//dtd html 3.2 draft//",
145 "-//w3c//dtd html 3.2 final//",
146 "-//w3c//dtd html 3.2//",
147 "-//w3c//dtd html 3.2s draft//",
148 "-//w3c//dtd html 4.0 frameset//",
149 "-//w3c//dtd html 4.0 transitional//",
150 "-//w3c//dtd html experimental 19960712//",
151 "-//w3c//dtd html experimental 970421//",
152 "-//w3c//dtd w3 html//",
153 "-//w3o//dtd w3 html 3.0//",
154 "-//webtechs//dtd mozilla html 2.0//",
155 "-//webtechs//dtd mozilla html//",
156}
diff --git a/vendor/golang.org/x/net/html/entity.go b/vendor/golang.org/x/net/html/entity.go
new file mode 100644
index 0000000..a50c04c
--- /dev/null
+++ b/vendor/golang.org/x/net/html/entity.go
@@ -0,0 +1,2253 @@
1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package html
6
7// All entities that do not end with ';' are 6 or fewer bytes long.
8const longestEntityWithoutSemicolon = 6
9
10// entity is a map from HTML entity names to their values. The semicolon matters:
11// https://html.spec.whatwg.org/multipage/syntax.html#named-character-references
12// lists both "amp" and "amp;" as two separate entries.
13//
14// Note that the HTML5 list is larger than the HTML4 list at
15// http://www.w3.org/TR/html4/sgml/entities.html
16var entity = map[string]rune{
17 "AElig;": '\U000000C6',
18 "AMP;": '\U00000026',
19 "Aacute;": '\U000000C1',
20 "Abreve;": '\U00000102',
21 "Acirc;": '\U000000C2',
22 "Acy;": '\U00000410',
23 "Afr;": '\U0001D504',
24 "Agrave;": '\U000000C0',
25 "Alpha;": '\U00000391',
26 "Amacr;": '\U00000100',
27 "And;": '\U00002A53',
28 "Aogon;": '\U00000104',
29 "Aopf;": '\U0001D538',
30 "ApplyFunction;": '\U00002061',
31 "Aring;": '\U000000C5',
32 "Ascr;": '\U0001D49C',
33 "Assign;": '\U00002254',
34 "Atilde;": '\U000000C3',
35 "Auml;": '\U000000C4',
36 "Backslash;": '\U00002216',
37 "Barv;": '\U00002AE7',
38 "Barwed;": '\U00002306',
39 "Bcy;": '\U00000411',
40 "Because;": '\U00002235',
41 "Bernoullis;": '\U0000212C',
42 "Beta;": '\U00000392',
43 "Bfr;": '\U0001D505',
44 "Bopf;": '\U0001D539',
45 "Breve;": '\U000002D8',
46 "Bscr;": '\U0000212C',
47 "Bumpeq;": '\U0000224E',
48 "CHcy;": '\U00000427',
49 "COPY;": '\U000000A9',
50 "Cacute;": '\U00000106',
51 "Cap;": '\U000022D2',
52 "CapitalDifferentialD;": '\U00002145',
53 "Cayleys;": '\U0000212D',
54 "Ccaron;": '\U0000010C',
55 "Ccedil;": '\U000000C7',
56 "Ccirc;": '\U00000108',
57 "Cconint;": '\U00002230',
58 "Cdot;": '\U0000010A',
59 "Cedilla;": '\U000000B8',
60 "CenterDot;": '\U000000B7',
61 "Cfr;": '\U0000212D',
62 "Chi;": '\U000003A7',
63 "CircleDot;": '\U00002299',
64 "CircleMinus;": '\U00002296',
65 "CirclePlus;": '\U00002295',
66 "CircleTimes;": '\U00002297',
67 "ClockwiseContourIntegral;": '\U00002232',
68 "CloseCurlyDoubleQuote;": '\U0000201D',
69 "CloseCurlyQuote;": '\U00002019',
70 "Colon;": '\U00002237',
71 "Colone;": '\U00002A74',
72 "Congruent;": '\U00002261',
73 "Conint;": '\U0000222F',
74 "ContourIntegral;": '\U0000222E',
75 "Copf;": '\U00002102',
76 "Coproduct;": '\U00002210',
77 "CounterClockwiseContourIntegral;": '\U00002233',
78 "Cross;": '\U00002A2F',
79 "Cscr;": '\U0001D49E',
80 "Cup;": '\U000022D3',
81 "CupCap;": '\U0000224D',
82 "DD;": '\U00002145',
83 "DDotrahd;": '\U00002911',
84 "DJcy;": '\U00000402',
85 "DScy;": '\U00000405',
86 "DZcy;": '\U0000040F',
87 "Dagger;": '\U00002021',
88 "Darr;": '\U000021A1',
89 "Dashv;": '\U00002AE4',
90 "Dcaron;": '\U0000010E',
91 "Dcy;": '\U00000414',
92 "Del;": '\U00002207',
93 "Delta;": '\U00000394',
94 "Dfr;": '\U0001D507',
95 "DiacriticalAcute;": '\U000000B4',
96 "DiacriticalDot;": '\U000002D9',
97 "DiacriticalDoubleAcute;": '\U000002DD',
98 "DiacriticalGrave;": '\U00000060',
99 "DiacriticalTilde;": '\U000002DC',
100 "Diamond;": '\U000022C4',
101 "DifferentialD;": '\U00002146',
102 "Dopf;": '\U0001D53B',
103 "Dot;": '\U000000A8',
104 "DotDot;": '\U000020DC',
105 "DotEqual;": '\U00002250',
106 "DoubleContourIntegral;": '\U0000222F',
107 "DoubleDot;": '\U000000A8',
108 "DoubleDownArrow;": '\U000021D3',
109 "DoubleLeftArrow;": '\U000021D0',
110 "DoubleLeftRightArrow;": '\U000021D4',
111 "DoubleLeftTee;": '\U00002AE4',
112 "DoubleLongLeftArrow;": '\U000027F8',
113 "DoubleLongLeftRightArrow;": '\U000027FA',
114 "DoubleLongRightArrow;": '\U000027F9',
115 "DoubleRightArrow;": '\U000021D2',
116 "DoubleRightTee;": '\U000022A8',
117 "DoubleUpArrow;": '\U000021D1',
118 "DoubleUpDownArrow;": '\U000021D5',
119 "DoubleVerticalBar;": '\U00002225',
120 "DownArrow;": '\U00002193',
121 "DownArrowBar;": '\U00002913',
122 "DownArrowUpArrow;": '\U000021F5',
123 "DownBreve;": '\U00000311',
124 "DownLeftRightVector;": '\U00002950',
125 "DownLeftTeeVector;": '\U0000295E',
126 "DownLeftVector;": '\U000021BD',
127 "DownLeftVectorBar;": '\U00002956',
128 "DownRightTeeVector;": '\U0000295F',
129 "DownRightVector;": '\U000021C1',
130 "DownRightVectorBar;": '\U00002957',
131 "DownTee;": '\U000022A4',
132 "DownTeeArrow;": '\U000021A7',
133 "Downarrow;": '\U000021D3',
134 "Dscr;": '\U0001D49F',
135 "Dstrok;": '\U00000110',
136 "ENG;": '\U0000014A',
137 "ETH;": '\U000000D0',
138 "Eacute;": '\U000000C9',
139 "Ecaron;": '\U0000011A',
140 "Ecirc;": '\U000000CA',
141 "Ecy;": '\U0000042D',
142 "Edot;": '\U00000116',
143 "Efr;": '\U0001D508',
144 "Egrave;": '\U000000C8',
145 "Element;": '\U00002208',
146 "Emacr;": '\U00000112',
147 "EmptySmallSquare;": '\U000025FB',
148 "EmptyVerySmallSquare;": '\U000025AB',
149 "Eogon;": '\U00000118',
150 "Eopf;": '\U0001D53C',
151 "Epsilon;": '\U00000395',
152 "Equal;": '\U00002A75',
153 "EqualTilde;": '\U00002242',
154 "Equilibrium;": '\U000021CC',
155 "Escr;": '\U00002130',
156 "Esim;": '\U00002A73',
157 "Eta;": '\U00000397',
158 "Euml;": '\U000000CB',
159 "Exists;": '\U00002203',
160 "ExponentialE;": '\U00002147',
161 "Fcy;": '\U00000424',
162 "Ffr;": '\U0001D509',
163 "FilledSmallSquare;": '\U000025FC',
164 "FilledVerySmallSquare;": '\U000025AA',
165 "Fopf;": '\U0001D53D',
166 "ForAll;": '\U00002200',
167 "Fouriertrf;": '\U00002131',
168 "Fscr;": '\U00002131',
169 "GJcy;": '\U00000403',
170 "GT;": '\U0000003E',
171 "Gamma;": '\U00000393',
172 "Gammad;": '\U000003DC',
173 "Gbreve;": '\U0000011E',
174 "Gcedil;": '\U00000122',
175 "Gcirc;": '\U0000011C',
176 "Gcy;": '\U00000413',
177 "Gdot;": '\U00000120',
178 "Gfr;": '\U0001D50A',
179 "Gg;": '\U000022D9',
180 "Gopf;": '\U0001D53E',
181 "GreaterEqual;": '\U00002265',
182 "GreaterEqualLess;": '\U000022DB',
183 "GreaterFullEqual;": '\U00002267',
184 "GreaterGreater;": '\U00002AA2',
185 "GreaterLess;": '\U00002277',
186 "GreaterSlantEqual;": '\U00002A7E',
187 "GreaterTilde;": '\U00002273',
188 "Gscr;": '\U0001D4A2',
189 "Gt;": '\U0000226B',
190 "HARDcy;": '\U0000042A',
191 "Hacek;": '\U000002C7',
192 "Hat;": '\U0000005E',
193 "Hcirc;": '\U00000124',
194 "Hfr;": '\U0000210C',
195 "HilbertSpace;": '\U0000210B',
196 "Hopf;": '\U0000210D',
197 "HorizontalLine;": '\U00002500',
198 "Hscr;": '\U0000210B',
199 "Hstrok;": '\U00000126',
200 "HumpDownHump;": '\U0000224E',
201 "HumpEqual;": '\U0000224F',
202 "IEcy;": '\U00000415',
203 "IJlig;": '\U00000132',
204 "IOcy;": '\U00000401',
205 "Iacute;": '\U000000CD',
206 "Icirc;": '\U000000CE',
207 "Icy;": '\U00000418',
208 "Idot;": '\U00000130',
209 "Ifr;": '\U00002111',
210 "Igrave;": '\U000000CC',
211 "Im;": '\U00002111',
212 "Imacr;": '\U0000012A',
213 "ImaginaryI;": '\U00002148',
214 "Implies;": '\U000021D2',
215 "Int;": '\U0000222C',
216 "Integral;": '\U0000222B',
217 "Intersection;": '\U000022C2',
218 "InvisibleComma;": '\U00002063',
219 "InvisibleTimes;": '\U00002062',
220 "Iogon;": '\U0000012E',
221 "Iopf;": '\U0001D540',
222 "Iota;": '\U00000399',
223 "Iscr;": '\U00002110',
224 "Itilde;": '\U00000128',
225 "Iukcy;": '\U00000406',
226 "Iuml;": '\U000000CF',
227 "Jcirc;": '\U00000134',
228 "Jcy;": '\U00000419',
229 "Jfr;": '\U0001D50D',
230 "Jopf;": '\U0001D541',
231 "Jscr;": '\U0001D4A5',
232 "Jsercy;": '\U00000408',
233 "Jukcy;": '\U00000404',
234 "KHcy;": '\U00000425',
235 "KJcy;": '\U0000040C',
236 "Kappa;": '\U0000039A',
237 "Kcedil;": '\U00000136',
238 "Kcy;": '\U0000041A',
239 "Kfr;": '\U0001D50E',
240 "Kopf;": '\U0001D542',
241 "Kscr;": '\U0001D4A6',
242 "LJcy;": '\U00000409',
243 "LT;": '\U0000003C',
244 "Lacute;": '\U00000139',
245 "Lambda;": '\U0000039B',
246 "Lang;": '\U000027EA',
247 "Laplacetrf;": '\U00002112',
248 "Larr;": '\U0000219E',
249 "Lcaron;": '\U0000013D',
250 "Lcedil;": '\U0000013B',
251 "Lcy;": '\U0000041B',
252 "LeftAngleBracket;": '\U000027E8',
253 "LeftArrow;": '\U00002190',
254 "LeftArrowBar;": '\U000021E4',
255 "LeftArrowRightArrow;": '\U000021C6',
256 "LeftCeiling;": '\U00002308',
257 "LeftDoubleBracket;": '\U000027E6',
258 "LeftDownTeeVector;": '\U00002961',
259 "LeftDownVector;": '\U000021C3',
260 "LeftDownVectorBar;": '\U00002959',
261 "LeftFloor;": '\U0000230A',
262 "LeftRightArrow;": '\U00002194',
263 "LeftRightVector;": '\U0000294E',
264 "LeftTee;": '\U000022A3',
265 "LeftTeeArrow;": '\U000021A4',
266 "LeftTeeVector;": '\U0000295A',
267 "LeftTriangle;": '\U000022B2',
268 "LeftTriangleBar;": '\U000029CF',
269 "LeftTriangleEqual;": '\U000022B4',
270 "LeftUpDownVector;": '\U00002951',
271 "LeftUpTeeVector;": '\U00002960',
272 "LeftUpVector;": '\U000021BF',
273 "LeftUpVectorBar;": '\U00002958',
274 "LeftVector;": '\U000021BC',
275 "LeftVectorBar;": '\U00002952',
276 "Leftarrow;": '\U000021D0',
277 "Leftrightarrow;": '\U000021D4',
278 "LessEqualGreater;": '\U000022DA',
279 "LessFullEqual;": '\U00002266',
280 "LessGreater;": '\U00002276',
281 "LessLess;": '\U00002AA1',
282 "LessSlantEqual;": '\U00002A7D',
283 "LessTilde;": '\U00002272',
284 "Lfr;": '\U0001D50F',
285 "Ll;": '\U000022D8',
286 "Lleftarrow;": '\U000021DA',
287 "Lmidot;": '\U0000013F',
288 "LongLeftArrow;": '\U000027F5',
289 "LongLeftRightArrow;": '\U000027F7',
290 "LongRightArrow;": '\U000027F6',
291 "Longleftarrow;": '\U000027F8',
292 "Longleftrightarrow;": '\U000027FA',
293 "Longrightarrow;": '\U000027F9',
294 "Lopf;": '\U0001D543',
295 "LowerLeftArrow;": '\U00002199',
296 "LowerRightArrow;": '\U00002198',
297 "Lscr;": '\U00002112',
298 "Lsh;": '\U000021B0',
299 "Lstrok;": '\U00000141',
300 "Lt;": '\U0000226A',
301 "Map;": '\U00002905',
302 "Mcy;": '\U0000041C',
303 "MediumSpace;": '\U0000205F',
304 "Mellintrf;": '\U00002133',
305 "Mfr;": '\U0001D510',
306 "MinusPlus;": '\U00002213',
307 "Mopf;": '\U0001D544',
308 "Mscr;": '\U00002133',
309 "Mu;": '\U0000039C',
310 "NJcy;": '\U0000040A',
311 "Nacute;": '\U00000143',
312 "Ncaron;": '\U00000147',
313 "Ncedil;": '\U00000145',
314 "Ncy;": '\U0000041D',
315 "NegativeMediumSpace;": '\U0000200B',
316 "NegativeThickSpace;": '\U0000200B',
317 "NegativeThinSpace;": '\U0000200B',
318 "NegativeVeryThinSpace;": '\U0000200B',
319 "NestedGreaterGreater;": '\U0000226B',
320 "NestedLessLess;": '\U0000226A',
321 "NewLine;": '\U0000000A',
322 "Nfr;": '\U0001D511',
323 "NoBreak;": '\U00002060',
324 "NonBreakingSpace;": '\U000000A0',
325 "Nopf;": '\U00002115',
326 "Not;": '\U00002AEC',
327 "NotCongruent;": '\U00002262',
328 "NotCupCap;": '\U0000226D',
329 "NotDoubleVerticalBar;": '\U00002226',
330 "NotElement;": '\U00002209',
331 "NotEqual;": '\U00002260',
332 "NotExists;": '\U00002204',
333 "NotGreater;": '\U0000226F',
334 "NotGreaterEqual;": '\U00002271',
335 "NotGreaterLess;": '\U00002279',
336 "NotGreaterTilde;": '\U00002275',
337 "NotLeftTriangle;": '\U000022EA',
338 "NotLeftTriangleEqual;": '\U000022EC',
339 "NotLess;": '\U0000226E',
340 "NotLessEqual;": '\U00002270',
341 "NotLessGreater;": '\U00002278',
342 "NotLessTilde;": '\U00002274',
343 "NotPrecedes;": '\U00002280',
344 "NotPrecedesSlantEqual;": '\U000022E0',
345 "NotReverseElement;": '\U0000220C',
346 "NotRightTriangle;": '\U000022EB',
347 "NotRightTriangleEqual;": '\U000022ED',
348 "NotSquareSubsetEqual;": '\U000022E2',
349 "NotSquareSupersetEqual;": '\U000022E3',
350 "NotSubsetEqual;": '\U00002288',
351 "NotSucceeds;": '\U00002281',
352 "NotSucceedsSlantEqual;": '\U000022E1',
353 "NotSupersetEqual;": '\U00002289',
354 "NotTilde;": '\U00002241',
355 "NotTildeEqual;": '\U00002244',
356 "NotTildeFullEqual;": '\U00002247',
357 "NotTildeTilde;": '\U00002249',
358 "NotVerticalBar;": '\U00002224',
359 "Nscr;": '\U0001D4A9',
360 "Ntilde;": '\U000000D1',
361 "Nu;": '\U0000039D',
362 "OElig;": '\U00000152',
363 "Oacute;": '\U000000D3',
364 "Ocirc;": '\U000000D4',
365 "Ocy;": '\U0000041E',
366 "Odblac;": '\U00000150',
367 "Ofr;": '\U0001D512',
368 "Ograve;": '\U000000D2',
369 "Omacr;": '\U0000014C',
370 "Omega;": '\U000003A9',
371 "Omicron;": '\U0000039F',
372 "Oopf;": '\U0001D546',
373 "OpenCurlyDoubleQuote;": '\U0000201C',
374 "OpenCurlyQuote;": '\U00002018',
375 "Or;": '\U00002A54',
376 "Oscr;": '\U0001D4AA',
377 "Oslash;": '\U000000D8',
378 "Otilde;": '\U000000D5',
379 "Otimes;": '\U00002A37',
380 "Ouml;": '\U000000D6',
381 "OverBar;": '\U0000203E',
382 "OverBrace;": '\U000023DE',
383 "OverBracket;": '\U000023B4',
384 "OverParenthesis;": '\U000023DC',
385 "PartialD;": '\U00002202',
386 "Pcy;": '\U0000041F',
387 "Pfr;": '\U0001D513',
388 "Phi;": '\U000003A6',
389 "Pi;": '\U000003A0',
390 "PlusMinus;": '\U000000B1',
391 "Poincareplane;": '\U0000210C',
392 "Popf;": '\U00002119',
393 "Pr;": '\U00002ABB',
394 "Precedes;": '\U0000227A',
395 "PrecedesEqual;": '\U00002AAF',
396 "PrecedesSlantEqual;": '\U0000227C',
397 "PrecedesTilde;": '\U0000227E',
398 "Prime;": '\U00002033',
399 "Product;": '\U0000220F',
400 "Proportion;": '\U00002237',
401 "Proportional;": '\U0000221D',
402 "Pscr;": '\U0001D4AB',
403 "Psi;": '\U000003A8',
404 "QUOT;": '\U00000022',
405 "Qfr;": '\U0001D514',
406 "Qopf;": '\U0000211A',
407 "Qscr;": '\U0001D4AC',
408 "RBarr;": '\U00002910',
409 "REG;": '\U000000AE',
410 "Racute;": '\U00000154',
411 "Rang;": '\U000027EB',
412 "Rarr;": '\U000021A0',
413 "Rarrtl;": '\U00002916',
414 "Rcaron;": '\U00000158',
415 "Rcedil;": '\U00000156',
416 "Rcy;": '\U00000420',
417 "Re;": '\U0000211C',
418 "ReverseElement;": '\U0000220B',
419 "ReverseEquilibrium;": '\U000021CB',
420 "ReverseUpEquilibrium;": '\U0000296F',
421 "Rfr;": '\U0000211C',
422 "Rho;": '\U000003A1',
423 "RightAngleBracket;": '\U000027E9',
424 "RightArrow;": '\U00002192',
425 "RightArrowBar;": '\U000021E5',
426 "RightArrowLeftArrow;": '\U000021C4',
427 "RightCeiling;": '\U00002309',
428 "RightDoubleBracket;": '\U000027E7',
429 "RightDownTeeVector;": '\U0000295D',
430 "RightDownVector;": '\U000021C2',
431 "RightDownVectorBar;": '\U00002955',
432 "RightFloor;": '\U0000230B',
433 "RightTee;": '\U000022A2',
434 "RightTeeArrow;": '\U000021A6',
435 "RightTeeVector;": '\U0000295B',
436 "RightTriangle;": '\U000022B3',
437 "RightTriangleBar;": '\U000029D0',
438 "RightTriangleEqual;": '\U000022B5',
439 "RightUpDownVector;": '\U0000294F',
440 "RightUpTeeVector;": '\U0000295C',
441 "RightUpVector;": '\U000021BE',
442 "RightUpVectorBar;": '\U00002954',
443 "RightVector;": '\U000021C0',
444 "RightVectorBar;": '\U00002953',
445 "Rightarrow;": '\U000021D2',
446 "Ropf;": '\U0000211D',
447 "RoundImplies;": '\U00002970',
448 "Rrightarrow;": '\U000021DB',
449 "Rscr;": '\U0000211B',
450 "Rsh;": '\U000021B1',
451 "RuleDelayed;": '\U000029F4',
452 "SHCHcy;": '\U00000429',
453 "SHcy;": '\U00000428',
454 "SOFTcy;": '\U0000042C',
455 "Sacute;": '\U0000015A',
456 "Sc;": '\U00002ABC',
457 "Scaron;": '\U00000160',
458 "Scedil;": '\U0000015E',
459 "Scirc;": '\U0000015C',
460 "Scy;": '\U00000421',
461 "Sfr;": '\U0001D516',
462 "ShortDownArrow;": '\U00002193',
463 "ShortLeftArrow;": '\U00002190',
464 "ShortRightArrow;": '\U00002192',
465 "ShortUpArrow;": '\U00002191',
466 "Sigma;": '\U000003A3',
467 "SmallCircle;": '\U00002218',
468 "Sopf;": '\U0001D54A',
469 "Sqrt;": '\U0000221A',
470 "Square;": '\U000025A1',
471 "SquareIntersection;": '\U00002293',
472 "SquareSubset;": '\U0000228F',
473 "SquareSubsetEqual;": '\U00002291',
474 "SquareSuperset;": '\U00002290',
475 "SquareSupersetEqual;": '\U00002292',
476 "SquareUnion;": '\U00002294',
477 "Sscr;": '\U0001D4AE',
478 "Star;": '\U000022C6',
479 "Sub;": '\U000022D0',
480 "Subset;": '\U000022D0',
481 "SubsetEqual;": '\U00002286',
482 "Succeeds;": '\U0000227B',
483 "SucceedsEqual;": '\U00002AB0',
484 "SucceedsSlantEqual;": '\U0000227D',
485 "SucceedsTilde;": '\U0000227F',
486 "SuchThat;": '\U0000220B',
487 "Sum;": '\U00002211',
488 "Sup;": '\U000022D1',
489 "Superset;": '\U00002283',
490 "SupersetEqual;": '\U00002287',
491 "Supset;": '\U000022D1',
492 "THORN;": '\U000000DE',
493 "TRADE;": '\U00002122',
494 "TSHcy;": '\U0000040B',
495 "TScy;": '\U00000426',
496 "Tab;": '\U00000009',
497 "Tau;": '\U000003A4',
498 "Tcaron;": '\U00000164',
499 "Tcedil;": '\U00000162',
500 "Tcy;": '\U00000422',
501 "Tfr;": '\U0001D517',
502 "Therefore;": '\U00002234',
503 "Theta;": '\U00000398',
504 "ThinSpace;": '\U00002009',
505 "Tilde;": '\U0000223C',
506 "TildeEqual;": '\U00002243',
507 "TildeFullEqual;": '\U00002245',
508 "TildeTilde;": '\U00002248',
509 "Topf;": '\U0001D54B',
510 "TripleDot;": '\U000020DB',
511 "Tscr;": '\U0001D4AF',
512 "Tstrok;": '\U00000166',
513 "Uacute;": '\U000000DA',
514 "Uarr;": '\U0000219F',
515 "Uarrocir;": '\U00002949',
516 "Ubrcy;": '\U0000040E',
517 "Ubreve;": '\U0000016C',
518 "Ucirc;": '\U000000DB',
519 "Ucy;": '\U00000423',
520 "Udblac;": '\U00000170',
521 "Ufr;": '\U0001D518',
522 "Ugrave;": '\U000000D9',
523 "Umacr;": '\U0000016A',
524 "UnderBar;": '\U0000005F',
525 "UnderBrace;": '\U000023DF',
526 "UnderBracket;": '\U000023B5',
527 "UnderParenthesis;": '\U000023DD',
528 "Union;": '\U000022C3',
529 "UnionPlus;": '\U0000228E',
530 "Uogon;": '\U00000172',
531 "Uopf;": '\U0001D54C',
532 "UpArrow;": '\U00002191',
533 "UpArrowBar;": '\U00002912',
534 "UpArrowDownArrow;": '\U000021C5',
535 "UpDownArrow;": '\U00002195',
536 "UpEquilibrium;": '\U0000296E',
537 "UpTee;": '\U000022A5',
538 "UpTeeArrow;": '\U000021A5',
539 "Uparrow;": '\U000021D1',
540 "Updownarrow;": '\U000021D5',
541 "UpperLeftArrow;": '\U00002196',
542 "UpperRightArrow;": '\U00002197',
543 "Upsi;": '\U000003D2',
544 "Upsilon;": '\U000003A5',
545 "Uring;": '\U0000016E',
546 "Uscr;": '\U0001D4B0',
547 "Utilde;": '\U00000168',
548 "Uuml;": '\U000000DC',
549 "VDash;": '\U000022AB',
550 "Vbar;": '\U00002AEB',
551 "Vcy;": '\U00000412',
552 "Vdash;": '\U000022A9',
553 "Vdashl;": '\U00002AE6',
554 "Vee;": '\U000022C1',
555 "Verbar;": '\U00002016',
556 "Vert;": '\U00002016',
557 "VerticalBar;": '\U00002223',
558 "VerticalLine;": '\U0000007C',
559 "VerticalSeparator;": '\U00002758',
560 "VerticalTilde;": '\U00002240',
561 "VeryThinSpace;": '\U0000200A',
562 "Vfr;": '\U0001D519',
563 "Vopf;": '\U0001D54D',
564 "Vscr;": '\U0001D4B1',
565 "Vvdash;": '\U000022AA',
566 "Wcirc;": '\U00000174',
567 "Wedge;": '\U000022C0',
568 "Wfr;": '\U0001D51A',
569 "Wopf;": '\U0001D54E',
570 "Wscr;": '\U0001D4B2',
571 "Xfr;": '\U0001D51B',
572 "Xi;": '\U0000039E',
573 "Xopf;": '\U0001D54F',
574 "Xscr;": '\U0001D4B3',
575 "YAcy;": '\U0000042F',
576 "YIcy;": '\U00000407',
577 "YUcy;": '\U0000042E',
578 "Yacute;": '\U000000DD',
579 "Ycirc;": '\U00000176',
580 "Ycy;": '\U0000042B',
581 "Yfr;": '\U0001D51C',
582 "Yopf;": '\U0001D550',
583 "Yscr;": '\U0001D4B4',
584 "Yuml;": '\U00000178',
585 "ZHcy;": '\U00000416',
586 "Zacute;": '\U00000179',
587 "Zcaron;": '\U0000017D',
588 "Zcy;": '\U00000417',
589 "Zdot;": '\U0000017B',
590 "ZeroWidthSpace;": '\U0000200B',
591 "Zeta;": '\U00000396',
592 "Zfr;": '\U00002128',
593 "Zopf;": '\U00002124',
594 "Zscr;": '\U0001D4B5',
595 "aacute;": '\U000000E1',
596 "abreve;": '\U00000103',
597 "ac;": '\U0000223E',
598 "acd;": '\U0000223F',
599 "acirc;": '\U000000E2',
600 "acute;": '\U000000B4',
601 "acy;": '\U00000430',
602 "aelig;": '\U000000E6',
603 "af;": '\U00002061',
604 "afr;": '\U0001D51E',
605 "agrave;": '\U000000E0',
606 "alefsym;": '\U00002135',
607 "aleph;": '\U00002135',
608 "alpha;": '\U000003B1',
609 "amacr;": '\U00000101',
610 "amalg;": '\U00002A3F',
611 "amp;": '\U00000026',
612 "and;": '\U00002227',
613 "andand;": '\U00002A55',
614 "andd;": '\U00002A5C',
615 "andslope;": '\U00002A58',
616 "andv;": '\U00002A5A',
617 "ang;": '\U00002220',
618 "ange;": '\U000029A4',
619 "angle;": '\U00002220',
620 "angmsd;": '\U00002221',
621 "angmsdaa;": '\U000029A8',
622 "angmsdab;": '\U000029A9',
623 "angmsdac;": '\U000029AA',
624 "angmsdad;": '\U000029AB',
625 "angmsdae;": '\U000029AC',
626 "angmsdaf;": '\U000029AD',
627 "angmsdag;": '\U000029AE',
628 "angmsdah;": '\U000029AF',
629 "angrt;": '\U0000221F',
630 "angrtvb;": '\U000022BE',
631 "angrtvbd;": '\U0000299D',
632 "angsph;": '\U00002222',
633 "angst;": '\U000000C5',
634 "angzarr;": '\U0000237C',
635 "aogon;": '\U00000105',
636 "aopf;": '\U0001D552',
637 "ap;": '\U00002248',
638 "apE;": '\U00002A70',
639 "apacir;": '\U00002A6F',
640 "ape;": '\U0000224A',
641 "apid;": '\U0000224B',
642 "apos;": '\U00000027',
643 "approx;": '\U00002248',
644 "approxeq;": '\U0000224A',
645 "aring;": '\U000000E5',
646 "ascr;": '\U0001D4B6',
647 "ast;": '\U0000002A',
648 "asymp;": '\U00002248',
649 "asympeq;": '\U0000224D',
650 "atilde;": '\U000000E3',
651 "auml;": '\U000000E4',
652 "awconint;": '\U00002233',
653 "awint;": '\U00002A11',
654 "bNot;": '\U00002AED',
655 "backcong;": '\U0000224C',
656 "backepsilon;": '\U000003F6',
657 "backprime;": '\U00002035',
658 "backsim;": '\U0000223D',
659 "backsimeq;": '\U000022CD',
660 "barvee;": '\U000022BD',
661 "barwed;": '\U00002305',
662 "barwedge;": '\U00002305',
663 "bbrk;": '\U000023B5',
664 "bbrktbrk;": '\U000023B6',
665 "bcong;": '\U0000224C',
666 "bcy;": '\U00000431',
667 "bdquo;": '\U0000201E',
668 "becaus;": '\U00002235',
669 "because;": '\U00002235',
670 "bemptyv;": '\U000029B0',
671 "bepsi;": '\U000003F6',
672 "bernou;": '\U0000212C',
673 "beta;": '\U000003B2',
674 "beth;": '\U00002136',
675 "between;": '\U0000226C',
676 "bfr;": '\U0001D51F',
677 "bigcap;": '\U000022C2',
678 "bigcirc;": '\U000025EF',
679 "bigcup;": '\U000022C3',
680 "bigodot;": '\U00002A00',
681 "bigoplus;": '\U00002A01',
682 "bigotimes;": '\U00002A02',
683 "bigsqcup;": '\U00002A06',
684 "bigstar;": '\U00002605',
685 "bigtriangledown;": '\U000025BD',
686 "bigtriangleup;": '\U000025B3',
687 "biguplus;": '\U00002A04',
688 "bigvee;": '\U000022C1',
689 "bigwedge;": '\U000022C0',
690 "bkarow;": '\U0000290D',
691 "blacklozenge;": '\U000029EB',
692 "blacksquare;": '\U000025AA',
693 "blacktriangle;": '\U000025B4',
694 "blacktriangledown;": '\U000025BE',
695 "blacktriangleleft;": '\U000025C2',
696 "blacktriangleright;": '\U000025B8',
697 "blank;": '\U00002423',
698 "blk12;": '\U00002592',
699 "blk14;": '\U00002591',
700 "blk34;": '\U00002593',
701 "block;": '\U00002588',
702 "bnot;": '\U00002310',
703 "bopf;": '\U0001D553',
704 "bot;": '\U000022A5',
705 "bottom;": '\U000022A5',
706 "bowtie;": '\U000022C8',
707 "boxDL;": '\U00002557',
708 "boxDR;": '\U00002554',
709 "boxDl;": '\U00002556',
710 "boxDr;": '\U00002553',
711 "boxH;": '\U00002550',
712 "boxHD;": '\U00002566',
713 "boxHU;": '\U00002569',
714 "boxHd;": '\U00002564',
715 "boxHu;": '\U00002567',
716 "boxUL;": '\U0000255D',
717 "boxUR;": '\U0000255A',
718 "boxUl;": '\U0000255C',
719 "boxUr;": '\U00002559',
720 "boxV;": '\U00002551',
721 "boxVH;": '\U0000256C',
722 "boxVL;": '\U00002563',
723 "boxVR;": '\U00002560',
724 "boxVh;": '\U0000256B',
725 "boxVl;": '\U00002562',
726 "boxVr;": '\U0000255F',
727 "boxbox;": '\U000029C9',
728 "boxdL;": '\U00002555',
729 "boxdR;": '\U00002552',
730 "boxdl;": '\U00002510',
731 "boxdr;": '\U0000250C',
732 "boxh;": '\U00002500',
733 "boxhD;": '\U00002565',
734 "boxhU;": '\U00002568',
735 "boxhd;": '\U0000252C',
736 "boxhu;": '\U00002534',
737 "boxminus;": '\U0000229F',
738 "boxplus;": '\U0000229E',
739 "boxtimes;": '\U000022A0',
740 "boxuL;": '\U0000255B',
741 "boxuR;": '\U00002558',
742 "boxul;": '\U00002518',
743 "boxur;": '\U00002514',
744 "boxv;": '\U00002502',
745 "boxvH;": '\U0000256A',
746 "boxvL;": '\U00002561',
747 "boxvR;": '\U0000255E',
748 "boxvh;": '\U0000253C',
749 "boxvl;": '\U00002524',
750 "boxvr;": '\U0000251C',
751 "bprime;": '\U00002035',
752 "breve;": '\U000002D8',
753 "brvbar;": '\U000000A6',
754 "bscr;": '\U0001D4B7',
755 "bsemi;": '\U0000204F',
756 "bsim;": '\U0000223D',
757 "bsime;": '\U000022CD',
758 "bsol;": '\U0000005C',
759 "bsolb;": '\U000029C5',
760 "bsolhsub;": '\U000027C8',
761 "bull;": '\U00002022',
762 "bullet;": '\U00002022',
763 "bump;": '\U0000224E',
764 "bumpE;": '\U00002AAE',
765 "bumpe;": '\U0000224F',
766 "bumpeq;": '\U0000224F',
767 "cacute;": '\U00000107',
768 "cap;": '\U00002229',
769 "capand;": '\U00002A44',
770 "capbrcup;": '\U00002A49',
771 "capcap;": '\U00002A4B',
772 "capcup;": '\U00002A47',
773 "capdot;": '\U00002A40',
774 "caret;": '\U00002041',
775 "caron;": '\U000002C7',
776 "ccaps;": '\U00002A4D',
777 "ccaron;": '\U0000010D',
778 "ccedil;": '\U000000E7',
779 "ccirc;": '\U00000109',
780 "ccups;": '\U00002A4C',
781 "ccupssm;": '\U00002A50',
782 "cdot;": '\U0000010B',
783 "cedil;": '\U000000B8',
784 "cemptyv;": '\U000029B2',
785 "cent;": '\U000000A2',
786 "centerdot;": '\U000000B7',
787 "cfr;": '\U0001D520',
788 "chcy;": '\U00000447',
789 "check;": '\U00002713',
790 "checkmark;": '\U00002713',
791 "chi;": '\U000003C7',
792 "cir;": '\U000025CB',
793 "cirE;": '\U000029C3',
794 "circ;": '\U000002C6',
795 "circeq;": '\U00002257',
796 "circlearrowleft;": '\U000021BA',
797 "circlearrowright;": '\U000021BB',
798 "circledR;": '\U000000AE',
799 "circledS;": '\U000024C8',
800 "circledast;": '\U0000229B',
801 "circledcirc;": '\U0000229A',
802 "circleddash;": '\U0000229D',
803 "cire;": '\U00002257',
804 "cirfnint;": '\U00002A10',
805 "cirmid;": '\U00002AEF',
806 "cirscir;": '\U000029C2',
807 "clubs;": '\U00002663',
808 "clubsuit;": '\U00002663',
809 "colon;": '\U0000003A',
810 "colone;": '\U00002254',
811 "coloneq;": '\U00002254',
812 "comma;": '\U0000002C',
813 "commat;": '\U00000040',
814 "comp;": '\U00002201',
815 "compfn;": '\U00002218',
816 "complement;": '\U00002201',
817 "complexes;": '\U00002102',
818 "cong;": '\U00002245',
819 "congdot;": '\U00002A6D',
820 "conint;": '\U0000222E',
821 "copf;": '\U0001D554',
822 "coprod;": '\U00002210',
823 "copy;": '\U000000A9',
824 "copysr;": '\U00002117',
825 "crarr;": '\U000021B5',
826 "cross;": '\U00002717',
827 "cscr;": '\U0001D4B8',
828 "csub;": '\U00002ACF',
829 "csube;": '\U00002AD1',
830 "csup;": '\U00002AD0',
831 "csupe;": '\U00002AD2',
832 "ctdot;": '\U000022EF',
833 "cudarrl;": '\U00002938',
834 "cudarrr;": '\U00002935',
835 "cuepr;": '\U000022DE',
836 "cuesc;": '\U000022DF',
837 "cularr;": '\U000021B6',
838 "cularrp;": '\U0000293D',
839 "cup;": '\U0000222A',
840 "cupbrcap;": '\U00002A48',
841 "cupcap;": '\U00002A46',
842 "cupcup;": '\U00002A4A',
843 "cupdot;": '\U0000228D',
844 "cupor;": '\U00002A45',
845 "curarr;": '\U000021B7',
846 "curarrm;": '\U0000293C',
847 "curlyeqprec;": '\U000022DE',
848 "curlyeqsucc;": '\U000022DF',
849 "curlyvee;": '\U000022CE',
850 "curlywedge;": '\U000022CF',
851 "curren;": '\U000000A4',
852 "curvearrowleft;": '\U000021B6',
853 "curvearrowright;": '\U000021B7',
854 "cuvee;": '\U000022CE',
855 "cuwed;": '\U000022CF',
856 "cwconint;": '\U00002232',
857 "cwint;": '\U00002231',
858 "cylcty;": '\U0000232D',
859 "dArr;": '\U000021D3',
860 "dHar;": '\U00002965',
861 "dagger;": '\U00002020',
862 "daleth;": '\U00002138',
863 "darr;": '\U00002193',
864 "dash;": '\U00002010',
865 "dashv;": '\U000022A3',
866 "dbkarow;": '\U0000290F',
867 "dblac;": '\U000002DD',
868 "dcaron;": '\U0000010F',
869 "dcy;": '\U00000434',
870 "dd;": '\U00002146',
871 "ddagger;": '\U00002021',
872 "ddarr;": '\U000021CA',
873 "ddotseq;": '\U00002A77',
874 "deg;": '\U000000B0',
875 "delta;": '\U000003B4',
876 "demptyv;": '\U000029B1',
877 "dfisht;": '\U0000297F',
878 "dfr;": '\U0001D521',
879 "dharl;": '\U000021C3',
880 "dharr;": '\U000021C2',
881 "diam;": '\U000022C4',
882 "diamond;": '\U000022C4',
883 "diamondsuit;": '\U00002666',
884 "diams;": '\U00002666',
885 "die;": '\U000000A8',
886 "digamma;": '\U000003DD',
887 "disin;": '\U000022F2',
888 "div;": '\U000000F7',
889 "divide;": '\U000000F7',
890 "divideontimes;": '\U000022C7',
891 "divonx;": '\U000022C7',
892 "djcy;": '\U00000452',
893 "dlcorn;": '\U0000231E',
894 "dlcrop;": '\U0000230D',
895 "dollar;": '\U00000024',
896 "dopf;": '\U0001D555',
897 "dot;": '\U000002D9',
898 "doteq;": '\U00002250',
899 "doteqdot;": '\U00002251',
900 "dotminus;": '\U00002238',
901 "dotplus;": '\U00002214',
902 "dotsquare;": '\U000022A1',
903 "doublebarwedge;": '\U00002306',
904 "downarrow;": '\U00002193',
905 "downdownarrows;": '\U000021CA',
906 "downharpoonleft;": '\U000021C3',
907 "downharpoonright;": '\U000021C2',
908 "drbkarow;": '\U00002910',
909 "drcorn;": '\U0000231F',
910 "drcrop;": '\U0000230C',
911 "dscr;": '\U0001D4B9',
912 "dscy;": '\U00000455',
913 "dsol;": '\U000029F6',
914 "dstrok;": '\U00000111',
915 "dtdot;": '\U000022F1',
916 "dtri;": '\U000025BF',
917 "dtrif;": '\U000025BE',
918 "duarr;": '\U000021F5',
919 "duhar;": '\U0000296F',
920 "dwangle;": '\U000029A6',
921 "dzcy;": '\U0000045F',
922 "dzigrarr;": '\U000027FF',
923 "eDDot;": '\U00002A77',
924 "eDot;": '\U00002251',
925 "eacute;": '\U000000E9',
926 "easter;": '\U00002A6E',
927 "ecaron;": '\U0000011B',
928 "ecir;": '\U00002256',
929 "ecirc;": '\U000000EA',
930 "ecolon;": '\U00002255',
931 "ecy;": '\U0000044D',
932 "edot;": '\U00000117',
933 "ee;": '\U00002147',
934 "efDot;": '\U00002252',
935 "efr;": '\U0001D522',
936 "eg;": '\U00002A9A',
937 "egrave;": '\U000000E8',
938 "egs;": '\U00002A96',
939 "egsdot;": '\U00002A98',
940 "el;": '\U00002A99',
941 "elinters;": '\U000023E7',
942 "ell;": '\U00002113',
943 "els;": '\U00002A95',
944 "elsdot;": '\U00002A97',
945 "emacr;": '\U00000113',
946 "empty;": '\U00002205',
947 "emptyset;": '\U00002205',
948 "emptyv;": '\U00002205',
949 "emsp;": '\U00002003',
950 "emsp13;": '\U00002004',
951 "emsp14;": '\U00002005',
952 "eng;": '\U0000014B',
953 "ensp;": '\U00002002',
954 "eogon;": '\U00000119',
955 "eopf;": '\U0001D556',
956 "epar;": '\U000022D5',
957 "eparsl;": '\U000029E3',
958 "eplus;": '\U00002A71',
959 "epsi;": '\U000003B5',
960 "epsilon;": '\U000003B5',
961 "epsiv;": '\U000003F5',
962 "eqcirc;": '\U00002256',
963 "eqcolon;": '\U00002255',
964 "eqsim;": '\U00002242',
965 "eqslantgtr;": '\U00002A96',
966 "eqslantless;": '\U00002A95',
967 "equals;": '\U0000003D',
968 "equest;": '\U0000225F',
969 "equiv;": '\U00002261',
970 "equivDD;": '\U00002A78',
971 "eqvparsl;": '\U000029E5',
972 "erDot;": '\U00002253',
973 "erarr;": '\U00002971',
974 "escr;": '\U0000212F',
975 "esdot;": '\U00002250',
976 "esim;": '\U00002242',
977 "eta;": '\U000003B7',
978 "eth;": '\U000000F0',
979 "euml;": '\U000000EB',
980 "euro;": '\U000020AC',
981 "excl;": '\U00000021',
982 "exist;": '\U00002203',
983 "expectation;": '\U00002130',
984 "exponentiale;": '\U00002147',
985 "fallingdotseq;": '\U00002252',
986 "fcy;": '\U00000444',
987 "female;": '\U00002640',
988 "ffilig;": '\U0000FB03',
989 "fflig;": '\U0000FB00',
990 "ffllig;": '\U0000FB04',
991 "ffr;": '\U0001D523',
992 "filig;": '\U0000FB01',
993 "flat;": '\U0000266D',
994 "fllig;": '\U0000FB02',
995 "fltns;": '\U000025B1',
996 "fnof;": '\U00000192',
997 "fopf;": '\U0001D557',
998 "forall;": '\U00002200',
999 "fork;": '\U000022D4',
1000 "forkv;": '\U00002AD9',
1001 "fpartint;": '\U00002A0D',
1002 "frac12;": '\U000000BD',
1003 "frac13;": '\U00002153',
1004 "frac14;": '\U000000BC',
1005 "frac15;": '\U00002155',
1006 "frac16;": '\U00002159',
1007 "frac18;": '\U0000215B',
1008 "frac23;": '\U00002154',
1009 "frac25;": '\U00002156',
1010 "frac34;": '\U000000BE',
1011 "frac35;": '\U00002157',
1012 "frac38;": '\U0000215C',
1013 "frac45;": '\U00002158',
1014 "frac56;": '\U0000215A',
1015 "frac58;": '\U0000215D',
1016 "frac78;": '\U0000215E',
1017 "frasl;": '\U00002044',
1018 "frown;": '\U00002322',
1019 "fscr;": '\U0001D4BB',
1020 "gE;": '\U00002267',
1021 "gEl;": '\U00002A8C',
1022 "gacute;": '\U000001F5',
1023 "gamma;": '\U000003B3',
1024 "gammad;": '\U000003DD',
1025 "gap;": '\U00002A86',
1026 "gbreve;": '\U0000011F',
1027 "gcirc;": '\U0000011D',
1028 "gcy;": '\U00000433',
1029 "gdot;": '\U00000121',
1030 "ge;": '\U00002265',
1031 "gel;": '\U000022DB',
1032 "geq;": '\U00002265',
1033 "geqq;": '\U00002267',
1034 "geqslant;": '\U00002A7E',
1035 "ges;": '\U00002A7E',
1036 "gescc;": '\U00002AA9',
1037 "gesdot;": '\U00002A80',
1038 "gesdoto;": '\U00002A82',
1039 "gesdotol;": '\U00002A84',
1040 "gesles;": '\U00002A94',
1041 "gfr;": '\U0001D524',
1042 "gg;": '\U0000226B',
1043 "ggg;": '\U000022D9',
1044 "gimel;": '\U00002137',
1045 "gjcy;": '\U00000453',
1046 "gl;": '\U00002277',
1047 "glE;": '\U00002A92',
1048 "gla;": '\U00002AA5',
1049 "glj;": '\U00002AA4',
1050 "gnE;": '\U00002269',
1051 "gnap;": '\U00002A8A',
1052 "gnapprox;": '\U00002A8A',
1053 "gne;": '\U00002A88',
1054 "gneq;": '\U00002A88',
1055 "gneqq;": '\U00002269',
1056 "gnsim;": '\U000022E7',
1057 "gopf;": '\U0001D558',
1058 "grave;": '\U00000060',
1059 "gscr;": '\U0000210A',
1060 "gsim;": '\U00002273',
1061 "gsime;": '\U00002A8E',
1062 "gsiml;": '\U00002A90',
1063 "gt;": '\U0000003E',
1064 "gtcc;": '\U00002AA7',
1065 "gtcir;": '\U00002A7A',
1066 "gtdot;": '\U000022D7',
1067 "gtlPar;": '\U00002995',
1068 "gtquest;": '\U00002A7C',
1069 "gtrapprox;": '\U00002A86',
1070 "gtrarr;": '\U00002978',
1071 "gtrdot;": '\U000022D7',
1072 "gtreqless;": '\U000022DB',
1073 "gtreqqless;": '\U00002A8C',
1074 "gtrless;": '\U00002277',
1075 "gtrsim;": '\U00002273',
1076 "hArr;": '\U000021D4',
1077 "hairsp;": '\U0000200A',
1078 "half;": '\U000000BD',
1079 "hamilt;": '\U0000210B',
1080 "hardcy;": '\U0000044A',
1081 "harr;": '\U00002194',
1082 "harrcir;": '\U00002948',
1083 "harrw;": '\U000021AD',
1084 "hbar;": '\U0000210F',
1085 "hcirc;": '\U00000125',
1086 "hearts;": '\U00002665',
1087 "heartsuit;": '\U00002665',
1088 "hellip;": '\U00002026',
1089 "hercon;": '\U000022B9',
1090 "hfr;": '\U0001D525',
1091 "hksearow;": '\U00002925',
1092 "hkswarow;": '\U00002926',
1093 "hoarr;": '\U000021FF',
1094 "homtht;": '\U0000223B',
1095 "hookleftarrow;": '\U000021A9',
1096 "hookrightarrow;": '\U000021AA',
1097 "hopf;": '\U0001D559',
1098 "horbar;": '\U00002015',
1099 "hscr;": '\U0001D4BD',
1100 "hslash;": '\U0000210F',
1101 "hstrok;": '\U00000127',
1102 "hybull;": '\U00002043',
1103 "hyphen;": '\U00002010',
1104 "iacute;": '\U000000ED',
1105 "ic;": '\U00002063',
1106 "icirc;": '\U000000EE',
1107 "icy;": '\U00000438',
1108 "iecy;": '\U00000435',
1109 "iexcl;": '\U000000A1',
1110 "iff;": '\U000021D4',
1111 "ifr;": '\U0001D526',
1112 "igrave;": '\U000000EC',
1113 "ii;": '\U00002148',
1114 "iiiint;": '\U00002A0C',
1115 "iiint;": '\U0000222D',
1116 "iinfin;": '\U000029DC',
1117 "iiota;": '\U00002129',
1118 "ijlig;": '\U00000133',
1119 "imacr;": '\U0000012B',
1120 "image;": '\U00002111',
1121 "imagline;": '\U00002110',
1122 "imagpart;": '\U00002111',
1123 "imath;": '\U00000131',
1124 "imof;": '\U000022B7',
1125 "imped;": '\U000001B5',
1126 "in;": '\U00002208',
1127 "incare;": '\U00002105',
1128 "infin;": '\U0000221E',
1129 "infintie;": '\U000029DD',
1130 "inodot;": '\U00000131',
1131 "int;": '\U0000222B',
1132 "intcal;": '\U000022BA',
1133 "integers;": '\U00002124',
1134 "intercal;": '\U000022BA',
1135 "intlarhk;": '\U00002A17',
1136 "intprod;": '\U00002A3C',
1137 "iocy;": '\U00000451',
1138 "iogon;": '\U0000012F',
1139 "iopf;": '\U0001D55A',
1140 "iota;": '\U000003B9',
1141 "iprod;": '\U00002A3C',
1142 "iquest;": '\U000000BF',
1143 "iscr;": '\U0001D4BE',
1144 "isin;": '\U00002208',
1145 "isinE;": '\U000022F9',
1146 "isindot;": '\U000022F5',
1147 "isins;": '\U000022F4',
1148 "isinsv;": '\U000022F3',
1149 "isinv;": '\U00002208',
1150 "it;": '\U00002062',
1151 "itilde;": '\U00000129',
1152 "iukcy;": '\U00000456',
1153 "iuml;": '\U000000EF',
1154 "jcirc;": '\U00000135',
1155 "jcy;": '\U00000439',
1156 "jfr;": '\U0001D527',
1157 "jmath;": '\U00000237',
1158 "jopf;": '\U0001D55B',
1159 "jscr;": '\U0001D4BF',
1160 "jsercy;": '\U00000458',
1161 "jukcy;": '\U00000454',
1162 "kappa;": '\U000003BA',
1163 "kappav;": '\U000003F0',
1164 "kcedil;": '\U00000137',
1165 "kcy;": '\U0000043A',
1166 "kfr;": '\U0001D528',
1167 "kgreen;": '\U00000138',
1168 "khcy;": '\U00000445',
1169 "kjcy;": '\U0000045C',
1170 "kopf;": '\U0001D55C',
1171 "kscr;": '\U0001D4C0',
1172 "lAarr;": '\U000021DA',
1173 "lArr;": '\U000021D0',
1174 "lAtail;": '\U0000291B',
1175 "lBarr;": '\U0000290E',
1176 "lE;": '\U00002266',
1177 "lEg;": '\U00002A8B',
1178 "lHar;": '\U00002962',
1179 "lacute;": '\U0000013A',
1180 "laemptyv;": '\U000029B4',
1181 "lagran;": '\U00002112',
1182 "lambda;": '\U000003BB',
1183 "lang;": '\U000027E8',
1184 "langd;": '\U00002991',
1185 "langle;": '\U000027E8',
1186 "lap;": '\U00002A85',
1187 "laquo;": '\U000000AB',
1188 "larr;": '\U00002190',
1189 "larrb;": '\U000021E4',
1190 "larrbfs;": '\U0000291F',
1191 "larrfs;": '\U0000291D',
1192 "larrhk;": '\U000021A9',
1193 "larrlp;": '\U000021AB',
1194 "larrpl;": '\U00002939',
1195 "larrsim;": '\U00002973',
1196 "larrtl;": '\U000021A2',
1197 "lat;": '\U00002AAB',
1198 "latail;": '\U00002919',
1199 "late;": '\U00002AAD',
1200 "lbarr;": '\U0000290C',
1201 "lbbrk;": '\U00002772',
1202 "lbrace;": '\U0000007B',
1203 "lbrack;": '\U0000005B',
1204 "lbrke;": '\U0000298B',
1205 "lbrksld;": '\U0000298F',
1206 "lbrkslu;": '\U0000298D',
1207 "lcaron;": '\U0000013E',
1208 "lcedil;": '\U0000013C',
1209 "lceil;": '\U00002308',
1210 "lcub;": '\U0000007B',
1211 "lcy;": '\U0000043B',
1212 "ldca;": '\U00002936',
1213 "ldquo;": '\U0000201C',
1214 "ldquor;": '\U0000201E',
1215 "ldrdhar;": '\U00002967',
1216 "ldrushar;": '\U0000294B',
1217 "ldsh;": '\U000021B2',
1218 "le;": '\U00002264',
1219 "leftarrow;": '\U00002190',
1220 "leftarrowtail;": '\U000021A2',
1221 "leftharpoondown;": '\U000021BD',
1222 "leftharpoonup;": '\U000021BC',
1223 "leftleftarrows;": '\U000021C7',
1224 "leftrightarrow;": '\U00002194',
1225 "leftrightarrows;": '\U000021C6',
1226 "leftrightharpoons;": '\U000021CB',
1227 "leftrightsquigarrow;": '\U000021AD',
1228 "leftthreetimes;": '\U000022CB',
1229 "leg;": '\U000022DA',
1230 "leq;": '\U00002264',
1231 "leqq;": '\U00002266',
1232 "leqslant;": '\U00002A7D',
1233 "les;": '\U00002A7D',
1234 "lescc;": '\U00002AA8',
1235 "lesdot;": '\U00002A7F',
1236 "lesdoto;": '\U00002A81',
1237 "lesdotor;": '\U00002A83',
1238 "lesges;": '\U00002A93',
1239 "lessapprox;": '\U00002A85',
1240 "lessdot;": '\U000022D6',
1241 "lesseqgtr;": '\U000022DA',
1242 "lesseqqgtr;": '\U00002A8B',
1243 "lessgtr;": '\U00002276',
1244 "lesssim;": '\U00002272',
1245 "lfisht;": '\U0000297C',
1246 "lfloor;": '\U0000230A',
1247 "lfr;": '\U0001D529',
1248 "lg;": '\U00002276',
1249 "lgE;": '\U00002A91',
1250 "lhard;": '\U000021BD',
1251 "lharu;": '\U000021BC',
1252 "lharul;": '\U0000296A',
1253 "lhblk;": '\U00002584',
1254 "ljcy;": '\U00000459',
1255 "ll;": '\U0000226A',
1256 "llarr;": '\U000021C7',
1257 "llcorner;": '\U0000231E',
1258 "llhard;": '\U0000296B',
1259 "lltri;": '\U000025FA',
1260 "lmidot;": '\U00000140',
1261 "lmoust;": '\U000023B0',
1262 "lmoustache;": '\U000023B0',
1263 "lnE;": '\U00002268',
1264 "lnap;": '\U00002A89',
1265 "lnapprox;": '\U00002A89',
1266 "lne;": '\U00002A87',
1267 "lneq;": '\U00002A87',
1268 "lneqq;": '\U00002268',
1269 "lnsim;": '\U000022E6',
1270 "loang;": '\U000027EC',
1271 "loarr;": '\U000021FD',
1272 "lobrk;": '\U000027E6',
1273 "longleftarrow;": '\U000027F5',
1274 "longleftrightarrow;": '\U000027F7',
1275 "longmapsto;": '\U000027FC',
1276 "longrightarrow;": '\U000027F6',
1277 "looparrowleft;": '\U000021AB',
1278 "looparrowright;": '\U000021AC',
1279 "lopar;": '\U00002985',
1280 "lopf;": '\U0001D55D',
1281 "loplus;": '\U00002A2D',
1282 "lotimes;": '\U00002A34',
1283 "lowast;": '\U00002217',
1284 "lowbar;": '\U0000005F',
1285 "loz;": '\U000025CA',
1286 "lozenge;": '\U000025CA',
1287 "lozf;": '\U000029EB',
1288 "lpar;": '\U00000028',
1289 "lparlt;": '\U00002993',
1290 "lrarr;": '\U000021C6',
1291 "lrcorner;": '\U0000231F',
1292 "lrhar;": '\U000021CB',
1293 "lrhard;": '\U0000296D',
1294 "lrm;": '\U0000200E',
1295 "lrtri;": '\U000022BF',
1296 "lsaquo;": '\U00002039',
1297 "lscr;": '\U0001D4C1',
1298 "lsh;": '\U000021B0',
1299 "lsim;": '\U00002272',
1300 "lsime;": '\U00002A8D',
1301 "lsimg;": '\U00002A8F',
1302 "lsqb;": '\U0000005B',
1303 "lsquo;": '\U00002018',
1304 "lsquor;": '\U0000201A',
1305 "lstrok;": '\U00000142',
1306 "lt;": '\U0000003C',
1307 "ltcc;": '\U00002AA6',
1308 "ltcir;": '\U00002A79',
1309 "ltdot;": '\U000022D6',
1310 "lthree;": '\U000022CB',
1311 "ltimes;": '\U000022C9',
1312 "ltlarr;": '\U00002976',
1313 "ltquest;": '\U00002A7B',
1314 "ltrPar;": '\U00002996',
1315 "ltri;": '\U000025C3',
1316 "ltrie;": '\U000022B4',
1317 "ltrif;": '\U000025C2',
1318 "lurdshar;": '\U0000294A',
1319 "luruhar;": '\U00002966',
1320 "mDDot;": '\U0000223A',
1321 "macr;": '\U000000AF',
1322 "male;": '\U00002642',
1323 "malt;": '\U00002720',
1324 "maltese;": '\U00002720',
1325 "map;": '\U000021A6',
1326 "mapsto;": '\U000021A6',
1327 "mapstodown;": '\U000021A7',
1328 "mapstoleft;": '\U000021A4',
1329 "mapstoup;": '\U000021A5',
1330 "marker;": '\U000025AE',
1331 "mcomma;": '\U00002A29',
1332 "mcy;": '\U0000043C',
1333 "mdash;": '\U00002014',
1334 "measuredangle;": '\U00002221',
1335 "mfr;": '\U0001D52A',
1336 "mho;": '\U00002127',
1337 "micro;": '\U000000B5',
1338 "mid;": '\U00002223',
1339 "midast;": '\U0000002A',
1340 "midcir;": '\U00002AF0',
1341 "middot;": '\U000000B7',
1342 "minus;": '\U00002212',
1343 "minusb;": '\U0000229F',
1344 "minusd;": '\U00002238',
1345 "minusdu;": '\U00002A2A',
1346 "mlcp;": '\U00002ADB',
1347 "mldr;": '\U00002026',
1348 "mnplus;": '\U00002213',
1349 "models;": '\U000022A7',
1350 "mopf;": '\U0001D55E',
1351 "mp;": '\U00002213',
1352 "mscr;": '\U0001D4C2',
1353 "mstpos;": '\U0000223E',
1354 "mu;": '\U000003BC',
1355 "multimap;": '\U000022B8',
1356 "mumap;": '\U000022B8',
1357 "nLeftarrow;": '\U000021CD',
1358 "nLeftrightarrow;": '\U000021CE',
1359 "nRightarrow;": '\U000021CF',
1360 "nVDash;": '\U000022AF',
1361 "nVdash;": '\U000022AE',
1362 "nabla;": '\U00002207',
1363 "nacute;": '\U00000144',
1364 "nap;": '\U00002249',
1365 "napos;": '\U00000149',
1366 "napprox;": '\U00002249',
1367 "natur;": '\U0000266E',
1368 "natural;": '\U0000266E',
1369 "naturals;": '\U00002115',
1370 "nbsp;": '\U000000A0',
1371 "ncap;": '\U00002A43',
1372 "ncaron;": '\U00000148',
1373 "ncedil;": '\U00000146',
1374 "ncong;": '\U00002247',
1375 "ncup;": '\U00002A42',
1376 "ncy;": '\U0000043D',
1377 "ndash;": '\U00002013',
1378 "ne;": '\U00002260',
1379 "neArr;": '\U000021D7',
1380 "nearhk;": '\U00002924',
1381 "nearr;": '\U00002197',
1382 "nearrow;": '\U00002197',
1383 "nequiv;": '\U00002262',
1384 "nesear;": '\U00002928',
1385 "nexist;": '\U00002204',
1386 "nexists;": '\U00002204',
1387 "nfr;": '\U0001D52B',
1388 "nge;": '\U00002271',
1389 "ngeq;": '\U00002271',
1390 "ngsim;": '\U00002275',
1391 "ngt;": '\U0000226F',
1392 "ngtr;": '\U0000226F',
1393 "nhArr;": '\U000021CE',
1394 "nharr;": '\U000021AE',
1395 "nhpar;": '\U00002AF2',
1396 "ni;": '\U0000220B',
1397 "nis;": '\U000022FC',
1398 "nisd;": '\U000022FA',
1399 "niv;": '\U0000220B',
1400 "njcy;": '\U0000045A',
1401 "nlArr;": '\U000021CD',
1402 "nlarr;": '\U0000219A',
1403 "nldr;": '\U00002025',
1404 "nle;": '\U00002270',
1405 "nleftarrow;": '\U0000219A',
1406 "nleftrightarrow;": '\U000021AE',
1407 "nleq;": '\U00002270',
1408 "nless;": '\U0000226E',
1409 "nlsim;": '\U00002274',
1410 "nlt;": '\U0000226E',
1411 "nltri;": '\U000022EA',
1412 "nltrie;": '\U000022EC',
1413 "nmid;": '\U00002224',
1414 "nopf;": '\U0001D55F',
1415 "not;": '\U000000AC',
1416 "notin;": '\U00002209',
1417 "notinva;": '\U00002209',
1418 "notinvb;": '\U000022F7',
1419 "notinvc;": '\U000022F6',
1420 "notni;": '\U0000220C',
1421 "notniva;": '\U0000220C',
1422 "notnivb;": '\U000022FE',
1423 "notnivc;": '\U000022FD',
1424 "npar;": '\U00002226',
1425 "nparallel;": '\U00002226',
1426 "npolint;": '\U00002A14',
1427 "npr;": '\U00002280',
1428 "nprcue;": '\U000022E0',
1429 "nprec;": '\U00002280',
1430 "nrArr;": '\U000021CF',
1431 "nrarr;": '\U0000219B',
1432 "nrightarrow;": '\U0000219B',
1433 "nrtri;": '\U000022EB',
1434 "nrtrie;": '\U000022ED',
1435 "nsc;": '\U00002281',
1436 "nsccue;": '\U000022E1',
1437 "nscr;": '\U0001D4C3',
1438 "nshortmid;": '\U00002224',
1439 "nshortparallel;": '\U00002226',
1440 "nsim;": '\U00002241',
1441 "nsime;": '\U00002244',
1442 "nsimeq;": '\U00002244',
1443 "nsmid;": '\U00002224',
1444 "nspar;": '\U00002226',
1445 "nsqsube;": '\U000022E2',
1446 "nsqsupe;": '\U000022E3',
1447 "nsub;": '\U00002284',
1448 "nsube;": '\U00002288',
1449 "nsubseteq;": '\U00002288',
1450 "nsucc;": '\U00002281',
1451 "nsup;": '\U00002285',
1452 "nsupe;": '\U00002289',
1453 "nsupseteq;": '\U00002289',
1454 "ntgl;": '\U00002279',
1455 "ntilde;": '\U000000F1',
1456 "ntlg;": '\U00002278',
1457 "ntriangleleft;": '\U000022EA',
1458 "ntrianglelefteq;": '\U000022EC',
1459 "ntriangleright;": '\U000022EB',
1460 "ntrianglerighteq;": '\U000022ED',
1461 "nu;": '\U000003BD',
1462 "num;": '\U00000023',
1463 "numero;": '\U00002116',
1464 "numsp;": '\U00002007',
1465 "nvDash;": '\U000022AD',
1466 "nvHarr;": '\U00002904',
1467 "nvdash;": '\U000022AC',
1468 "nvinfin;": '\U000029DE',
1469 "nvlArr;": '\U00002902',
1470 "nvrArr;": '\U00002903',
1471 "nwArr;": '\U000021D6',
1472 "nwarhk;": '\U00002923',
1473 "nwarr;": '\U00002196',
1474 "nwarrow;": '\U00002196',
1475 "nwnear;": '\U00002927',
1476 "oS;": '\U000024C8',
1477 "oacute;": '\U000000F3',
1478 "oast;": '\U0000229B',
1479 "ocir;": '\U0000229A',
1480 "ocirc;": '\U000000F4',
1481 "ocy;": '\U0000043E',
1482 "odash;": '\U0000229D',
1483 "odblac;": '\U00000151',
1484 "odiv;": '\U00002A38',
1485 "odot;": '\U00002299',
1486 "odsold;": '\U000029BC',
1487 "oelig;": '\U00000153',
1488 "ofcir;": '\U000029BF',
1489 "ofr;": '\U0001D52C',
1490 "ogon;": '\U000002DB',
1491 "ograve;": '\U000000F2',
1492 "ogt;": '\U000029C1',
1493 "ohbar;": '\U000029B5',
1494 "ohm;": '\U000003A9',
1495 "oint;": '\U0000222E',
1496 "olarr;": '\U000021BA',
1497 "olcir;": '\U000029BE',
1498 "olcross;": '\U000029BB',
1499 "oline;": '\U0000203E',
1500 "olt;": '\U000029C0',
1501 "omacr;": '\U0000014D',
1502 "omega;": '\U000003C9',
1503 "omicron;": '\U000003BF',
1504 "omid;": '\U000029B6',
1505 "ominus;": '\U00002296',
1506 "oopf;": '\U0001D560',
1507 "opar;": '\U000029B7',
1508 "operp;": '\U000029B9',
1509 "oplus;": '\U00002295',
1510 "or;": '\U00002228',
1511 "orarr;": '\U000021BB',
1512 "ord;": '\U00002A5D',
1513 "order;": '\U00002134',
1514 "orderof;": '\U00002134',
1515 "ordf;": '\U000000AA',
1516 "ordm;": '\U000000BA',
1517 "origof;": '\U000022B6',
1518 "oror;": '\U00002A56',
1519 "orslope;": '\U00002A57',
1520 "orv;": '\U00002A5B',
1521 "oscr;": '\U00002134',
1522 "oslash;": '\U000000F8',
1523 "osol;": '\U00002298',
1524 "otilde;": '\U000000F5',
1525 "otimes;": '\U00002297',
1526 "otimesas;": '\U00002A36',
1527 "ouml;": '\U000000F6',
1528 "ovbar;": '\U0000233D',
1529 "par;": '\U00002225',
1530 "para;": '\U000000B6',
1531 "parallel;": '\U00002225',
1532 "parsim;": '\U00002AF3',
1533 "parsl;": '\U00002AFD',
1534 "part;": '\U00002202',
1535 "pcy;": '\U0000043F',
1536 "percnt;": '\U00000025',
1537 "period;": '\U0000002E',
1538 "permil;": '\U00002030',
1539 "perp;": '\U000022A5',
1540 "pertenk;": '\U00002031',
1541 "pfr;": '\U0001D52D',
1542 "phi;": '\U000003C6',
1543 "phiv;": '\U000003D5',
1544 "phmmat;": '\U00002133',
1545 "phone;": '\U0000260E',
1546 "pi;": '\U000003C0',
1547 "pitchfork;": '\U000022D4',
1548 "piv;": '\U000003D6',
1549 "planck;": '\U0000210F',
1550 "planckh;": '\U0000210E',
1551 "plankv;": '\U0000210F',
1552 "plus;": '\U0000002B',
1553 "plusacir;": '\U00002A23',
1554 "plusb;": '\U0000229E',
1555 "pluscir;": '\U00002A22',
1556 "plusdo;": '\U00002214',
1557 "plusdu;": '\U00002A25',
1558 "pluse;": '\U00002A72',
1559 "plusmn;": '\U000000B1',
1560 "plussim;": '\U00002A26',
1561 "plustwo;": '\U00002A27',
1562 "pm;": '\U000000B1',
1563 "pointint;": '\U00002A15',
1564 "popf;": '\U0001D561',
1565 "pound;": '\U000000A3',
1566 "pr;": '\U0000227A',
1567 "prE;": '\U00002AB3',
1568 "prap;": '\U00002AB7',
1569 "prcue;": '\U0000227C',
1570 "pre;": '\U00002AAF',
1571 "prec;": '\U0000227A',
1572 "precapprox;": '\U00002AB7',
1573 "preccurlyeq;": '\U0000227C',
1574 "preceq;": '\U00002AAF',
1575 "precnapprox;": '\U00002AB9',
1576 "precneqq;": '\U00002AB5',
1577 "precnsim;": '\U000022E8',
1578 "precsim;": '\U0000227E',
1579 "prime;": '\U00002032',
1580 "primes;": '\U00002119',
1581 "prnE;": '\U00002AB5',
1582 "prnap;": '\U00002AB9',
1583 "prnsim;": '\U000022E8',
1584 "prod;": '\U0000220F',
1585 "profalar;": '\U0000232E',
1586 "profline;": '\U00002312',
1587 "profsurf;": '\U00002313',
1588 "prop;": '\U0000221D',
1589 "propto;": '\U0000221D',
1590 "prsim;": '\U0000227E',
1591 "prurel;": '\U000022B0',
1592 "pscr;": '\U0001D4C5',
1593 "psi;": '\U000003C8',
1594 "puncsp;": '\U00002008',
1595 "qfr;": '\U0001D52E',
1596 "qint;": '\U00002A0C',
1597 "qopf;": '\U0001D562',
1598 "qprime;": '\U00002057',
1599 "qscr;": '\U0001D4C6',
1600 "quaternions;": '\U0000210D',
1601 "quatint;": '\U00002A16',
1602 "quest;": '\U0000003F',
1603 "questeq;": '\U0000225F',
1604 "quot;": '\U00000022',
1605 "rAarr;": '\U000021DB',
1606 "rArr;": '\U000021D2',
1607 "rAtail;": '\U0000291C',
1608 "rBarr;": '\U0000290F',
1609 "rHar;": '\U00002964',
1610 "racute;": '\U00000155',
1611 "radic;": '\U0000221A',
1612 "raemptyv;": '\U000029B3',
1613 "rang;": '\U000027E9',
1614 "rangd;": '\U00002992',
1615 "range;": '\U000029A5',
1616 "rangle;": '\U000027E9',
1617 "raquo;": '\U000000BB',
1618 "rarr;": '\U00002192',
1619 "rarrap;": '\U00002975',
1620 "rarrb;": '\U000021E5',
1621 "rarrbfs;": '\U00002920',
1622 "rarrc;": '\U00002933',
1623 "rarrfs;": '\U0000291E',
1624 "rarrhk;": '\U000021AA',
1625 "rarrlp;": '\U000021AC',
1626 "rarrpl;": '\U00002945',
1627 "rarrsim;": '\U00002974',
1628 "rarrtl;": '\U000021A3',
1629 "rarrw;": '\U0000219D',
1630 "ratail;": '\U0000291A',
1631 "ratio;": '\U00002236',
1632 "rationals;": '\U0000211A',
1633 "rbarr;": '\U0000290D',
1634 "rbbrk;": '\U00002773',
1635 "rbrace;": '\U0000007D',
1636 "rbrack;": '\U0000005D',
1637 "rbrke;": '\U0000298C',
1638 "rbrksld;": '\U0000298E',
1639 "rbrkslu;": '\U00002990',
1640 "rcaron;": '\U00000159',
1641 "rcedil;": '\U00000157',
1642 "rceil;": '\U00002309',
1643 "rcub;": '\U0000007D',
1644 "rcy;": '\U00000440',
1645 "rdca;": '\U00002937',
1646 "rdldhar;": '\U00002969',
1647 "rdquo;": '\U0000201D',
1648 "rdquor;": '\U0000201D',
1649 "rdsh;": '\U000021B3',
1650 "real;": '\U0000211C',
1651 "realine;": '\U0000211B',
1652 "realpart;": '\U0000211C',
1653 "reals;": '\U0000211D',
1654 "rect;": '\U000025AD',
1655 "reg;": '\U000000AE',
1656 "rfisht;": '\U0000297D',
1657 "rfloor;": '\U0000230B',
1658 "rfr;": '\U0001D52F',
1659 "rhard;": '\U000021C1',
1660 "rharu;": '\U000021C0',
1661 "rharul;": '\U0000296C',
1662 "rho;": '\U000003C1',
1663 "rhov;": '\U000003F1',
1664 "rightarrow;": '\U00002192',
1665 "rightarrowtail;": '\U000021A3',
1666 "rightharpoondown;": '\U000021C1',
1667 "rightharpoonup;": '\U000021C0',
1668 "rightleftarrows;": '\U000021C4',
1669 "rightleftharpoons;": '\U000021CC',
1670 "rightrightarrows;": '\U000021C9',
1671 "rightsquigarrow;": '\U0000219D',
1672 "rightthreetimes;": '\U000022CC',
1673 "ring;": '\U000002DA',
1674 "risingdotseq;": '\U00002253',
1675 "rlarr;": '\U000021C4',
1676 "rlhar;": '\U000021CC',
1677 "rlm;": '\U0000200F',
1678 "rmoust;": '\U000023B1',
1679 "rmoustache;": '\U000023B1',
1680 "rnmid;": '\U00002AEE',
1681 "roang;": '\U000027ED',
1682 "roarr;": '\U000021FE',
1683 "robrk;": '\U000027E7',
1684 "ropar;": '\U00002986',
1685 "ropf;": '\U0001D563',
1686 "roplus;": '\U00002A2E',
1687 "rotimes;": '\U00002A35',
1688 "rpar;": '\U00000029',
1689 "rpargt;": '\U00002994',
1690 "rppolint;": '\U00002A12',
1691 "rrarr;": '\U000021C9',
1692 "rsaquo;": '\U0000203A',
1693 "rscr;": '\U0001D4C7',
1694 "rsh;": '\U000021B1',
1695 "rsqb;": '\U0000005D',
1696 "rsquo;": '\U00002019',
1697 "rsquor;": '\U00002019',
1698 "rthree;": '\U000022CC',
1699 "rtimes;": '\U000022CA',
1700 "rtri;": '\U000025B9',
1701 "rtrie;": '\U000022B5',
1702 "rtrif;": '\U000025B8',
1703 "rtriltri;": '\U000029CE',
1704 "ruluhar;": '\U00002968',
1705 "rx;": '\U0000211E',
1706 "sacute;": '\U0000015B',
1707 "sbquo;": '\U0000201A',
1708 "sc;": '\U0000227B',
1709 "scE;": '\U00002AB4',
1710 "scap;": '\U00002AB8',
1711 "scaron;": '\U00000161',
1712 "sccue;": '\U0000227D',
1713 "sce;": '\U00002AB0',
1714 "scedil;": '\U0000015F',
1715 "scirc;": '\U0000015D',
1716 "scnE;": '\U00002AB6',
1717 "scnap;": '\U00002ABA',
1718 "scnsim;": '\U000022E9',
1719 "scpolint;": '\U00002A13',
1720 "scsim;": '\U0000227F',
1721 "scy;": '\U00000441',
1722 "sdot;": '\U000022C5',
1723 "sdotb;": '\U000022A1',
1724 "sdote;": '\U00002A66',
1725 "seArr;": '\U000021D8',
1726 "searhk;": '\U00002925',
1727 "searr;": '\U00002198',
1728 "searrow;": '\U00002198',
1729 "sect;": '\U000000A7',
1730 "semi;": '\U0000003B',
1731 "seswar;": '\U00002929',
1732 "setminus;": '\U00002216',
1733 "setmn;": '\U00002216',
1734 "sext;": '\U00002736',
1735 "sfr;": '\U0001D530',
1736 "sfrown;": '\U00002322',
1737 "sharp;": '\U0000266F',
1738 "shchcy;": '\U00000449',
1739 "shcy;": '\U00000448',
1740 "shortmid;": '\U00002223',
1741 "shortparallel;": '\U00002225',
1742 "shy;": '\U000000AD',
1743 "sigma;": '\U000003C3',
1744 "sigmaf;": '\U000003C2',
1745 "sigmav;": '\U000003C2',
1746 "sim;": '\U0000223C',
1747 "simdot;": '\U00002A6A',
1748 "sime;": '\U00002243',
1749 "simeq;": '\U00002243',
1750 "simg;": '\U00002A9E',
1751 "simgE;": '\U00002AA0',
1752 "siml;": '\U00002A9D',
1753 "simlE;": '\U00002A9F',
1754 "simne;": '\U00002246',
1755 "simplus;": '\U00002A24',
1756 "simrarr;": '\U00002972',
1757 "slarr;": '\U00002190',
1758 "smallsetminus;": '\U00002216',
1759 "smashp;": '\U00002A33',
1760 "smeparsl;": '\U000029E4',
1761 "smid;": '\U00002223',
1762 "smile;": '\U00002323',
1763 "smt;": '\U00002AAA',
1764 "smte;": '\U00002AAC',
1765 "softcy;": '\U0000044C',
1766 "sol;": '\U0000002F',
1767 "solb;": '\U000029C4',
1768 "solbar;": '\U0000233F',
1769 "sopf;": '\U0001D564',
1770 "spades;": '\U00002660',
1771 "spadesuit;": '\U00002660',
1772 "spar;": '\U00002225',
1773 "sqcap;": '\U00002293',
1774 "sqcup;": '\U00002294',
1775 "sqsub;": '\U0000228F',
1776 "sqsube;": '\U00002291',
1777 "sqsubset;": '\U0000228F',
1778 "sqsubseteq;": '\U00002291',
1779 "sqsup;": '\U00002290',
1780 "sqsupe;": '\U00002292',
1781 "sqsupset;": '\U00002290',
1782 "sqsupseteq;": '\U00002292',
1783 "squ;": '\U000025A1',
1784 "square;": '\U000025A1',
1785 "squarf;": '\U000025AA',
1786 "squf;": '\U000025AA',
1787 "srarr;": '\U00002192',
1788 "sscr;": '\U0001D4C8',
1789 "ssetmn;": '\U00002216',
1790 "ssmile;": '\U00002323',
1791 "sstarf;": '\U000022C6',
1792 "star;": '\U00002606',
1793 "starf;": '\U00002605',
1794 "straightepsilon;": '\U000003F5',
1795 "straightphi;": '\U000003D5',
1796 "strns;": '\U000000AF',
1797 "sub;": '\U00002282',
1798 "subE;": '\U00002AC5',
1799 "subdot;": '\U00002ABD',
1800 "sube;": '\U00002286',
1801 "subedot;": '\U00002AC3',
1802 "submult;": '\U00002AC1',
1803 "subnE;": '\U00002ACB',
1804 "subne;": '\U0000228A',
1805 "subplus;": '\U00002ABF',
1806 "subrarr;": '\U00002979',
1807 "subset;": '\U00002282',
1808 "subseteq;": '\U00002286',
1809 "subseteqq;": '\U00002AC5',
1810 "subsetneq;": '\U0000228A',
1811 "subsetneqq;": '\U00002ACB',
1812 "subsim;": '\U00002AC7',
1813 "subsub;": '\U00002AD5',
1814 "subsup;": '\U00002AD3',
1815 "succ;": '\U0000227B',
1816 "succapprox;": '\U00002AB8',
1817 "succcurlyeq;": '\U0000227D',
1818 "succeq;": '\U00002AB0',
1819 "succnapprox;": '\U00002ABA',
1820 "succneqq;": '\U00002AB6',
1821 "succnsim;": '\U000022E9',
1822 "succsim;": '\U0000227F',
1823 "sum;": '\U00002211',
1824 "sung;": '\U0000266A',
1825 "sup;": '\U00002283',
1826 "sup1;": '\U000000B9',
1827 "sup2;": '\U000000B2',
1828 "sup3;": '\U000000B3',
1829 "supE;": '\U00002AC6',
1830 "supdot;": '\U00002ABE',
1831 "supdsub;": '\U00002AD8',
1832 "supe;": '\U00002287',
1833 "supedot;": '\U00002AC4',
1834 "suphsol;": '\U000027C9',
1835 "suphsub;": '\U00002AD7',
1836 "suplarr;": '\U0000297B',
1837 "supmult;": '\U00002AC2',
1838 "supnE;": '\U00002ACC',
1839 "supne;": '\U0000228B',
1840 "supplus;": '\U00002AC0',
1841 "supset;": '\U00002283',
1842 "supseteq;": '\U00002287',
1843 "supseteqq;": '\U00002AC6',
1844 "supsetneq;": '\U0000228B',
1845 "supsetneqq;": '\U00002ACC',
1846 "supsim;": '\U00002AC8',
1847 "supsub;": '\U00002AD4',
1848 "supsup;": '\U00002AD6',
1849 "swArr;": '\U000021D9',
1850 "swarhk;": '\U00002926',
1851 "swarr;": '\U00002199',
1852 "swarrow;": '\U00002199',
1853 "swnwar;": '\U0000292A',
1854 "szlig;": '\U000000DF',
1855 "target;": '\U00002316',
1856 "tau;": '\U000003C4',
1857 "tbrk;": '\U000023B4',
1858 "tcaron;": '\U00000165',
1859 "tcedil;": '\U00000163',
1860 "tcy;": '\U00000442',
1861 "tdot;": '\U000020DB',
1862 "telrec;": '\U00002315',
1863 "tfr;": '\U0001D531',
1864 "there4;": '\U00002234',
1865 "therefore;": '\U00002234',
1866 "theta;": '\U000003B8',
1867 "thetasym;": '\U000003D1',
1868 "thetav;": '\U000003D1',
1869 "thickapprox;": '\U00002248',
1870 "thicksim;": '\U0000223C',
1871 "thinsp;": '\U00002009',
1872 "thkap;": '\U00002248',
1873 "thksim;": '\U0000223C',
1874 "thorn;": '\U000000FE',
1875 "tilde;": '\U000002DC',
1876 "times;": '\U000000D7',
1877 "timesb;": '\U000022A0',
1878 "timesbar;": '\U00002A31',
1879 "timesd;": '\U00002A30',
1880 "tint;": '\U0000222D',
1881 "toea;": '\U00002928',
1882 "top;": '\U000022A4',
1883 "topbot;": '\U00002336',
1884 "topcir;": '\U00002AF1',
1885 "topf;": '\U0001D565',
1886 "topfork;": '\U00002ADA',
1887 "tosa;": '\U00002929',
1888 "tprime;": '\U00002034',
1889 "trade;": '\U00002122',
1890 "triangle;": '\U000025B5',
1891 "triangledown;": '\U000025BF',
1892 "triangleleft;": '\U000025C3',
1893 "trianglelefteq;": '\U000022B4',
1894 "triangleq;": '\U0000225C',
1895 "triangleright;": '\U000025B9',
1896 "trianglerighteq;": '\U000022B5',
1897 "tridot;": '\U000025EC',
1898 "trie;": '\U0000225C',
1899 "triminus;": '\U00002A3A',
1900 "triplus;": '\U00002A39',
1901 "trisb;": '\U000029CD',
1902 "tritime;": '\U00002A3B',
1903 "trpezium;": '\U000023E2',
1904 "tscr;": '\U0001D4C9',
1905 "tscy;": '\U00000446',
1906 "tshcy;": '\U0000045B',
1907 "tstrok;": '\U00000167',
1908 "twixt;": '\U0000226C',
1909 "twoheadleftarrow;": '\U0000219E',
1910 "twoheadrightarrow;": '\U000021A0',
1911 "uArr;": '\U000021D1',
1912 "uHar;": '\U00002963',
1913 "uacute;": '\U000000FA',
1914 "uarr;": '\U00002191',
1915 "ubrcy;": '\U0000045E',
1916 "ubreve;": '\U0000016D',
1917 "ucirc;": '\U000000FB',
1918 "ucy;": '\U00000443',
1919 "udarr;": '\U000021C5',
1920 "udblac;": '\U00000171',
1921 "udhar;": '\U0000296E',
1922 "ufisht;": '\U0000297E',
1923 "ufr;": '\U0001D532',
1924 "ugrave;": '\U000000F9',
1925 "uharl;": '\U000021BF',
1926 "uharr;": '\U000021BE',
1927 "uhblk;": '\U00002580',
1928 "ulcorn;": '\U0000231C',
1929 "ulcorner;": '\U0000231C',
1930 "ulcrop;": '\U0000230F',
1931 "ultri;": '\U000025F8',
1932 "umacr;": '\U0000016B',
1933 "uml;": '\U000000A8',
1934 "uogon;": '\U00000173',
1935 "uopf;": '\U0001D566',
1936 "uparrow;": '\U00002191',
1937 "updownarrow;": '\U00002195',
1938 "upharpoonleft;": '\U000021BF',
1939 "upharpoonright;": '\U000021BE',
1940 "uplus;": '\U0000228E',
1941 "upsi;": '\U000003C5',
1942 "upsih;": '\U000003D2',
1943 "upsilon;": '\U000003C5',
1944 "upuparrows;": '\U000021C8',
1945 "urcorn;": '\U0000231D',
1946 "urcorner;": '\U0000231D',
1947 "urcrop;": '\U0000230E',
1948 "uring;": '\U0000016F',
1949 "urtri;": '\U000025F9',
1950 "uscr;": '\U0001D4CA',
1951 "utdot;": '\U000022F0',
1952 "utilde;": '\U00000169',
1953 "utri;": '\U000025B5',
1954 "utrif;": '\U000025B4',
1955 "uuarr;": '\U000021C8',
1956 "uuml;": '\U000000FC',
1957 "uwangle;": '\U000029A7',
1958 "vArr;": '\U000021D5',
1959 "vBar;": '\U00002AE8',
1960 "vBarv;": '\U00002AE9',
1961 "vDash;": '\U000022A8',
1962 "vangrt;": '\U0000299C',
1963 "varepsilon;": '\U000003F5',
1964 "varkappa;": '\U000003F0',
1965 "varnothing;": '\U00002205',
1966 "varphi;": '\U000003D5',
1967 "varpi;": '\U000003D6',
1968 "varpropto;": '\U0000221D',
1969 "varr;": '\U00002195',
1970 "varrho;": '\U000003F1',
1971 "varsigma;": '\U000003C2',
1972 "vartheta;": '\U000003D1',
1973 "vartriangleleft;": '\U000022B2',
1974 "vartriangleright;": '\U000022B3',
1975 "vcy;": '\U00000432',
1976 "vdash;": '\U000022A2',
1977 "vee;": '\U00002228',
1978 "veebar;": '\U000022BB',
1979 "veeeq;": '\U0000225A',
1980 "vellip;": '\U000022EE',
1981 "verbar;": '\U0000007C',
1982 "vert;": '\U0000007C',
1983 "vfr;": '\U0001D533',
1984 "vltri;": '\U000022B2',
1985 "vopf;": '\U0001D567',
1986 "vprop;": '\U0000221D',
1987 "vrtri;": '\U000022B3',
1988 "vscr;": '\U0001D4CB',
1989 "vzigzag;": '\U0000299A',
1990 "wcirc;": '\U00000175',
1991 "wedbar;": '\U00002A5F',
1992 "wedge;": '\U00002227',
1993 "wedgeq;": '\U00002259',
1994 "weierp;": '\U00002118',
1995 "wfr;": '\U0001D534',
1996 "wopf;": '\U0001D568',
1997 "wp;": '\U00002118',
1998 "wr;": '\U00002240',
1999 "wreath;": '\U00002240',
2000 "wscr;": '\U0001D4CC',
2001 "xcap;": '\U000022C2',
2002 "xcirc;": '\U000025EF',
2003 "xcup;": '\U000022C3',
2004 "xdtri;": '\U000025BD',
2005 "xfr;": '\U0001D535',
2006 "xhArr;": '\U000027FA',
2007 "xharr;": '\U000027F7',
2008 "xi;": '\U000003BE',
2009 "xlArr;": '\U000027F8',
2010 "xlarr;": '\U000027F5',
2011 "xmap;": '\U000027FC',
2012 "xnis;": '\U000022FB',
2013 "xodot;": '\U00002A00',
2014 "xopf;": '\U0001D569',
2015 "xoplus;": '\U00002A01',
2016 "xotime;": '\U00002A02',
2017 "xrArr;": '\U000027F9',
2018 "xrarr;": '\U000027F6',
2019 "xscr;": '\U0001D4CD',
2020 "xsqcup;": '\U00002A06',
2021 "xuplus;": '\U00002A04',
2022 "xutri;": '\U000025B3',
2023 "xvee;": '\U000022C1',
2024 "xwedge;": '\U000022C0',
2025 "yacute;": '\U000000FD',
2026 "yacy;": '\U0000044F',
2027 "ycirc;": '\U00000177',
2028 "ycy;": '\U0000044B',
2029 "yen;": '\U000000A5',
2030 "yfr;": '\U0001D536',
2031 "yicy;": '\U00000457',
2032 "yopf;": '\U0001D56A',
2033 "yscr;": '\U0001D4CE',
2034 "yucy;": '\U0000044E',
2035 "yuml;": '\U000000FF',
2036 "zacute;": '\U0000017A',
2037 "zcaron;": '\U0000017E',
2038 "zcy;": '\U00000437',
2039 "zdot;": '\U0000017C',
2040 "zeetrf;": '\U00002128',
2041 "zeta;": '\U000003B6',
2042 "zfr;": '\U0001D537',
2043 "zhcy;": '\U00000436',
2044 "zigrarr;": '\U000021DD',
2045 "zopf;": '\U0001D56B',
2046 "zscr;": '\U0001D4CF',
2047 "zwj;": '\U0000200D',
2048 "zwnj;": '\U0000200C',
2049 "AElig": '\U000000C6',
2050 "AMP": '\U00000026',
2051 "Aacute": '\U000000C1',
2052 "Acirc": '\U000000C2',
2053 "Agrave": '\U000000C0',
2054 "Aring": '\U000000C5',
2055 "Atilde": '\U000000C3',
2056 "Auml": '\U000000C4',
2057 "COPY": '\U000000A9',
2058 "Ccedil": '\U000000C7',
2059 "ETH": '\U000000D0',
2060 "Eacute": '\U000000C9',
2061 "Ecirc": '\U000000CA',
2062 "Egrave": '\U000000C8',
2063 "Euml": '\U000000CB',
2064 "GT": '\U0000003E',
2065 "Iacute": '\U000000CD',
2066 "Icirc": '\U000000CE',
2067 "Igrave": '\U000000CC',
2068 "Iuml": '\U000000CF',
2069 "LT": '\U0000003C',
2070 "Ntilde": '\U000000D1',
2071 "Oacute": '\U000000D3',
2072 "Ocirc": '\U000000D4',
2073 "Ograve": '\U000000D2',
2074 "Oslash": '\U000000D8',
2075 "Otilde": '\U000000D5',
2076 "Ouml": '\U000000D6',
2077 "QUOT": '\U00000022',
2078 "REG": '\U000000AE',
2079 "THORN": '\U000000DE',
2080 "Uacute": '\U000000DA',
2081 "Ucirc": '\U000000DB',
2082 "Ugrave": '\U000000D9',
2083 "Uuml": '\U000000DC',
2084 "Yacute": '\U000000DD',
2085 "aacute": '\U000000E1',
2086 "acirc": '\U000000E2',
2087 "acute": '\U000000B4',
2088 "aelig": '\U000000E6',
2089 "agrave": '\U000000E0',
2090 "amp": '\U00000026',
2091 "aring": '\U000000E5',
2092 "atilde": '\U000000E3',
2093 "auml": '\U000000E4',
2094 "brvbar": '\U000000A6',
2095 "ccedil": '\U000000E7',
2096 "cedil": '\U000000B8',
2097 "cent": '\U000000A2',
2098 "copy": '\U000000A9',
2099 "curren": '\U000000A4',
2100 "deg": '\U000000B0',
2101 "divide": '\U000000F7',
2102 "eacute": '\U000000E9',
2103 "ecirc": '\U000000EA',
2104 "egrave": '\U000000E8',
2105 "eth": '\U000000F0',
2106 "euml": '\U000000EB',
2107 "frac12": '\U000000BD',
2108 "frac14": '\U000000BC',
2109 "frac34": '\U000000BE',
2110 "gt": '\U0000003E',
2111 "iacute": '\U000000ED',
2112 "icirc": '\U000000EE',
2113 "iexcl": '\U000000A1',
2114 "igrave": '\U000000EC',
2115 "iquest": '\U000000BF',
2116 "iuml": '\U000000EF',
2117 "laquo": '\U000000AB',
2118 "lt": '\U0000003C',
2119 "macr": '\U000000AF',
2120 "micro": '\U000000B5',
2121 "middot": '\U000000B7',
2122 "nbsp": '\U000000A0',
2123 "not": '\U000000AC',
2124 "ntilde": '\U000000F1',
2125 "oacute": '\U000000F3',
2126 "ocirc": '\U000000F4',
2127 "ograve": '\U000000F2',
2128 "ordf": '\U000000AA',
2129 "ordm": '\U000000BA',
2130 "oslash": '\U000000F8',
2131 "otilde": '\U000000F5',
2132 "ouml": '\U000000F6',
2133 "para": '\U000000B6',
2134 "plusmn": '\U000000B1',
2135 "pound": '\U000000A3',
2136 "quot": '\U00000022',
2137 "raquo": '\U000000BB',
2138 "reg": '\U000000AE',
2139 "sect": '\U000000A7',
2140 "shy": '\U000000AD',
2141 "sup1": '\U000000B9',
2142 "sup2": '\U000000B2',
2143 "sup3": '\U000000B3',
2144 "szlig": '\U000000DF',
2145 "thorn": '\U000000FE',
2146 "times": '\U000000D7',
2147 "uacute": '\U000000FA',
2148 "ucirc": '\U000000FB',
2149 "ugrave": '\U000000F9',
2150 "uml": '\U000000A8',
2151 "uuml": '\U000000FC',
2152 "yacute": '\U000000FD',
2153 "yen": '\U000000A5',
2154 "yuml": '\U000000FF',
2155}
2156
2157// HTML entities that are two unicode codepoints.
2158var entity2 = map[string][2]rune{
2159 // TODO(nigeltao): Handle replacements that are wider than their names.
2160 // "nLt;": {'\u226A', '\u20D2'},
2161 // "nGt;": {'\u226B', '\u20D2'},
2162 "NotEqualTilde;": {'\u2242', '\u0338'},
2163 "NotGreaterFullEqual;": {'\u2267', '\u0338'},
2164 "NotGreaterGreater;": {'\u226B', '\u0338'},
2165 "NotGreaterSlantEqual;": {'\u2A7E', '\u0338'},
2166 "NotHumpDownHump;": {'\u224E', '\u0338'},
2167 "NotHumpEqual;": {'\u224F', '\u0338'},
2168 "NotLeftTriangleBar;": {'\u29CF', '\u0338'},
2169 "NotLessLess;": {'\u226A', '\u0338'},
2170 "NotLessSlantEqual;": {'\u2A7D', '\u0338'},
2171 "NotNestedGreaterGreater;": {'\u2AA2', '\u0338'},
2172 "NotNestedLessLess;": {'\u2AA1', '\u0338'},
2173 "NotPrecedesEqual;": {'\u2AAF', '\u0338'},
2174 "NotRightTriangleBar;": {'\u29D0', '\u0338'},
2175 "NotSquareSubset;": {'\u228F', '\u0338'},
2176 "NotSquareSuperset;": {'\u2290', '\u0338'},
2177 "NotSubset;": {'\u2282', '\u20D2'},
2178 "NotSucceedsEqual;": {'\u2AB0', '\u0338'},
2179 "NotSucceedsTilde;": {'\u227F', '\u0338'},
2180 "NotSuperset;": {'\u2283', '\u20D2'},
2181 "ThickSpace;": {'\u205F', '\u200A'},
2182 "acE;": {'\u223E', '\u0333'},
2183 "bne;": {'\u003D', '\u20E5'},
2184 "bnequiv;": {'\u2261', '\u20E5'},
2185 "caps;": {'\u2229', '\uFE00'},
2186 "cups;": {'\u222A', '\uFE00'},
2187 "fjlig;": {'\u0066', '\u006A'},
2188 "gesl;": {'\u22DB', '\uFE00'},
2189 "gvertneqq;": {'\u2269', '\uFE00'},
2190 "gvnE;": {'\u2269', '\uFE00'},
2191 "lates;": {'\u2AAD', '\uFE00'},
2192 "lesg;": {'\u22DA', '\uFE00'},
2193 "lvertneqq;": {'\u2268', '\uFE00'},
2194 "lvnE;": {'\u2268', '\uFE00'},
2195 "nGg;": {'\u22D9', '\u0338'},
2196 "nGtv;": {'\u226B', '\u0338'},
2197 "nLl;": {'\u22D8', '\u0338'},
2198 "nLtv;": {'\u226A', '\u0338'},
2199 "nang;": {'\u2220', '\u20D2'},
2200 "napE;": {'\u2A70', '\u0338'},
2201 "napid;": {'\u224B', '\u0338'},
2202 "nbump;": {'\u224E', '\u0338'},
2203 "nbumpe;": {'\u224F', '\u0338'},
2204 "ncongdot;": {'\u2A6D', '\u0338'},
2205 "nedot;": {'\u2250', '\u0338'},
2206 "nesim;": {'\u2242', '\u0338'},
2207 "ngE;": {'\u2267', '\u0338'},
2208 "ngeqq;": {'\u2267', '\u0338'},
2209 "ngeqslant;": {'\u2A7E', '\u0338'},
2210 "nges;": {'\u2A7E', '\u0338'},
2211 "nlE;": {'\u2266', '\u0338'},
2212 "nleqq;": {'\u2266', '\u0338'},
2213 "nleqslant;": {'\u2A7D', '\u0338'},
2214 "nles;": {'\u2A7D', '\u0338'},
2215 "notinE;": {'\u22F9', '\u0338'},
2216 "notindot;": {'\u22F5', '\u0338'},
2217 "nparsl;": {'\u2AFD', '\u20E5'},
2218 "npart;": {'\u2202', '\u0338'},
2219 "npre;": {'\u2AAF', '\u0338'},
2220 "npreceq;": {'\u2AAF', '\u0338'},
2221 "nrarrc;": {'\u2933', '\u0338'},
2222 "nrarrw;": {'\u219D', '\u0338'},
2223 "nsce;": {'\u2AB0', '\u0338'},
2224 "nsubE;": {'\u2AC5', '\u0338'},
2225 "nsubset;": {'\u2282', '\u20D2'},
2226 "nsubseteqq;": {'\u2AC5', '\u0338'},
2227 "nsucceq;": {'\u2AB0', '\u0338'},
2228 "nsupE;": {'\u2AC6', '\u0338'},
2229 "nsupset;": {'\u2283', '\u20D2'},
2230 "nsupseteqq;": {'\u2AC6', '\u0338'},
2231 "nvap;": {'\u224D', '\u20D2'},
2232 "nvge;": {'\u2265', '\u20D2'},
2233 "nvgt;": {'\u003E', '\u20D2'},
2234 "nvle;": {'\u2264', '\u20D2'},
2235 "nvlt;": {'\u003C', '\u20D2'},
2236 "nvltrie;": {'\u22B4', '\u20D2'},
2237 "nvrtrie;": {'\u22B5', '\u20D2'},
2238 "nvsim;": {'\u223C', '\u20D2'},
2239 "race;": {'\u223D', '\u0331'},
2240 "smtes;": {'\u2AAC', '\uFE00'},
2241 "sqcaps;": {'\u2293', '\uFE00'},
2242 "sqcups;": {'\u2294', '\uFE00'},
2243 "varsubsetneq;": {'\u228A', '\uFE00'},
2244 "varsubsetneqq;": {'\u2ACB', '\uFE00'},
2245 "varsupsetneq;": {'\u228B', '\uFE00'},
2246 "varsupsetneqq;": {'\u2ACC', '\uFE00'},
2247 "vnsub;": {'\u2282', '\u20D2'},
2248 "vnsup;": {'\u2283', '\u20D2'},
2249 "vsubnE;": {'\u2ACB', '\uFE00'},
2250 "vsubne;": {'\u228A', '\uFE00'},
2251 "vsupnE;": {'\u2ACC', '\uFE00'},
2252 "vsupne;": {'\u228B', '\uFE00'},
2253}
diff --git a/vendor/golang.org/x/net/html/escape.go b/vendor/golang.org/x/net/html/escape.go
new file mode 100644
index 0000000..d856139
--- /dev/null
+++ b/vendor/golang.org/x/net/html/escape.go
@@ -0,0 +1,258 @@
1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package html
6
7import (
8 "bytes"
9 "strings"
10 "unicode/utf8"
11)
12
13// These replacements permit compatibility with old numeric entities that
14// assumed Windows-1252 encoding.
15// https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
16var replacementTable = [...]rune{
17 '\u20AC', // First entry is what 0x80 should be replaced with.
18 '\u0081',
19 '\u201A',
20 '\u0192',
21 '\u201E',
22 '\u2026',
23 '\u2020',
24 '\u2021',
25 '\u02C6',
26 '\u2030',
27 '\u0160',
28 '\u2039',
29 '\u0152',
30 '\u008D',
31 '\u017D',
32 '\u008F',
33 '\u0090',
34 '\u2018',
35 '\u2019',
36 '\u201C',
37 '\u201D',
38 '\u2022',
39 '\u2013',
40 '\u2014',
41 '\u02DC',
42 '\u2122',
43 '\u0161',
44 '\u203A',
45 '\u0153',
46 '\u009D',
47 '\u017E',
48 '\u0178', // Last entry is 0x9F.
49 // 0x00->'\uFFFD' is handled programmatically.
50 // 0x0D->'\u000D' is a no-op.
51}
52
53// unescapeEntity reads an entity like "&lt;" from b[src:] and writes the
54// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
55// Precondition: b[src] == '&' && dst <= src.
56// attribute should be true if parsing an attribute value.
57func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
58 // https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
59
60 // i starts at 1 because we already know that s[0] == '&'.
61 i, s := 1, b[src:]
62
63 if len(s) <= 1 {
64 b[dst] = b[src]
65 return dst + 1, src + 1
66 }
67
68 if s[i] == '#' {
69 if len(s) <= 3 { // We need to have at least "&#.".
70 b[dst] = b[src]
71 return dst + 1, src + 1
72 }
73 i++
74 c := s[i]
75 hex := false
76 if c == 'x' || c == 'X' {
77 hex = true
78 i++
79 }
80
81 x := '\x00'
82 for i < len(s) {
83 c = s[i]
84 i++
85 if hex {
86 if '0' <= c && c <= '9' {
87 x = 16*x + rune(c) - '0'
88 continue
89 } else if 'a' <= c && c <= 'f' {
90 x = 16*x + rune(c) - 'a' + 10
91 continue
92 } else if 'A' <= c && c <= 'F' {
93 x = 16*x + rune(c) - 'A' + 10
94 continue
95 }
96 } else if '0' <= c && c <= '9' {
97 x = 10*x + rune(c) - '0'
98 continue
99 }
100 if c != ';' {
101 i--
102 }
103 break
104 }
105
106 if i <= 3 { // No characters matched.
107 b[dst] = b[src]
108 return dst + 1, src + 1
109 }
110
111 if 0x80 <= x && x <= 0x9F {
112 // Replace characters from Windows-1252 with UTF-8 equivalents.
113 x = replacementTable[x-0x80]
114 } else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF {
115 // Replace invalid characters with the replacement character.
116 x = '\uFFFD'
117 }
118
119 return dst + utf8.EncodeRune(b[dst:], x), src + i
120 }
121
122 // Consume the maximum number of characters possible, with the
123 // consumed characters matching one of the named references.
124
125 for i < len(s) {
126 c := s[i]
127 i++
128 // Lower-cased characters are more common in entities, so we check for them first.
129 if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
130 continue
131 }
132 if c != ';' {
133 i--
134 }
135 break
136 }
137
138 entityName := string(s[1:i])
139 if entityName == "" {
140 // No-op.
141 } else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' {
142 // No-op.
143 } else if x := entity[entityName]; x != 0 {
144 return dst + utf8.EncodeRune(b[dst:], x), src + i
145 } else if x := entity2[entityName]; x[0] != 0 {
146 dst1 := dst + utf8.EncodeRune(b[dst:], x[0])
147 return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i
148 } else if !attribute {
149 maxLen := len(entityName) - 1
150 if maxLen > longestEntityWithoutSemicolon {
151 maxLen = longestEntityWithoutSemicolon
152 }
153 for j := maxLen; j > 1; j-- {
154 if x := entity[entityName[:j]]; x != 0 {
155 return dst + utf8.EncodeRune(b[dst:], x), src + j + 1
156 }
157 }
158 }
159
160 dst1, src1 = dst+i, src+i
161 copy(b[dst:dst1], b[src:src1])
162 return dst1, src1
163}
164
165// unescape unescapes b's entities in-place, so that "a&lt;b" becomes "a<b".
166// attribute should be true if parsing an attribute value.
167func unescape(b []byte, attribute bool) []byte {
168 for i, c := range b {
169 if c == '&' {
170 dst, src := unescapeEntity(b, i, i, attribute)
171 for src < len(b) {
172 c := b[src]
173 if c == '&' {
174 dst, src = unescapeEntity(b, dst, src, attribute)
175 } else {
176 b[dst] = c
177 dst, src = dst+1, src+1
178 }
179 }
180 return b[0:dst]
181 }
182 }
183 return b
184}
185
186// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
187func lower(b []byte) []byte {
188 for i, c := range b {
189 if 'A' <= c && c <= 'Z' {
190 b[i] = c + 'a' - 'A'
191 }
192 }
193 return b
194}
195
196const escapedChars = "&'<>\"\r"
197
198func escape(w writer, s string) error {
199 i := strings.IndexAny(s, escapedChars)
200 for i != -1 {
201 if _, err := w.WriteString(s[:i]); err != nil {
202 return err
203 }
204 var esc string
205 switch s[i] {
206 case '&':
207 esc = "&amp;"
208 case '\'':
209 // "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
210 esc = "&#39;"
211 case '<':
212 esc = "&lt;"
213 case '>':
214 esc = "&gt;"
215 case '"':
216 // "&#34;" is shorter than "&quot;".
217 esc = "&#34;"
218 case '\r':
219 esc = "&#13;"
220 default:
221 panic("unrecognized escape character")
222 }
223 s = s[i+1:]
224 if _, err := w.WriteString(esc); err != nil {
225 return err
226 }
227 i = strings.IndexAny(s, escapedChars)
228 }
229 _, err := w.WriteString(s)
230 return err
231}
232
233// EscapeString escapes special characters like "<" to become "&lt;". It
234// escapes only five such characters: <, >, &, ' and ".
235// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
236// always true.
237func EscapeString(s string) string {
238 if strings.IndexAny(s, escapedChars) == -1 {
239 return s
240 }
241 var buf bytes.Buffer
242 escape(&buf, s)
243 return buf.String()
244}
245
246// UnescapeString unescapes entities like "&lt;" to become "<". It unescapes a
247// larger range of entities than EscapeString escapes. For example, "&aacute;"
248// unescapes to "á", as does "&#225;" and "&xE1;".
249// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
250// always true.
251func UnescapeString(s string) string {
252 for _, c := range s {
253 if c == '&' {
254 return string(unescape([]byte(s), false))
255 }
256 }
257 return s
258}
diff --git a/vendor/golang.org/x/net/html/foreign.go b/vendor/golang.org/x/net/html/foreign.go
new file mode 100644
index 0000000..d3b3844
--- /dev/null
+++ b/vendor/golang.org/x/net/html/foreign.go
@@ -0,0 +1,226 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package html
6
7import (
8 "strings"
9)
10
11func adjustAttributeNames(aa []Attribute, nameMap map[string]string) {
12 for i := range aa {
13 if newName, ok := nameMap[aa[i].Key]; ok {
14 aa[i].Key = newName
15 }
16 }
17}
18
19func adjustForeignAttributes(aa []Attribute) {
20 for i, a := range aa {
21 if a.Key == "" || a.Key[0] != 'x' {
22 continue
23 }
24 switch a.Key {
25 case "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show",
26 "xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "xmlns:xlink":
27 j := strings.Index(a.Key, ":")
28 aa[i].Namespace = a.Key[:j]
29 aa[i].Key = a.Key[j+1:]
30 }
31 }
32}
33
34func htmlIntegrationPoint(n *Node) bool {
35 if n.Type != ElementNode {
36 return false
37 }
38 switch n.Namespace {
39 case "math":
40 if n.Data == "annotation-xml" {
41 for _, a := range n.Attr {
42 if a.Key == "encoding" {
43 val := strings.ToLower(a.Val)
44 if val == "text/html" || val == "application/xhtml+xml" {
45 return true
46 }
47 }
48 }
49 }
50 case "svg":
51 switch n.Data {
52 case "desc", "foreignObject", "title":
53 return true
54 }
55 }
56 return false
57}
58
59func mathMLTextIntegrationPoint(n *Node) bool {
60 if n.Namespace != "math" {
61 return false
62 }
63 switch n.Data {
64 case "mi", "mo", "mn", "ms", "mtext":
65 return true
66 }
67 return false
68}
69
70// Section 12.2.5.5.
71var breakout = map[string]bool{
72 "b": true,
73 "big": true,
74 "blockquote": true,
75 "body": true,
76 "br": true,
77 "center": true,
78 "code": true,
79 "dd": true,
80 "div": true,
81 "dl": true,
82 "dt": true,
83 "em": true,
84 "embed": true,
85 "h1": true,
86 "h2": true,
87 "h3": true,
88 "h4": true,
89 "h5": true,
90 "h6": true,
91 "head": true,
92 "hr": true,
93 "i": true,
94 "img": true,
95 "li": true,
96 "listing": true,
97 "menu": true,
98 "meta": true,
99 "nobr": true,
100 "ol": true,
101 "p": true,
102 "pre": true,
103 "ruby": true,
104 "s": true,
105 "small": true,
106 "span": true,
107 "strong": true,
108 "strike": true,
109 "sub": true,
110 "sup": true,
111 "table": true,
112 "tt": true,
113 "u": true,
114 "ul": true,
115 "var": true,
116}
117
118// Section 12.2.5.5.
119var svgTagNameAdjustments = map[string]string{
120 "altglyph": "altGlyph",
121 "altglyphdef": "altGlyphDef",
122 "altglyphitem": "altGlyphItem",
123 "animatecolor": "animateColor",
124 "animatemotion": "animateMotion",
125 "animatetransform": "animateTransform",
126 "clippath": "clipPath",
127 "feblend": "feBlend",
128 "fecolormatrix": "feColorMatrix",
129 "fecomponenttransfer": "feComponentTransfer",
130 "fecomposite": "feComposite",
131 "feconvolvematrix": "feConvolveMatrix",
132 "fediffuselighting": "feDiffuseLighting",
133 "fedisplacementmap": "feDisplacementMap",
134 "fedistantlight": "feDistantLight",
135 "feflood": "feFlood",
136 "fefunca": "feFuncA",
137 "fefuncb": "feFuncB",
138 "fefuncg": "feFuncG",
139 "fefuncr": "feFuncR",
140 "fegaussianblur": "feGaussianBlur",
141 "feimage": "feImage",
142 "femerge": "feMerge",
143 "femergenode": "feMergeNode",
144 "femorphology": "feMorphology",
145 "feoffset": "feOffset",
146 "fepointlight": "fePointLight",
147 "fespecularlighting": "feSpecularLighting",
148 "fespotlight": "feSpotLight",
149 "fetile": "feTile",
150 "feturbulence": "feTurbulence",
151 "foreignobject": "foreignObject",
152 "glyphref": "glyphRef",
153 "lineargradient": "linearGradient",
154 "radialgradient": "radialGradient",
155 "textpath": "textPath",
156}
157
158// Section 12.2.5.1
159var mathMLAttributeAdjustments = map[string]string{
160 "definitionurl": "definitionURL",
161}
162
163var svgAttributeAdjustments = map[string]string{
164 "attributename": "attributeName",
165 "attributetype": "attributeType",
166 "basefrequency": "baseFrequency",
167 "baseprofile": "baseProfile",
168 "calcmode": "calcMode",
169 "clippathunits": "clipPathUnits",
170 "contentscripttype": "contentScriptType",
171 "contentstyletype": "contentStyleType",
172 "diffuseconstant": "diffuseConstant",
173 "edgemode": "edgeMode",
174 "externalresourcesrequired": "externalResourcesRequired",
175 "filterres": "filterRes",
176 "filterunits": "filterUnits",
177 "glyphref": "glyphRef",
178 "gradienttransform": "gradientTransform",
179 "gradientunits": "gradientUnits",
180 "kernelmatrix": "kernelMatrix",
181 "kernelunitlength": "kernelUnitLength",
182 "keypoints": "keyPoints",
183 "keysplines": "keySplines",
184 "keytimes": "keyTimes",
185 "lengthadjust": "lengthAdjust",
186 "limitingconeangle": "limitingConeAngle",
187 "markerheight": "markerHeight",
188 "markerunits": "markerUnits",
189 "markerwidth": "markerWidth",
190 "maskcontentunits": "maskContentUnits",
191 "maskunits": "maskUnits",
192 "numoctaves": "numOctaves",
193 "pathlength": "pathLength",
194 "patterncontentunits": "patternContentUnits",
195 "patterntransform": "patternTransform",
196 "patternunits": "patternUnits",
197 "pointsatx": "pointsAtX",
198 "pointsaty": "pointsAtY",
199 "pointsatz": "pointsAtZ",
200 "preservealpha": "preserveAlpha",
201 "preserveaspectratio": "preserveAspectRatio",
202 "primitiveunits": "primitiveUnits",
203 "refx": "refX",
204 "refy": "refY",
205 "repeatcount": "repeatCount",
206 "repeatdur": "repeatDur",
207 "requiredextensions": "requiredExtensions",
208 "requiredfeatures": "requiredFeatures",
209 "specularconstant": "specularConstant",
210 "specularexponent": "specularExponent",
211 "spreadmethod": "spreadMethod",
212 "startoffset": "startOffset",
213 "stddeviation": "stdDeviation",
214 "stitchtiles": "stitchTiles",
215 "surfacescale": "surfaceScale",
216 "systemlanguage": "systemLanguage",
217 "tablevalues": "tableValues",
218 "targetx": "targetX",
219 "targety": "targetY",
220 "textlength": "textLength",
221 "viewbox": "viewBox",
222 "viewtarget": "viewTarget",
223 "xchannelselector": "xChannelSelector",
224 "ychannelselector": "yChannelSelector",
225 "zoomandpan": "zoomAndPan",
226}
diff --git a/vendor/golang.org/x/net/html/node.go b/vendor/golang.org/x/net/html/node.go
new file mode 100644
index 0000000..26b657a
--- /dev/null
+++ b/vendor/golang.org/x/net/html/node.go
@@ -0,0 +1,193 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package html
6
7import (
8 "golang.org/x/net/html/atom"
9)
10
11// A NodeType is the type of a Node.
12type NodeType uint32
13
14const (
15 ErrorNode NodeType = iota
16 TextNode
17 DocumentNode
18 ElementNode
19 CommentNode
20 DoctypeNode
21 scopeMarkerNode
22)
23
24// Section 12.2.3.3 says "scope markers are inserted when entering applet
25// elements, buttons, object elements, marquees, table cells, and table
26// captions, and are used to prevent formatting from 'leaking'".
27var scopeMarker = Node{Type: scopeMarkerNode}
28
29// A Node consists of a NodeType and some Data (tag name for element nodes,
30// content for text) and are part of a tree of Nodes. Element nodes may also
31// have a Namespace and contain a slice of Attributes. Data is unescaped, so
32// that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
33// is the atom for Data, or zero if Data is not a known tag name.
34//
35// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
36// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
37// "svg" is short for "http://www.w3.org/2000/svg".
38type Node struct {
39 Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
40
41 Type NodeType
42 DataAtom atom.Atom
43 Data string
44 Namespace string
45 Attr []Attribute
46}
47
48// InsertBefore inserts newChild as a child of n, immediately before oldChild
49// in the sequence of n's children. oldChild may be nil, in which case newChild
50// is appended to the end of n's children.
51//
52// It will panic if newChild already has a parent or siblings.
53func (n *Node) InsertBefore(newChild, oldChild *Node) {
54 if newChild.Parent != nil || newChild.PrevSibling != nil || newChild.NextSibling != nil {
55 panic("html: InsertBefore called for an attached child Node")
56 }
57 var prev, next *Node
58 if oldChild != nil {
59 prev, next = oldChild.PrevSibling, oldChild
60 } else {
61 prev = n.LastChild
62 }
63 if prev != nil {
64 prev.NextSibling = newChild
65 } else {
66 n.FirstChild = newChild
67 }
68 if next != nil {
69 next.PrevSibling = newChild
70 } else {
71 n.LastChild = newChild
72 }
73 newChild.Parent = n
74 newChild.PrevSibling = prev
75 newChild.NextSibling = next
76}
77
78// AppendChild adds a node c as a child of n.
79//
80// It will panic if c already has a parent or siblings.
81func (n *Node) AppendChild(c *Node) {
82 if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {
83 panic("html: AppendChild called for an attached child Node")
84 }
85 last := n.LastChild
86 if last != nil {
87 last.NextSibling = c
88 } else {
89 n.FirstChild = c
90 }
91 n.LastChild = c
92 c.Parent = n
93 c.PrevSibling = last
94}
95
96// RemoveChild removes a node c that is a child of n. Afterwards, c will have
97// no parent and no siblings.
98//
99// It will panic if c's parent is not n.
100func (n *Node) RemoveChild(c *Node) {
101 if c.Parent != n {
102 panic("html: RemoveChild called for a non-child Node")
103 }
104 if n.FirstChild == c {
105 n.FirstChild = c.NextSibling
106 }
107 if c.NextSibling != nil {
108 c.NextSibling.PrevSibling = c.PrevSibling
109 }
110 if n.LastChild == c {
111 n.LastChild = c.PrevSibling
112 }
113 if c.PrevSibling != nil {
114 c.PrevSibling.NextSibling = c.NextSibling
115 }
116 c.Parent = nil
117 c.PrevSibling = nil
118 c.NextSibling = nil
119}
120
121// reparentChildren reparents all of src's child nodes to dst.
122func reparentChildren(dst, src *Node) {
123 for {
124 child := src.FirstChild
125 if child == nil {
126 break
127 }
128 src.RemoveChild(child)
129 dst.AppendChild(child)
130 }
131}
132
133// clone returns a new node with the same type, data and attributes.
134// The clone has no parent, no siblings and no children.
135func (n *Node) clone() *Node {
136 m := &Node{
137 Type: n.Type,
138 DataAtom: n.DataAtom,
139 Data: n.Data,
140 Attr: make([]Attribute, len(n.Attr)),
141 }
142 copy(m.Attr, n.Attr)
143 return m
144}
145
146// nodeStack is a stack of nodes.
147type nodeStack []*Node
148
149// pop pops the stack. It will panic if s is empty.
150func (s *nodeStack) pop() *Node {
151 i := len(*s)
152 n := (*s)[i-1]
153 *s = (*s)[:i-1]
154 return n
155}
156
157// top returns the most recently pushed node, or nil if s is empty.
158func (s *nodeStack) top() *Node {
159 if i := len(*s); i > 0 {
160 return (*s)[i-1]
161 }
162 return nil
163}
164
165// index returns the index of the top-most occurrence of n in the stack, or -1
166// if n is not present.
167func (s *nodeStack) index(n *Node) int {
168 for i := len(*s) - 1; i >= 0; i-- {
169 if (*s)[i] == n {
170 return i
171 }
172 }
173 return -1
174}
175
176// insert inserts a node at the given index.
177func (s *nodeStack) insert(i int, n *Node) {
178 (*s) = append(*s, nil)
179 copy((*s)[i+1:], (*s)[i:])
180 (*s)[i] = n
181}
182
183// remove removes a node from the stack. It is a no-op if n is not present.
184func (s *nodeStack) remove(n *Node) {
185 i := s.index(n)
186 if i == -1 {
187 return
188 }
189 copy((*s)[i:], (*s)[i+1:])
190 j := len(*s) - 1
191 (*s)[j] = nil
192 *s = (*s)[:j]
193}
diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go
new file mode 100644
index 0000000..be4b2bf
--- /dev/null
+++ b/vendor/golang.org/x/net/html/parse.go
@@ -0,0 +1,2094 @@
1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package html
6
7import (
8 "errors"
9 "fmt"
10 "io"
11 "strings"
12
13 a "golang.org/x/net/html/atom"
14)
15
16// A parser implements the HTML5 parsing algorithm:
17// https://html.spec.whatwg.org/multipage/syntax.html#tree-construction
18type parser struct {
19 // tokenizer provides the tokens for the parser.
20 tokenizer *Tokenizer
21 // tok is the most recently read token.
22 tok Token
23 // Self-closing tags like <hr/> are treated as start tags, except that
24 // hasSelfClosingToken is set while they are being processed.
25 hasSelfClosingToken bool
26 // doc is the document root element.
27 doc *Node
28 // The stack of open elements (section 12.2.3.2) and active formatting
29 // elements (section 12.2.3.3).
30 oe, afe nodeStack
31 // Element pointers (section 12.2.3.4).
32 head, form *Node
33 // Other parsing state flags (section 12.2.3.5).
34 scripting, framesetOK bool
35 // im is the current insertion mode.
36 im insertionMode
37 // originalIM is the insertion mode to go back to after completing a text
38 // or inTableText insertion mode.
39 originalIM insertionMode
40 // fosterParenting is whether new elements should be inserted according to
41 // the foster parenting rules (section 12.2.5.3).
42 fosterParenting bool
43 // quirks is whether the parser is operating in "quirks mode."
44 quirks bool
45 // fragment is whether the parser is parsing an HTML fragment.
46 fragment bool
47 // context is the context element when parsing an HTML fragment
48 // (section 12.4).
49 context *Node
50}
51
52func (p *parser) top() *Node {
53 if n := p.oe.top(); n != nil {
54 return n
55 }
56 return p.doc
57}
58
59// Stop tags for use in popUntil. These come from section 12.2.3.2.
60var (
61 defaultScopeStopTags = map[string][]a.Atom{
62 "": {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template},
63 "math": {a.AnnotationXml, a.Mi, a.Mn, a.Mo, a.Ms, a.Mtext},
64 "svg": {a.Desc, a.ForeignObject, a.Title},
65 }
66)
67
68type scope int
69
70const (
71 defaultScope scope = iota
72 listItemScope
73 buttonScope
74 tableScope
75 tableRowScope
76 tableBodyScope
77 selectScope
78)
79
80// popUntil pops the stack of open elements at the highest element whose tag
81// is in matchTags, provided there is no higher element in the scope's stop
82// tags (as defined in section 12.2.3.2). It returns whether or not there was
83// such an element. If there was not, popUntil leaves the stack unchanged.
84//
85// For example, the set of stop tags for table scope is: "html", "table". If
86// the stack was:
87// ["html", "body", "font", "table", "b", "i", "u"]
88// then popUntil(tableScope, "font") would return false, but
89// popUntil(tableScope, "i") would return true and the stack would become:
90// ["html", "body", "font", "table", "b"]
91//
92// If an element's tag is in both the stop tags and matchTags, then the stack
93// will be popped and the function returns true (provided, of course, there was
94// no higher element in the stack that was also in the stop tags). For example,
95// popUntil(tableScope, "table") returns true and leaves:
96// ["html", "body", "font"]
97func (p *parser) popUntil(s scope, matchTags ...a.Atom) bool {
98 if i := p.indexOfElementInScope(s, matchTags...); i != -1 {
99 p.oe = p.oe[:i]
100 return true
101 }
102 return false
103}
104
105// indexOfElementInScope returns the index in p.oe of the highest element whose
106// tag is in matchTags that is in scope. If no matching element is in scope, it
107// returns -1.
108func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {
109 for i := len(p.oe) - 1; i >= 0; i-- {
110 tagAtom := p.oe[i].DataAtom
111 if p.oe[i].Namespace == "" {
112 for _, t := range matchTags {
113 if t == tagAtom {
114 return i
115 }
116 }
117 switch s {
118 case defaultScope:
119 // No-op.
120 case listItemScope:
121 if tagAtom == a.Ol || tagAtom == a.Ul {
122 return -1
123 }
124 case buttonScope:
125 if tagAtom == a.Button {
126 return -1
127 }
128 case tableScope:
129 if tagAtom == a.Html || tagAtom == a.Table {
130 return -1
131 }
132 case selectScope:
133 if tagAtom != a.Optgroup && tagAtom != a.Option {
134 return -1
135 }
136 default:
137 panic("unreachable")
138 }
139 }
140 switch s {
141 case defaultScope, listItemScope, buttonScope:
142 for _, t := range defaultScopeStopTags[p.oe[i].Namespace] {
143 if t == tagAtom {
144 return -1
145 }
146 }
147 }
148 }
149 return -1
150}
151
152// elementInScope is like popUntil, except that it doesn't modify the stack of
153// open elements.
154func (p *parser) elementInScope(s scope, matchTags ...a.Atom) bool {
155 return p.indexOfElementInScope(s, matchTags...) != -1
156}
157
158// clearStackToContext pops elements off the stack of open elements until a
159// scope-defined element is found.
160func (p *parser) clearStackToContext(s scope) {
161 for i := len(p.oe) - 1; i >= 0; i-- {
162 tagAtom := p.oe[i].DataAtom
163 switch s {
164 case tableScope:
165 if tagAtom == a.Html || tagAtom == a.Table {
166 p.oe = p.oe[:i+1]
167 return
168 }
169 case tableRowScope:
170 if tagAtom == a.Html || tagAtom == a.Tr {
171 p.oe = p.oe[:i+1]
172 return
173 }
174 case tableBodyScope:
175 if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead {
176 p.oe = p.oe[:i+1]
177 return
178 }
179 default:
180 panic("unreachable")
181 }
182 }
183}
184
185// generateImpliedEndTags pops nodes off the stack of open elements as long as
186// the top node has a tag name of dd, dt, li, option, optgroup, p, rp, or rt.
187// If exceptions are specified, nodes with that name will not be popped off.
188func (p *parser) generateImpliedEndTags(exceptions ...string) {
189 var i int
190loop:
191 for i = len(p.oe) - 1; i >= 0; i-- {
192 n := p.oe[i]
193 if n.Type == ElementNode {
194 switch n.DataAtom {
195 case a.Dd, a.Dt, a.Li, a.Option, a.Optgroup, a.P, a.Rp, a.Rt:
196 for _, except := range exceptions {
197 if n.Data == except {
198 break loop
199 }
200 }
201 continue
202 }
203 }
204 break
205 }
206
207 p.oe = p.oe[:i+1]
208}
209
210// addChild adds a child node n to the top element, and pushes n onto the stack
211// of open elements if it is an element node.
212func (p *parser) addChild(n *Node) {
213 if p.shouldFosterParent() {
214 p.fosterParent(n)
215 } else {
216 p.top().AppendChild(n)
217 }
218
219 if n.Type == ElementNode {
220 p.oe = append(p.oe, n)
221 }
222}
223
224// shouldFosterParent returns whether the next node to be added should be
225// foster parented.
226func (p *parser) shouldFosterParent() bool {
227 if p.fosterParenting {
228 switch p.top().DataAtom {
229 case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
230 return true
231 }
232 }
233 return false
234}
235
236// fosterParent adds a child node according to the foster parenting rules.
237// Section 12.2.5.3, "foster parenting".
238func (p *parser) fosterParent(n *Node) {
239 var table, parent, prev *Node
240 var i int
241 for i = len(p.oe) - 1; i >= 0; i-- {
242 if p.oe[i].DataAtom == a.Table {
243 table = p.oe[i]
244 break
245 }
246 }
247
248 if table == nil {
249 // The foster parent is the html element.
250 parent = p.oe[0]
251 } else {
252 parent = table.Parent
253 }
254 if parent == nil {
255 parent = p.oe[i-1]
256 }
257
258 if table != nil {
259 prev = table.PrevSibling
260 } else {
261 prev = parent.LastChild
262 }
263 if prev != nil && prev.Type == TextNode && n.Type == TextNode {
264 prev.Data += n.Data
265 return
266 }
267
268 parent.InsertBefore(n, table)
269}
270
271// addText adds text to the preceding node if it is a text node, or else it
272// calls addChild with a new text node.
273func (p *parser) addText(text string) {
274 if text == "" {
275 return
276 }
277
278 if p.shouldFosterParent() {
279 p.fosterParent(&Node{
280 Type: TextNode,
281 Data: text,
282 })
283 return
284 }
285
286 t := p.top()
287 if n := t.LastChild; n != nil && n.Type == TextNode {
288 n.Data += text
289 return
290 }
291 p.addChild(&Node{
292 Type: TextNode,
293 Data: text,
294 })
295}
296
297// addElement adds a child element based on the current token.
298func (p *parser) addElement() {
299 p.addChild(&Node{
300 Type: ElementNode,
301 DataAtom: p.tok.DataAtom,
302 Data: p.tok.Data,
303 Attr: p.tok.Attr,
304 })
305}
306
307// Section 12.2.3.3.
308func (p *parser) addFormattingElement() {
309 tagAtom, attr := p.tok.DataAtom, p.tok.Attr
310 p.addElement()
311
312 // Implement the Noah's Ark clause, but with three per family instead of two.
313 identicalElements := 0
314findIdenticalElements:
315 for i := len(p.afe) - 1; i >= 0; i-- {
316 n := p.afe[i]
317 if n.Type == scopeMarkerNode {
318 break
319 }
320 if n.Type != ElementNode {
321 continue
322 }
323 if n.Namespace != "" {
324 continue
325 }
326 if n.DataAtom != tagAtom {
327 continue
328 }
329 if len(n.Attr) != len(attr) {
330 continue
331 }
332 compareAttributes:
333 for _, t0 := range n.Attr {
334 for _, t1 := range attr {
335 if t0.Key == t1.Key && t0.Namespace == t1.Namespace && t0.Val == t1.Val {
336 // Found a match for this attribute, continue with the next attribute.
337 continue compareAttributes
338 }
339 }
340 // If we get here, there is no attribute that matches a.
341 // Therefore the element is not identical to the new one.
342 continue findIdenticalElements
343 }
344
345 identicalElements++
346 if identicalElements >= 3 {
347 p.afe.remove(n)
348 }
349 }
350
351 p.afe = append(p.afe, p.top())
352}
353
354// Section 12.2.3.3.
355func (p *parser) clearActiveFormattingElements() {
356 for {
357 n := p.afe.pop()
358 if len(p.afe) == 0 || n.Type == scopeMarkerNode {
359 return
360 }
361 }
362}
363
364// Section 12.2.3.3.
365func (p *parser) reconstructActiveFormattingElements() {
366 n := p.afe.top()
367 if n == nil {
368 return
369 }
370 if n.Type == scopeMarkerNode || p.oe.index(n) != -1 {
371 return
372 }
373 i := len(p.afe) - 1
374 for n.Type != scopeMarkerNode && p.oe.index(n) == -1 {
375 if i == 0 {
376 i = -1
377 break
378 }
379 i--
380 n = p.afe[i]
381 }
382 for {
383 i++
384 clone := p.afe[i].clone()
385 p.addChild(clone)
386 p.afe[i] = clone
387 if i == len(p.afe)-1 {
388 break
389 }
390 }
391}
392
393// Section 12.2.4.
394func (p *parser) acknowledgeSelfClosingTag() {
395 p.hasSelfClosingToken = false
396}
397
398// An insertion mode (section 12.2.3.1) is the state transition function from
399// a particular state in the HTML5 parser's state machine. It updates the
400// parser's fields depending on parser.tok (where ErrorToken means EOF).
401// It returns whether the token was consumed.
402type insertionMode func(*parser) bool
403
404// setOriginalIM sets the insertion mode to return to after completing a text or
405// inTableText insertion mode.
406// Section 12.2.3.1, "using the rules for".
407func (p *parser) setOriginalIM() {
408 if p.originalIM != nil {
409 panic("html: bad parser state: originalIM was set twice")
410 }
411 p.originalIM = p.im
412}
413
414// Section 12.2.3.1, "reset the insertion mode".
415func (p *parser) resetInsertionMode() {
416 for i := len(p.oe) - 1; i >= 0; i-- {
417 n := p.oe[i]
418 if i == 0 && p.context != nil {
419 n = p.context
420 }
421
422 switch n.DataAtom {
423 case a.Select:
424 p.im = inSelectIM
425 case a.Td, a.Th:
426 p.im = inCellIM
427 case a.Tr:
428 p.im = inRowIM
429 case a.Tbody, a.Thead, a.Tfoot:
430 p.im = inTableBodyIM
431 case a.Caption:
432 p.im = inCaptionIM
433 case a.Colgroup:
434 p.im = inColumnGroupIM
435 case a.Table:
436 p.im = inTableIM
437 case a.Head:
438 p.im = inBodyIM
439 case a.Body:
440 p.im = inBodyIM
441 case a.Frameset:
442 p.im = inFramesetIM
443 case a.Html:
444 p.im = beforeHeadIM
445 default:
446 continue
447 }
448 return
449 }
450 p.im = inBodyIM
451}
452
453const whitespace = " \t\r\n\f"
454
455// Section 12.2.5.4.1.
456func initialIM(p *parser) bool {
457 switch p.tok.Type {
458 case TextToken:
459 p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
460 if len(p.tok.Data) == 0 {
461 // It was all whitespace, so ignore it.
462 return true
463 }
464 case CommentToken:
465 p.doc.AppendChild(&Node{
466 Type: CommentNode,
467 Data: p.tok.Data,
468 })
469 return true
470 case DoctypeToken:
471 n, quirks := parseDoctype(p.tok.Data)
472 p.doc.AppendChild(n)
473 p.quirks = quirks
474 p.im = beforeHTMLIM
475 return true
476 }
477 p.quirks = true
478 p.im = beforeHTMLIM
479 return false
480}
481
482// Section 12.2.5.4.2.
483func beforeHTMLIM(p *parser) bool {
484 switch p.tok.Type {
485 case DoctypeToken:
486 // Ignore the token.
487 return true
488 case TextToken:
489 p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
490 if len(p.tok.Data) == 0 {
491 // It was all whitespace, so ignore it.
492 return true
493 }
494 case StartTagToken:
495 if p.tok.DataAtom == a.Html {
496 p.addElement()
497 p.im = beforeHeadIM
498 return true
499 }
500 case EndTagToken:
501 switch p.tok.DataAtom {
502 case a.Head, a.Body, a.Html, a.Br:
503 p.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
504 return false
505 default:
506 // Ignore the token.
507 return true
508 }
509 case CommentToken:
510 p.doc.AppendChild(&Node{
511 Type: CommentNode,
512 Data: p.tok.Data,
513 })
514 return true
515 }
516 p.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
517 return false
518}
519
520// Section 12.2.5.4.3.
521func beforeHeadIM(p *parser) bool {
522 switch p.tok.Type {
523 case TextToken:
524 p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
525 if len(p.tok.Data) == 0 {
526 // It was all whitespace, so ignore it.
527 return true
528 }
529 case StartTagToken:
530 switch p.tok.DataAtom {
531 case a.Head:
532 p.addElement()
533 p.head = p.top()
534 p.im = inHeadIM
535 return true
536 case a.Html:
537 return inBodyIM(p)
538 }
539 case EndTagToken:
540 switch p.tok.DataAtom {
541 case a.Head, a.Body, a.Html, a.Br:
542 p.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
543 return false
544 default:
545 // Ignore the token.
546 return true
547 }
548 case CommentToken:
549 p.addChild(&Node{
550 Type: CommentNode,
551 Data: p.tok.Data,
552 })
553 return true
554 case DoctypeToken:
555 // Ignore the token.
556 return true
557 }
558
559 p.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
560 return false
561}
562
563// Section 12.2.5.4.4.
564func inHeadIM(p *parser) bool {
565 switch p.tok.Type {
566 case TextToken:
567 s := strings.TrimLeft(p.tok.Data, whitespace)
568 if len(s) < len(p.tok.Data) {
569 // Add the initial whitespace to the current node.
570 p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
571 if s == "" {
572 return true
573 }
574 p.tok.Data = s
575 }
576 case StartTagToken:
577 switch p.tok.DataAtom {
578 case a.Html:
579 return inBodyIM(p)
580 case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta:
581 p.addElement()
582 p.oe.pop()
583 p.acknowledgeSelfClosingTag()
584 return true
585 case a.Script, a.Title, a.Noscript, a.Noframes, a.Style:
586 p.addElement()
587 p.setOriginalIM()
588 p.im = textIM
589 return true
590 case a.Head:
591 // Ignore the token.
592 return true
593 }
594 case EndTagToken:
595 switch p.tok.DataAtom {
596 case a.Head:
597 n := p.oe.pop()
598 if n.DataAtom != a.Head {
599 panic("html: bad parser state: <head> element not found, in the in-head insertion mode")
600 }
601 p.im = afterHeadIM
602 return true
603 case a.Body, a.Html, a.Br:
604 p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
605 return false
606 default:
607 // Ignore the token.
608 return true
609 }
610 case CommentToken:
611 p.addChild(&Node{
612 Type: CommentNode,
613 Data: p.tok.Data,
614 })
615 return true
616 case DoctypeToken:
617 // Ignore the token.
618 return true
619 }
620
621 p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
622 return false
623}
624
625// Section 12.2.5.4.6.
626func afterHeadIM(p *parser) bool {
627 switch p.tok.Type {
628 case TextToken:
629 s := strings.TrimLeft(p.tok.Data, whitespace)
630 if len(s) < len(p.tok.Data) {
631 // Add the initial whitespace to the current node.
632 p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
633 if s == "" {
634 return true
635 }
636 p.tok.Data = s
637 }
638 case StartTagToken:
639 switch p.tok.DataAtom {
640 case a.Html:
641 return inBodyIM(p)
642 case a.Body:
643 p.addElement()
644 p.framesetOK = false
645 p.im = inBodyIM
646 return true
647 case a.Frameset:
648 p.addElement()
649 p.im = inFramesetIM
650 return true
651 case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:
652 p.oe = append(p.oe, p.head)
653 defer p.oe.remove(p.head)
654 return inHeadIM(p)
655 case a.Head:
656 // Ignore the token.
657 return true
658 }
659 case EndTagToken:
660 switch p.tok.DataAtom {
661 case a.Body, a.Html, a.Br:
662 // Drop down to creating an implied <body> tag.
663 default:
664 // Ignore the token.
665 return true
666 }
667 case CommentToken:
668 p.addChild(&Node{
669 Type: CommentNode,
670 Data: p.tok.Data,
671 })
672 return true
673 case DoctypeToken:
674 // Ignore the token.
675 return true
676 }
677
678 p.parseImpliedToken(StartTagToken, a.Body, a.Body.String())
679 p.framesetOK = true
680 return false
681}
682
683// copyAttributes copies attributes of src not found on dst to dst.
684func copyAttributes(dst *Node, src Token) {
685 if len(src.Attr) == 0 {
686 return
687 }
688 attr := map[string]string{}
689 for _, t := range dst.Attr {
690 attr[t.Key] = t.Val
691 }
692 for _, t := range src.Attr {
693 if _, ok := attr[t.Key]; !ok {
694 dst.Attr = append(dst.Attr, t)
695 attr[t.Key] = t.Val
696 }
697 }
698}
699
700// Section 12.2.5.4.7.
701func inBodyIM(p *parser) bool {
702 switch p.tok.Type {
703 case TextToken:
704 d := p.tok.Data
705 switch n := p.oe.top(); n.DataAtom {
706 case a.Pre, a.Listing:
707 if n.FirstChild == nil {
708 // Ignore a newline at the start of a <pre> block.
709 if d != "" && d[0] == '\r' {
710 d = d[1:]
711 }
712 if d != "" && d[0] == '\n' {
713 d = d[1:]
714 }
715 }
716 }
717 d = strings.Replace(d, "\x00", "", -1)
718 if d == "" {
719 return true
720 }
721 p.reconstructActiveFormattingElements()
722 p.addText(d)
723 if p.framesetOK && strings.TrimLeft(d, whitespace) != "" {
724 // There were non-whitespace characters inserted.
725 p.framesetOK = false
726 }
727 case StartTagToken:
728 switch p.tok.DataAtom {
729 case a.Html:
730 copyAttributes(p.oe[0], p.tok)
731 case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title:
732 return inHeadIM(p)
733 case a.Body:
734 if len(p.oe) >= 2 {
735 body := p.oe[1]
736 if body.Type == ElementNode && body.DataAtom == a.Body {
737 p.framesetOK = false
738 copyAttributes(body, p.tok)
739 }
740 }
741 case a.Frameset:
742 if !p.framesetOK || len(p.oe) < 2 || p.oe[1].DataAtom != a.Body {
743 // Ignore the token.
744 return true
745 }
746 body := p.oe[1]
747 if body.Parent != nil {
748 body.Parent.RemoveChild(body)
749 }
750 p.oe = p.oe[:1]
751 p.addElement()
752 p.im = inFramesetIM
753 return true
754 case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
755 p.popUntil(buttonScope, a.P)
756 p.addElement()
757 case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
758 p.popUntil(buttonScope, a.P)
759 switch n := p.top(); n.DataAtom {
760 case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
761 p.oe.pop()
762 }
763 p.addElement()
764 case a.Pre, a.Listing:
765 p.popUntil(buttonScope, a.P)
766 p.addElement()
767 // The newline, if any, will be dealt with by the TextToken case.
768 p.framesetOK = false
769 case a.Form:
770 if p.form == nil {
771 p.popUntil(buttonScope, a.P)
772 p.addElement()
773 p.form = p.top()
774 }
775 case a.Li:
776 p.framesetOK = false
777 for i := len(p.oe) - 1; i >= 0; i-- {
778 node := p.oe[i]
779 switch node.DataAtom {
780 case a.Li:
781 p.oe = p.oe[:i]
782 case a.Address, a.Div, a.P:
783 continue
784 default:
785 if !isSpecialElement(node) {
786 continue
787 }
788 }
789 break
790 }
791 p.popUntil(buttonScope, a.P)
792 p.addElement()
793 case a.Dd, a.Dt:
794 p.framesetOK = false
795 for i := len(p.oe) - 1; i >= 0; i-- {
796 node := p.oe[i]
797 switch node.DataAtom {
798 case a.Dd, a.Dt:
799 p.oe = p.oe[:i]
800 case a.Address, a.Div, a.P:
801 continue
802 default:
803 if !isSpecialElement(node) {
804 continue
805 }
806 }
807 break
808 }
809 p.popUntil(buttonScope, a.P)
810 p.addElement()
811 case a.Plaintext:
812 p.popUntil(buttonScope, a.P)
813 p.addElement()
814 case a.Button:
815 p.popUntil(defaultScope, a.Button)
816 p.reconstructActiveFormattingElements()
817 p.addElement()
818 p.framesetOK = false
819 case a.A:
820 for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
821 if n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A {
822 p.inBodyEndTagFormatting(a.A)
823 p.oe.remove(n)
824 p.afe.remove(n)
825 break
826 }
827 }
828 p.reconstructActiveFormattingElements()
829 p.addFormattingElement()
830 case a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
831 p.reconstructActiveFormattingElements()
832 p.addFormattingElement()
833 case a.Nobr:
834 p.reconstructActiveFormattingElements()
835 if p.elementInScope(defaultScope, a.Nobr) {
836 p.inBodyEndTagFormatting(a.Nobr)
837 p.reconstructActiveFormattingElements()
838 }
839 p.addFormattingElement()
840 case a.Applet, a.Marquee, a.Object:
841 p.reconstructActiveFormattingElements()
842 p.addElement()
843 p.afe = append(p.afe, &scopeMarker)
844 p.framesetOK = false
845 case a.Table:
846 if !p.quirks {
847 p.popUntil(buttonScope, a.P)
848 }
849 p.addElement()
850 p.framesetOK = false
851 p.im = inTableIM
852 return true
853 case a.Area, a.Br, a.Embed, a.Img, a.Input, a.Keygen, a.Wbr:
854 p.reconstructActiveFormattingElements()
855 p.addElement()
856 p.oe.pop()
857 p.acknowledgeSelfClosingTag()
858 if p.tok.DataAtom == a.Input {
859 for _, t := range p.tok.Attr {
860 if t.Key == "type" {
861 if strings.ToLower(t.Val) == "hidden" {
862 // Skip setting framesetOK = false
863 return true
864 }
865 }
866 }
867 }
868 p.framesetOK = false
869 case a.Param, a.Source, a.Track:
870 p.addElement()
871 p.oe.pop()
872 p.acknowledgeSelfClosingTag()
873 case a.Hr:
874 p.popUntil(buttonScope, a.P)
875 p.addElement()
876 p.oe.pop()
877 p.acknowledgeSelfClosingTag()
878 p.framesetOK = false
879 case a.Image:
880 p.tok.DataAtom = a.Img
881 p.tok.Data = a.Img.String()
882 return false
883 case a.Isindex:
884 if p.form != nil {
885 // Ignore the token.
886 return true
887 }
888 action := ""
889 prompt := "This is a searchable index. Enter search keywords: "
890 attr := []Attribute{{Key: "name", Val: "isindex"}}
891 for _, t := range p.tok.Attr {
892 switch t.Key {
893 case "action":
894 action = t.Val
895 case "name":
896 // Ignore the attribute.
897 case "prompt":
898 prompt = t.Val
899 default:
900 attr = append(attr, t)
901 }
902 }
903 p.acknowledgeSelfClosingTag()
904 p.popUntil(buttonScope, a.P)
905 p.parseImpliedToken(StartTagToken, a.Form, a.Form.String())
906 if action != "" {
907 p.form.Attr = []Attribute{{Key: "action", Val: action}}
908 }
909 p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
910 p.parseImpliedToken(StartTagToken, a.Label, a.Label.String())
911 p.addText(prompt)
912 p.addChild(&Node{
913 Type: ElementNode,
914 DataAtom: a.Input,
915 Data: a.Input.String(),
916 Attr: attr,
917 })
918 p.oe.pop()
919 p.parseImpliedToken(EndTagToken, a.Label, a.Label.String())
920 p.parseImpliedToken(StartTagToken, a.Hr, a.Hr.String())
921 p.parseImpliedToken(EndTagToken, a.Form, a.Form.String())
922 case a.Textarea:
923 p.addElement()
924 p.setOriginalIM()
925 p.framesetOK = false
926 p.im = textIM
927 case a.Xmp:
928 p.popUntil(buttonScope, a.P)
929 p.reconstructActiveFormattingElements()
930 p.framesetOK = false
931 p.addElement()
932 p.setOriginalIM()
933 p.im = textIM
934 case a.Iframe:
935 p.framesetOK = false
936 p.addElement()
937 p.setOriginalIM()
938 p.im = textIM
939 case a.Noembed, a.Noscript:
940 p.addElement()
941 p.setOriginalIM()
942 p.im = textIM
943 case a.Select:
944 p.reconstructActiveFormattingElements()
945 p.addElement()
946 p.framesetOK = false
947 p.im = inSelectIM
948 return true
949 case a.Optgroup, a.Option:
950 if p.top().DataAtom == a.Option {
951 p.oe.pop()
952 }
953 p.reconstructActiveFormattingElements()
954 p.addElement()
955 case a.Rp, a.Rt:
956 if p.elementInScope(defaultScope, a.Ruby) {
957 p.generateImpliedEndTags()
958 }
959 p.addElement()
960 case a.Math, a.Svg:
961 p.reconstructActiveFormattingElements()
962 if p.tok.DataAtom == a.Math {
963 adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
964 } else {
965 adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
966 }
967 adjustForeignAttributes(p.tok.Attr)
968 p.addElement()
969 p.top().Namespace = p.tok.Data
970 if p.hasSelfClosingToken {
971 p.oe.pop()
972 p.acknowledgeSelfClosingTag()
973 }
974 return true
975 case a.Caption, a.Col, a.Colgroup, a.Frame, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
976 // Ignore the token.
977 default:
978 p.reconstructActiveFormattingElements()
979 p.addElement()
980 }
981 case EndTagToken:
982 switch p.tok.DataAtom {
983 case a.Body:
984 if p.elementInScope(defaultScope, a.Body) {
985 p.im = afterBodyIM
986 }
987 case a.Html:
988 if p.elementInScope(defaultScope, a.Body) {
989 p.parseImpliedToken(EndTagToken, a.Body, a.Body.String())
990 return false
991 }
992 return true
993 case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
994 p.popUntil(defaultScope, p.tok.DataAtom)
995 case a.Form:
996 node := p.form
997 p.form = nil
998 i := p.indexOfElementInScope(defaultScope, a.Form)
999 if node == nil || i == -1 || p.oe[i] != node {
1000 // Ignore the token.
1001 return true
1002 }
1003 p.generateImpliedEndTags()
1004 p.oe.remove(node)
1005 case a.P:
1006 if !p.elementInScope(buttonScope, a.P) {
1007 p.parseImpliedToken(StartTagToken, a.P, a.P.String())
1008 }
1009 p.popUntil(buttonScope, a.P)
1010 case a.Li:
1011 p.popUntil(listItemScope, a.Li)
1012 case a.Dd, a.Dt:
1013 p.popUntil(defaultScope, p.tok.DataAtom)
1014 case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
1015 p.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6)
1016 case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
1017 p.inBodyEndTagFormatting(p.tok.DataAtom)
1018 case a.Applet, a.Marquee, a.Object:
1019 if p.popUntil(defaultScope, p.tok.DataAtom) {
1020 p.clearActiveFormattingElements()
1021 }
1022 case a.Br:
1023 p.tok.Type = StartTagToken
1024 return false
1025 default:
1026 p.inBodyEndTagOther(p.tok.DataAtom)
1027 }
1028 case CommentToken:
1029 p.addChild(&Node{
1030 Type: CommentNode,
1031 Data: p.tok.Data,
1032 })
1033 }
1034
1035 return true
1036}
1037
1038func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
1039 // This is the "adoption agency" algorithm, described at
1040 // https://html.spec.whatwg.org/multipage/syntax.html#adoptionAgency
1041
1042 // TODO: this is a fairly literal line-by-line translation of that algorithm.
1043 // Once the code successfully parses the comprehensive test suite, we should
1044 // refactor this code to be more idiomatic.
1045
1046 // Steps 1-4. The outer loop.
1047 for i := 0; i < 8; i++ {
1048 // Step 5. Find the formatting element.
1049 var formattingElement *Node
1050 for j := len(p.afe) - 1; j >= 0; j-- {
1051 if p.afe[j].Type == scopeMarkerNode {
1052 break
1053 }
1054 if p.afe[j].DataAtom == tagAtom {
1055 formattingElement = p.afe[j]
1056 break
1057 }
1058 }
1059 if formattingElement == nil {
1060 p.inBodyEndTagOther(tagAtom)
1061 return
1062 }
1063 feIndex := p.oe.index(formattingElement)
1064 if feIndex == -1 {
1065 p.afe.remove(formattingElement)
1066 return
1067 }
1068 if !p.elementInScope(defaultScope, tagAtom) {
1069 // Ignore the tag.
1070 return
1071 }
1072
1073 // Steps 9-10. Find the furthest block.
1074 var furthestBlock *Node
1075 for _, e := range p.oe[feIndex:] {
1076 if isSpecialElement(e) {
1077 furthestBlock = e
1078 break
1079 }
1080 }
1081 if furthestBlock == nil {
1082 e := p.oe.pop()
1083 for e != formattingElement {
1084 e = p.oe.pop()
1085 }
1086 p.afe.remove(e)
1087 return
1088 }
1089
1090 // Steps 11-12. Find the common ancestor and bookmark node.
1091 commonAncestor := p.oe[feIndex-1]
1092 bookmark := p.afe.index(formattingElement)
1093
1094 // Step 13. The inner loop. Find the lastNode to reparent.
1095 lastNode := furthestBlock
1096 node := furthestBlock
1097 x := p.oe.index(node)
1098 // Steps 13.1-13.2
1099 for j := 0; j < 3; j++ {
1100 // Step 13.3.
1101 x--
1102 node = p.oe[x]
1103 // Step 13.4 - 13.5.
1104 if p.afe.index(node) == -1 {
1105 p.oe.remove(node)
1106 continue
1107 }
1108 // Step 13.6.
1109 if node == formattingElement {
1110 break
1111 }
1112 // Step 13.7.
1113 clone := node.clone()
1114 p.afe[p.afe.index(node)] = clone
1115 p.oe[p.oe.index(node)] = clone
1116 node = clone
1117 // Step 13.8.
1118 if lastNode == furthestBlock {
1119 bookmark = p.afe.index(node) + 1
1120 }
1121 // Step 13.9.
1122 if lastNode.Parent != nil {
1123 lastNode.Parent.RemoveChild(lastNode)
1124 }
1125 node.AppendChild(lastNode)
1126 // Step 13.10.
1127 lastNode = node
1128 }
1129
1130 // Step 14. Reparent lastNode to the common ancestor,
1131 // or for misnested table nodes, to the foster parent.
1132 if lastNode.Parent != nil {
1133 lastNode.Parent.RemoveChild(lastNode)
1134 }
1135 switch commonAncestor.DataAtom {
1136 case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
1137 p.fosterParent(lastNode)
1138 default:
1139 commonAncestor.AppendChild(lastNode)
1140 }
1141
1142 // Steps 15-17. Reparent nodes from the furthest block's children
1143 // to a clone of the formatting element.
1144 clone := formattingElement.clone()
1145 reparentChildren(clone, furthestBlock)
1146 furthestBlock.AppendChild(clone)
1147
1148 // Step 18. Fix up the list of active formatting elements.
1149 if oldLoc := p.afe.index(formattingElement); oldLoc != -1 && oldLoc < bookmark {
1150 // Move the bookmark with the rest of the list.
1151 bookmark--
1152 }
1153 p.afe.remove(formattingElement)
1154 p.afe.insert(bookmark, clone)
1155
1156 // Step 19. Fix up the stack of open elements.
1157 p.oe.remove(formattingElement)
1158 p.oe.insert(p.oe.index(furthestBlock)+1, clone)
1159 }
1160}
1161
1162// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
1163// "Any other end tag" handling from 12.2.5.5 The rules for parsing tokens in foreign content
1164// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign
1165func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
1166 for i := len(p.oe) - 1; i >= 0; i-- {
1167 if p.oe[i].DataAtom == tagAtom {
1168 p.oe = p.oe[:i]
1169 break
1170 }
1171 if isSpecialElement(p.oe[i]) {
1172 break
1173 }
1174 }
1175}
1176
1177// Section 12.2.5.4.8.
1178func textIM(p *parser) bool {
1179 switch p.tok.Type {
1180 case ErrorToken:
1181 p.oe.pop()
1182 case TextToken:
1183 d := p.tok.Data
1184 if n := p.oe.top(); n.DataAtom == a.Textarea && n.FirstChild == nil {
1185 // Ignore a newline at the start of a <textarea> block.
1186 if d != "" && d[0] == '\r' {
1187 d = d[1:]
1188 }
1189 if d != "" && d[0] == '\n' {
1190 d = d[1:]
1191 }
1192 }
1193 if d == "" {
1194 return true
1195 }
1196 p.addText(d)
1197 return true
1198 case EndTagToken:
1199 p.oe.pop()
1200 }
1201 p.im = p.originalIM
1202 p.originalIM = nil
1203 return p.tok.Type == EndTagToken
1204}
1205
1206// Section 12.2.5.4.9.
1207func inTableIM(p *parser) bool {
1208 switch p.tok.Type {
1209 case ErrorToken:
1210 // Stop parsing.
1211 return true
1212 case TextToken:
1213 p.tok.Data = strings.Replace(p.tok.Data, "\x00", "", -1)
1214 switch p.oe.top().DataAtom {
1215 case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
1216 if strings.Trim(p.tok.Data, whitespace) == "" {
1217 p.addText(p.tok.Data)
1218 return true
1219 }
1220 }
1221 case StartTagToken:
1222 switch p.tok.DataAtom {
1223 case a.Caption:
1224 p.clearStackToContext(tableScope)
1225 p.afe = append(p.afe, &scopeMarker)
1226 p.addElement()
1227 p.im = inCaptionIM
1228 return true
1229 case a.Colgroup:
1230 p.clearStackToContext(tableScope)
1231 p.addElement()
1232 p.im = inColumnGroupIM
1233 return true
1234 case a.Col:
1235 p.parseImpliedToken(StartTagToken, a.Colgroup, a.Colgroup.String())
1236 return false
1237 case a.Tbody, a.Tfoot, a.Thead:
1238 p.clearStackToContext(tableScope)
1239 p.addElement()
1240 p.im = inTableBodyIM
1241 return true
1242 case a.Td, a.Th, a.Tr:
1243 p.parseImpliedToken(StartTagToken, a.Tbody, a.Tbody.String())
1244 return false
1245 case a.Table:
1246 if p.popUntil(tableScope, a.Table) {
1247 p.resetInsertionMode()
1248 return false
1249 }
1250 // Ignore the token.
1251 return true
1252 case a.Style, a.Script:
1253 return inHeadIM(p)
1254 case a.Input:
1255 for _, t := range p.tok.Attr {
1256 if t.Key == "type" && strings.ToLower(t.Val) == "hidden" {
1257 p.addElement()
1258 p.oe.pop()
1259 return true
1260 }
1261 }
1262 // Otherwise drop down to the default action.
1263 case a.Form:
1264 if p.form != nil {
1265 // Ignore the token.
1266 return true
1267 }
1268 p.addElement()
1269 p.form = p.oe.pop()
1270 case a.Select:
1271 p.reconstructActiveFormattingElements()
1272 switch p.top().DataAtom {
1273 case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
1274 p.fosterParenting = true
1275 }
1276 p.addElement()
1277 p.fosterParenting = false
1278 p.framesetOK = false
1279 p.im = inSelectInTableIM
1280 return true
1281 }
1282 case EndTagToken:
1283 switch p.tok.DataAtom {
1284 case a.Table:
1285 if p.popUntil(tableScope, a.Table) {
1286 p.resetInsertionMode()
1287 return true
1288 }
1289 // Ignore the token.
1290 return true
1291 case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
1292 // Ignore the token.
1293 return true
1294 }
1295 case CommentToken:
1296 p.addChild(&Node{
1297 Type: CommentNode,
1298 Data: p.tok.Data,
1299 })
1300 return true
1301 case DoctypeToken:
1302 // Ignore the token.
1303 return true
1304 }
1305
1306 p.fosterParenting = true
1307 defer func() { p.fosterParenting = false }()
1308
1309 return inBodyIM(p)
1310}
1311
1312// Section 12.2.5.4.11.
1313func inCaptionIM(p *parser) bool {
1314 switch p.tok.Type {
1315 case StartTagToken:
1316 switch p.tok.DataAtom {
1317 case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Thead, a.Tr:
1318 if p.popUntil(tableScope, a.Caption) {
1319 p.clearActiveFormattingElements()
1320 p.im = inTableIM
1321 return false
1322 } else {
1323 // Ignore the token.
1324 return true
1325 }
1326 case a.Select:
1327 p.reconstructActiveFormattingElements()
1328 p.addElement()
1329 p.framesetOK = false
1330 p.im = inSelectInTableIM
1331 return true
1332 }
1333 case EndTagToken:
1334 switch p.tok.DataAtom {
1335 case a.Caption:
1336 if p.popUntil(tableScope, a.Caption) {
1337 p.clearActiveFormattingElements()
1338 p.im = inTableIM
1339 }
1340 return true
1341 case a.Table:
1342 if p.popUntil(tableScope, a.Caption) {
1343 p.clearActiveFormattingElements()
1344 p.im = inTableIM
1345 return false
1346 } else {
1347 // Ignore the token.
1348 return true
1349 }
1350 case a.Body, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
1351 // Ignore the token.
1352 return true
1353 }
1354 }
1355 return inBodyIM(p)
1356}
1357
1358// Section 12.2.5.4.12.
1359func inColumnGroupIM(p *parser) bool {
1360 switch p.tok.Type {
1361 case TextToken:
1362 s := strings.TrimLeft(p.tok.Data, whitespace)
1363 if len(s) < len(p.tok.Data) {
1364 // Add the initial whitespace to the current node.
1365 p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
1366 if s == "" {
1367 return true
1368 }
1369 p.tok.Data = s
1370 }
1371 case CommentToken:
1372 p.addChild(&Node{
1373 Type: CommentNode,
1374 Data: p.tok.Data,
1375 })
1376 return true
1377 case DoctypeToken:
1378 // Ignore the token.
1379 return true
1380 case StartTagToken:
1381 switch p.tok.DataAtom {
1382 case a.Html:
1383 return inBodyIM(p)
1384 case a.Col:
1385 p.addElement()
1386 p.oe.pop()
1387 p.acknowledgeSelfClosingTag()
1388 return true
1389 }
1390 case EndTagToken:
1391 switch p.tok.DataAtom {
1392 case a.Colgroup:
1393 if p.oe.top().DataAtom != a.Html {
1394 p.oe.pop()
1395 p.im = inTableIM
1396 }
1397 return true
1398 case a.Col:
1399 // Ignore the token.
1400 return true
1401 }
1402 }
1403 if p.oe.top().DataAtom != a.Html {
1404 p.oe.pop()
1405 p.im = inTableIM
1406 return false
1407 }
1408 return true
1409}
1410
1411// Section 12.2.5.4.13.
1412func inTableBodyIM(p *parser) bool {
1413 switch p.tok.Type {
1414 case StartTagToken:
1415 switch p.tok.DataAtom {
1416 case a.Tr:
1417 p.clearStackToContext(tableBodyScope)
1418 p.addElement()
1419 p.im = inRowIM
1420 return true
1421 case a.Td, a.Th:
1422 p.parseImpliedToken(StartTagToken, a.Tr, a.Tr.String())
1423 return false
1424 case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:
1425 if p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
1426 p.im = inTableIM
1427 return false
1428 }
1429 // Ignore the token.
1430 return true
1431 }
1432 case EndTagToken:
1433 switch p.tok.DataAtom {
1434 case a.Tbody, a.Tfoot, a.Thead:
1435 if p.elementInScope(tableScope, p.tok.DataAtom) {
1436 p.clearStackToContext(tableBodyScope)
1437 p.oe.pop()
1438 p.im = inTableIM
1439 }
1440 return true
1441 case a.Table:
1442 if p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
1443 p.im = inTableIM
1444 return false
1445 }
1446 // Ignore the token.
1447 return true
1448 case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th, a.Tr:
1449 // Ignore the token.
1450 return true
1451 }
1452 case CommentToken:
1453 p.addChild(&Node{
1454 Type: CommentNode,
1455 Data: p.tok.Data,
1456 })
1457 return true
1458 }
1459
1460 return inTableIM(p)
1461}
1462
1463// Section 12.2.5.4.14.
1464func inRowIM(p *parser) bool {
1465 switch p.tok.Type {
1466 case StartTagToken:
1467 switch p.tok.DataAtom {
1468 case a.Td, a.Th:
1469 p.clearStackToContext(tableRowScope)
1470 p.addElement()
1471 p.afe = append(p.afe, &scopeMarker)
1472 p.im = inCellIM
1473 return true
1474 case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr:
1475 if p.popUntil(tableScope, a.Tr) {
1476 p.im = inTableBodyIM
1477 return false
1478 }
1479 // Ignore the token.
1480 return true
1481 }
1482 case EndTagToken:
1483 switch p.tok.DataAtom {
1484 case a.Tr:
1485 if p.popUntil(tableScope, a.Tr) {
1486 p.im = inTableBodyIM
1487 return true
1488 }
1489 // Ignore the token.
1490 return true
1491 case a.Table:
1492 if p.popUntil(tableScope, a.Tr) {
1493 p.im = inTableBodyIM
1494 return false
1495 }
1496 // Ignore the token.
1497 return true
1498 case a.Tbody, a.Tfoot, a.Thead:
1499 if p.elementInScope(tableScope, p.tok.DataAtom) {
1500 p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String())
1501 return false
1502 }
1503 // Ignore the token.
1504 return true
1505 case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th:
1506 // Ignore the token.
1507 return true
1508 }
1509 }
1510
1511 return inTableIM(p)
1512}
1513
1514// Section 12.2.5.4.15.
1515func inCellIM(p *parser) bool {
1516 switch p.tok.Type {
1517 case StartTagToken:
1518 switch p.tok.DataAtom {
1519 case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
1520 if p.popUntil(tableScope, a.Td, a.Th) {
1521 // Close the cell and reprocess.
1522 p.clearActiveFormattingElements()
1523 p.im = inRowIM
1524 return false
1525 }
1526 // Ignore the token.
1527 return true
1528 case a.Select:
1529 p.reconstructActiveFormattingElements()
1530 p.addElement()
1531 p.framesetOK = false
1532 p.im = inSelectInTableIM
1533 return true
1534 }
1535 case EndTagToken:
1536 switch p.tok.DataAtom {
1537 case a.Td, a.Th:
1538 if !p.popUntil(tableScope, p.tok.DataAtom) {
1539 // Ignore the token.
1540 return true
1541 }
1542 p.clearActiveFormattingElements()
1543 p.im = inRowIM
1544 return true
1545 case a.Body, a.Caption, a.Col, a.Colgroup, a.Html:
1546 // Ignore the token.
1547 return true
1548 case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
1549 if !p.elementInScope(tableScope, p.tok.DataAtom) {
1550 // Ignore the token.
1551 return true
1552 }
1553 // Close the cell and reprocess.
1554 p.popUntil(tableScope, a.Td, a.Th)
1555 p.clearActiveFormattingElements()
1556 p.im = inRowIM
1557 return false
1558 }
1559 }
1560 return inBodyIM(p)
1561}
1562
1563// Section 12.2.5.4.16.
1564func inSelectIM(p *parser) bool {
1565 switch p.tok.Type {
1566 case ErrorToken:
1567 // Stop parsing.
1568 return true
1569 case TextToken:
1570 p.addText(strings.Replace(p.tok.Data, "\x00", "", -1))
1571 case StartTagToken:
1572 switch p.tok.DataAtom {
1573 case a.Html:
1574 return inBodyIM(p)
1575 case a.Option:
1576 if p.top().DataAtom == a.Option {
1577 p.oe.pop()
1578 }
1579 p.addElement()
1580 case a.Optgroup:
1581 if p.top().DataAtom == a.Option {
1582 p.oe.pop()
1583 }
1584 if p.top().DataAtom == a.Optgroup {
1585 p.oe.pop()
1586 }
1587 p.addElement()
1588 case a.Select:
1589 p.tok.Type = EndTagToken
1590 return false
1591 case a.Input, a.Keygen, a.Textarea:
1592 if p.elementInScope(selectScope, a.Select) {
1593 p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
1594 return false
1595 }
1596 // In order to properly ignore <textarea>, we need to change the tokenizer mode.
1597 p.tokenizer.NextIsNotRawText()
1598 // Ignore the token.
1599 return true
1600 case a.Script:
1601 return inHeadIM(p)
1602 }
1603 case EndTagToken:
1604 switch p.tok.DataAtom {
1605 case a.Option:
1606 if p.top().DataAtom == a.Option {
1607 p.oe.pop()
1608 }
1609 case a.Optgroup:
1610 i := len(p.oe) - 1
1611 if p.oe[i].DataAtom == a.Option {
1612 i--
1613 }
1614 if p.oe[i].DataAtom == a.Optgroup {
1615 p.oe = p.oe[:i]
1616 }
1617 case a.Select:
1618 if p.popUntil(selectScope, a.Select) {
1619 p.resetInsertionMode()
1620 }
1621 }
1622 case CommentToken:
1623 p.addChild(&Node{
1624 Type: CommentNode,
1625 Data: p.tok.Data,
1626 })
1627 case DoctypeToken:
1628 // Ignore the token.
1629 return true
1630 }
1631
1632 return true
1633}
1634
1635// Section 12.2.5.4.17.
1636func inSelectInTableIM(p *parser) bool {
1637 switch p.tok.Type {
1638 case StartTagToken, EndTagToken:
1639 switch p.tok.DataAtom {
1640 case a.Caption, a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr, a.Td, a.Th:
1641 if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.DataAtom) {
1642 p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
1643 return false
1644 } else {
1645 // Ignore the token.
1646 return true
1647 }
1648 }
1649 }
1650 return inSelectIM(p)
1651}
1652
1653// Section 12.2.5.4.18.
1654func afterBodyIM(p *parser) bool {
1655 switch p.tok.Type {
1656 case ErrorToken:
1657 // Stop parsing.
1658 return true
1659 case TextToken:
1660 s := strings.TrimLeft(p.tok.Data, whitespace)
1661 if len(s) == 0 {
1662 // It was all whitespace.
1663 return inBodyIM(p)
1664 }
1665 case StartTagToken:
1666 if p.tok.DataAtom == a.Html {
1667 return inBodyIM(p)
1668 }
1669 case EndTagToken:
1670 if p.tok.DataAtom == a.Html {
1671 if !p.fragment {
1672 p.im = afterAfterBodyIM
1673 }
1674 return true
1675 }
1676 case CommentToken:
1677 // The comment is attached to the <html> element.
1678 if len(p.oe) < 1 || p.oe[0].DataAtom != a.Html {
1679 panic("html: bad parser state: <html> element not found, in the after-body insertion mode")
1680 }
1681 p.oe[0].AppendChild(&Node{
1682 Type: CommentNode,
1683 Data: p.tok.Data,
1684 })
1685 return true
1686 }
1687 p.im = inBodyIM
1688 return false
1689}
1690
1691// Section 12.2.5.4.19.
1692func inFramesetIM(p *parser) bool {
1693 switch p.tok.Type {
1694 case CommentToken:
1695 p.addChild(&Node{
1696 Type: CommentNode,
1697 Data: p.tok.Data,
1698 })
1699 case TextToken:
1700 // Ignore all text but whitespace.
1701 s := strings.Map(func(c rune) rune {
1702 switch c {
1703 case ' ', '\t', '\n', '\f', '\r':
1704 return c
1705 }
1706 return -1
1707 }, p.tok.Data)
1708 if s != "" {
1709 p.addText(s)
1710 }
1711 case StartTagToken:
1712 switch p.tok.DataAtom {
1713 case a.Html:
1714 return inBodyIM(p)
1715 case a.Frameset:
1716 p.addElement()
1717 case a.Frame:
1718 p.addElement()
1719 p.oe.pop()
1720 p.acknowledgeSelfClosingTag()
1721 case a.Noframes:
1722 return inHeadIM(p)
1723 }
1724 case EndTagToken:
1725 switch p.tok.DataAtom {
1726 case a.Frameset:
1727 if p.oe.top().DataAtom != a.Html {
1728 p.oe.pop()
1729 if p.oe.top().DataAtom != a.Frameset {
1730 p.im = afterFramesetIM
1731 return true
1732 }
1733 }
1734 }
1735 default:
1736 // Ignore the token.
1737 }
1738 return true
1739}
1740
1741// Section 12.2.5.4.20.
1742func afterFramesetIM(p *parser) bool {
1743 switch p.tok.Type {
1744 case CommentToken:
1745 p.addChild(&Node{
1746 Type: CommentNode,
1747 Data: p.tok.Data,
1748 })
1749 case TextToken:
1750 // Ignore all text but whitespace.
1751 s := strings.Map(func(c rune) rune {
1752 switch c {
1753 case ' ', '\t', '\n', '\f', '\r':
1754 return c
1755 }
1756 return -1
1757 }, p.tok.Data)
1758 if s != "" {
1759 p.addText(s)
1760 }
1761 case StartTagToken:
1762 switch p.tok.DataAtom {
1763 case a.Html:
1764 return inBodyIM(p)
1765 case a.Noframes:
1766 return inHeadIM(p)
1767 }
1768 case EndTagToken:
1769 switch p.tok.DataAtom {
1770 case a.Html:
1771 p.im = afterAfterFramesetIM
1772 return true
1773 }
1774 default:
1775 // Ignore the token.
1776 }
1777 return true
1778}
1779
1780// Section 12.2.5.4.21.
1781func afterAfterBodyIM(p *parser) bool {
1782 switch p.tok.Type {
1783 case ErrorToken:
1784 // Stop parsing.
1785 return true
1786 case TextToken:
1787 s := strings.TrimLeft(p.tok.Data, whitespace)
1788 if len(s) == 0 {
1789 // It was all whitespace.
1790 return inBodyIM(p)
1791 }
1792 case StartTagToken:
1793 if p.tok.DataAtom == a.Html {
1794 return inBodyIM(p)
1795 }
1796 case CommentToken:
1797 p.doc.AppendChild(&Node{
1798 Type: CommentNode,
1799 Data: p.tok.Data,
1800 })
1801 return true
1802 case DoctypeToken:
1803 return inBodyIM(p)
1804 }
1805 p.im = inBodyIM
1806 return false
1807}
1808
1809// Section 12.2.5.4.22.
1810func afterAfterFramesetIM(p *parser) bool {
1811 switch p.tok.Type {
1812 case CommentToken:
1813 p.doc.AppendChild(&Node{
1814 Type: CommentNode,
1815 Data: p.tok.Data,
1816 })
1817 case TextToken:
1818 // Ignore all text but whitespace.
1819 s := strings.Map(func(c rune) rune {
1820 switch c {
1821 case ' ', '\t', '\n', '\f', '\r':
1822 return c
1823 }
1824 return -1
1825 }, p.tok.Data)
1826 if s != "" {
1827 p.tok.Data = s
1828 return inBodyIM(p)
1829 }
1830 case StartTagToken:
1831 switch p.tok.DataAtom {
1832 case a.Html:
1833 return inBodyIM(p)
1834 case a.Noframes:
1835 return inHeadIM(p)
1836 }
1837 case DoctypeToken:
1838 return inBodyIM(p)
1839 default:
1840 // Ignore the token.
1841 }
1842 return true
1843}
1844
1845const whitespaceOrNUL = whitespace + "\x00"
1846
1847// Section 12.2.5.5.
1848func parseForeignContent(p *parser) bool {
1849 switch p.tok.Type {
1850 case TextToken:
1851 if p.framesetOK {
1852 p.framesetOK = strings.TrimLeft(p.tok.Data, whitespaceOrNUL) == ""
1853 }
1854 p.tok.Data = strings.Replace(p.tok.Data, "\x00", "\ufffd", -1)
1855 p.addText(p.tok.Data)
1856 case CommentToken:
1857 p.addChild(&Node{
1858 Type: CommentNode,
1859 Data: p.tok.Data,
1860 })
1861 case StartTagToken:
1862 b := breakout[p.tok.Data]
1863 if p.tok.DataAtom == a.Font {
1864 loop:
1865 for _, attr := range p.tok.Attr {
1866 switch attr.Key {
1867 case "color", "face", "size":
1868 b = true
1869 break loop
1870 }
1871 }
1872 }
1873 if b {
1874 for i := len(p.oe) - 1; i >= 0; i-- {
1875 n := p.oe[i]
1876 if n.Namespace == "" || htmlIntegrationPoint(n) || mathMLTextIntegrationPoint(n) {
1877 p.oe = p.oe[:i+1]
1878 break
1879 }
1880 }
1881 return false
1882 }
1883 switch p.top().Namespace {
1884 case "math":
1885 adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
1886 case "svg":
1887 // Adjust SVG tag names. The tokenizer lower-cases tag names, but
1888 // SVG wants e.g. "foreignObject" with a capital second "O".
1889 if x := svgTagNameAdjustments[p.tok.Data]; x != "" {
1890 p.tok.DataAtom = a.Lookup([]byte(x))
1891 p.tok.Data = x
1892 }
1893 adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
1894 default:
1895 panic("html: bad parser state: unexpected namespace")
1896 }
1897 adjustForeignAttributes(p.tok.Attr)
1898 namespace := p.top().Namespace
1899 p.addElement()
1900 p.top().Namespace = namespace
1901 if namespace != "" {
1902 // Don't let the tokenizer go into raw text mode in foreign content
1903 // (e.g. in an SVG <title> tag).
1904 p.tokenizer.NextIsNotRawText()
1905 }
1906 if p.hasSelfClosingToken {
1907 p.oe.pop()
1908 p.acknowledgeSelfClosingTag()
1909 }
1910 case EndTagToken:
1911 for i := len(p.oe) - 1; i >= 0; i-- {
1912 if p.oe[i].Namespace == "" {
1913 return p.im(p)
1914 }
1915 if strings.EqualFold(p.oe[i].Data, p.tok.Data) {
1916 p.oe = p.oe[:i]
1917 break
1918 }
1919 }
1920 return true
1921 default:
1922 // Ignore the token.
1923 }
1924 return true
1925}
1926
1927// Section 12.2.5.
1928func (p *parser) inForeignContent() bool {
1929 if len(p.oe) == 0 {
1930 return false
1931 }
1932 n := p.oe[len(p.oe)-1]
1933 if n.Namespace == "" {
1934 return false
1935 }
1936 if mathMLTextIntegrationPoint(n) {
1937 if p.tok.Type == StartTagToken && p.tok.DataAtom != a.Mglyph && p.tok.DataAtom != a.Malignmark {
1938 return false
1939 }
1940 if p.tok.Type == TextToken {
1941 return false
1942 }
1943 }
1944 if n.Namespace == "math" && n.DataAtom == a.AnnotationXml && p.tok.Type == StartTagToken && p.tok.DataAtom == a.Svg {
1945 return false
1946 }
1947 if htmlIntegrationPoint(n) && (p.tok.Type == StartTagToken || p.tok.Type == TextToken) {
1948 return false
1949 }
1950 if p.tok.Type == ErrorToken {
1951 return false
1952 }
1953 return true
1954}
1955
1956// parseImpliedToken parses a token as though it had appeared in the parser's
1957// input.
1958func (p *parser) parseImpliedToken(t TokenType, dataAtom a.Atom, data string) {
1959 realToken, selfClosing := p.tok, p.hasSelfClosingToken
1960 p.tok = Token{
1961 Type: t,
1962 DataAtom: dataAtom,
1963 Data: data,
1964 }
1965 p.hasSelfClosingToken = false
1966 p.parseCurrentToken()
1967 p.tok, p.hasSelfClosingToken = realToken, selfClosing
1968}
1969
1970// parseCurrentToken runs the current token through the parsing routines
1971// until it is consumed.
1972func (p *parser) parseCurrentToken() {
1973 if p.tok.Type == SelfClosingTagToken {
1974 p.hasSelfClosingToken = true
1975 p.tok.Type = StartTagToken
1976 }
1977
1978 consumed := false
1979 for !consumed {
1980 if p.inForeignContent() {
1981 consumed = parseForeignContent(p)
1982 } else {
1983 consumed = p.im(p)
1984 }
1985 }
1986
1987 if p.hasSelfClosingToken {
1988 // This is a parse error, but ignore it.
1989 p.hasSelfClosingToken = false
1990 }
1991}
1992
1993func (p *parser) parse() error {
1994 // Iterate until EOF. Any other error will cause an early return.
1995 var err error
1996 for err != io.EOF {
1997 // CDATA sections are allowed only in foreign content.
1998 n := p.oe.top()
1999 p.tokenizer.AllowCDATA(n != nil && n.Namespace != "")
2000 // Read and parse the next token.
2001 p.tokenizer.Next()
2002 p.tok = p.tokenizer.Token()
2003 if p.tok.Type == ErrorToken {
2004 err = p.tokenizer.Err()
2005 if err != nil && err != io.EOF {
2006 return err
2007 }
2008 }
2009 p.parseCurrentToken()
2010 }
2011 return nil
2012}
2013
2014// Parse returns the parse tree for the HTML from the given Reader.
2015// The input is assumed to be UTF-8 encoded.
2016func Parse(r io.Reader) (*Node, error) {
2017 p := &parser{
2018 tokenizer: NewTokenizer(r),
2019 doc: &Node{
2020 Type: DocumentNode,
2021 },
2022 scripting: true,
2023 framesetOK: true,
2024 im: initialIM,
2025 }
2026 err := p.parse()
2027 if err != nil {
2028 return nil, err
2029 }
2030 return p.doc, nil
2031}
2032
2033// ParseFragment parses a fragment of HTML and returns the nodes that were
2034// found. If the fragment is the InnerHTML for an existing element, pass that
2035// element in context.
2036func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
2037 contextTag := ""
2038 if context != nil {
2039 if context.Type != ElementNode {
2040 return nil, errors.New("html: ParseFragment of non-element Node")
2041 }
2042 // The next check isn't just context.DataAtom.String() == context.Data because
2043 // it is valid to pass an element whose tag isn't a known atom. For example,
2044 // DataAtom == 0 and Data = "tagfromthefuture" is perfectly consistent.
2045 if context.DataAtom != a.Lookup([]byte(context.Data)) {
2046 return nil, fmt.Errorf("html: inconsistent Node: DataAtom=%q, Data=%q", context.DataAtom, context.Data)
2047 }
2048 contextTag = context.DataAtom.String()
2049 }
2050 p := &parser{
2051 tokenizer: NewTokenizerFragment(r, contextTag),
2052 doc: &Node{
2053 Type: DocumentNode,
2054 },
2055 scripting: true,
2056 fragment: true,
2057 context: context,
2058 }
2059
2060 root := &Node{
2061 Type: ElementNode,
2062 DataAtom: a.Html,
2063 Data: a.Html.String(),
2064 }
2065 p.doc.AppendChild(root)
2066 p.oe = nodeStack{root}
2067 p.resetInsertionMode()
2068
2069 for n := context; n != nil; n = n.Parent {
2070 if n.Type == ElementNode && n.DataAtom == a.Form {
2071 p.form = n
2072 break
2073 }
2074 }
2075
2076 err := p.parse()
2077 if err != nil {
2078 return nil, err
2079 }
2080
2081 parent := p.doc
2082 if context != nil {
2083 parent = root
2084 }
2085
2086 var result []*Node
2087 for c := parent.FirstChild; c != nil; {
2088 next := c.NextSibling
2089 parent.RemoveChild(c)
2090 result = append(result, c)
2091 c = next
2092 }
2093 return result, nil
2094}
diff --git a/vendor/golang.org/x/net/html/render.go b/vendor/golang.org/x/net/html/render.go
new file mode 100644
index 0000000..d34564f
--- /dev/null
+++ b/vendor/golang.org/x/net/html/render.go
@@ -0,0 +1,271 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package html
6
7import (
8 "bufio"
9 "errors"
10 "fmt"
11 "io"
12 "strings"
13)
14
15type writer interface {
16 io.Writer
17 io.ByteWriter
18 WriteString(string) (int, error)
19}
20
21// Render renders the parse tree n to the given writer.
22//
23// Rendering is done on a 'best effort' basis: calling Parse on the output of
24// Render will always result in something similar to the original tree, but it
25// is not necessarily an exact clone unless the original tree was 'well-formed'.
26// 'Well-formed' is not easily specified; the HTML5 specification is
27// complicated.
28//
29// Calling Parse on arbitrary input typically results in a 'well-formed' parse
30// tree. However, it is possible for Parse to yield a 'badly-formed' parse tree.
31// For example, in a 'well-formed' parse tree, no <a> element is a child of
32// another <a> element: parsing "<a><a>" results in two sibling elements.
33// Similarly, in a 'well-formed' parse tree, no <a> element is a child of a
34// <table> element: parsing "<p><table><a>" results in a <p> with two sibling
35// children; the <a> is reparented to the <table>'s parent. However, calling
36// Parse on "<a><table><a>" does not return an error, but the result has an <a>
37// element with an <a> child, and is therefore not 'well-formed'.
38//
39// Programmatically constructed trees are typically also 'well-formed', but it
40// is possible to construct a tree that looks innocuous but, when rendered and
41// re-parsed, results in a different tree. A simple example is that a solitary
42// text node would become a tree containing <html>, <head> and <body> elements.
43// Another example is that the programmatic equivalent of "a<head>b</head>c"
44// becomes "<html><head><head/><body>abc</body></html>".
45func Render(w io.Writer, n *Node) error {
46 if x, ok := w.(writer); ok {
47 return render(x, n)
48 }
49 buf := bufio.NewWriter(w)
50 if err := render(buf, n); err != nil {
51 return err
52 }
53 return buf.Flush()
54}
55
56// plaintextAbort is returned from render1 when a <plaintext> element
57// has been rendered. No more end tags should be rendered after that.
58var plaintextAbort = errors.New("html: internal error (plaintext abort)")
59
60func render(w writer, n *Node) error {
61 err := render1(w, n)
62 if err == plaintextAbort {
63 err = nil
64 }
65 return err
66}
67
68func render1(w writer, n *Node) error {
69 // Render non-element nodes; these are the easy cases.
70 switch n.Type {
71 case ErrorNode:
72 return errors.New("html: cannot render an ErrorNode node")
73 case TextNode:
74 return escape(w, n.Data)
75 case DocumentNode:
76 for c := n.FirstChild; c != nil; c = c.NextSibling {
77 if err := render1(w, c); err != nil {
78 return err
79 }
80 }
81 return nil
82 case ElementNode:
83 // No-op.
84 case CommentNode:
85 if _, err := w.WriteString("<!--"); err != nil {
86 return err
87 }
88 if _, err := w.WriteString(n.Data); err != nil {
89 return err
90 }
91 if _, err := w.WriteString("-->"); err != nil {
92 return err
93 }
94 return nil
95 case DoctypeNode:
96 if _, err := w.WriteString("<!DOCTYPE "); err != nil {
97 return err
98 }
99 if _, err := w.WriteString(n.Data); err != nil {
100 return err
101 }
102 if n.Attr != nil {
103 var p, s string
104 for _, a := range n.Attr {
105 switch a.Key {
106 case "public":
107 p = a.Val
108 case "system":
109 s = a.Val
110 }
111 }
112 if p != "" {
113 if _, err := w.WriteString(" PUBLIC "); err != nil {
114 return err
115 }
116 if err := writeQuoted(w, p); err != nil {
117 return err
118 }
119 if s != "" {
120 if err := w.WriteByte(' '); err != nil {
121 return err
122 }
123 if err := writeQuoted(w, s); err != nil {
124 return err
125 }
126 }
127 } else if s != "" {
128 if _, err := w.WriteString(" SYSTEM "); err != nil {
129 return err
130 }
131 if err := writeQuoted(w, s); err != nil {
132 return err
133 }
134 }
135 }
136 return w.WriteByte('>')
137 default:
138 return errors.New("html: unknown node type")
139 }
140
141 // Render the <xxx> opening tag.
142 if err := w.WriteByte('<'); err != nil {
143 return err
144 }
145 if _, err := w.WriteString(n.Data); err != nil {
146 return err
147 }
148 for _, a := range n.Attr {
149 if err := w.WriteByte(' '); err != nil {
150 return err
151 }
152 if a.Namespace != "" {
153 if _, err := w.WriteString(a.Namespace); err != nil {
154 return err
155 }
156 if err := w.WriteByte(':'); err != nil {
157 return err
158 }
159 }
160 if _, err := w.WriteString(a.Key); err != nil {
161 return err
162 }
163 if _, err := w.WriteString(`="`); err != nil {
164 return err
165 }
166 if err := escape(w, a.Val); err != nil {
167 return err
168 }
169 if err := w.WriteByte('"'); err != nil {
170 return err
171 }
172 }
173 if voidElements[n.Data] {
174 if n.FirstChild != nil {
175 return fmt.Errorf("html: void element <%s> has child nodes", n.Data)
176 }
177 _, err := w.WriteString("/>")
178 return err
179 }
180 if err := w.WriteByte('>'); err != nil {
181 return err
182 }
183
184 // Add initial newline where there is danger of a newline beging ignored.
185 if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") {
186 switch n.Data {
187 case "pre", "listing", "textarea":
188 if err := w.WriteByte('\n'); err != nil {
189 return err
190 }
191 }
192 }
193
194 // Render any child nodes.
195 switch n.Data {
196 case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp":
197 for c := n.FirstChild; c != nil; c = c.NextSibling {
198 if c.Type == TextNode {
199 if _, err := w.WriteString(c.Data); err != nil {
200 return err
201 }
202 } else {
203 if err := render1(w, c); err != nil {
204 return err
205 }
206 }
207 }
208 if n.Data == "plaintext" {
209 // Don't render anything else. <plaintext> must be the
210 // last element in the file, with no closing tag.
211 return plaintextAbort
212 }
213 default:
214 for c := n.FirstChild; c != nil; c = c.NextSibling {
215 if err := render1(w, c); err != nil {
216 return err
217 }
218 }
219 }
220
221 // Render the </xxx> closing tag.
222 if _, err := w.WriteString("</"); err != nil {
223 return err
224 }
225 if _, err := w.WriteString(n.Data); err != nil {
226 return err
227 }
228 return w.WriteByte('>')
229}
230
231// writeQuoted writes s to w surrounded by quotes. Normally it will use double
232// quotes, but if s contains a double quote, it will use single quotes.
233// It is used for writing the identifiers in a doctype declaration.
234// In valid HTML, they can't contain both types of quotes.
235func writeQuoted(w writer, s string) error {
236 var q byte = '"'
237 if strings.Contains(s, `"`) {
238 q = '\''
239 }
240 if err := w.WriteByte(q); err != nil {
241 return err
242 }
243 if _, err := w.WriteString(s); err != nil {
244 return err
245 }
246 if err := w.WriteByte(q); err != nil {
247 return err
248 }
249 return nil
250}
251
252// Section 12.1.2, "Elements", gives this list of void elements. Void elements
253// are those that can't have any contents.
254var voidElements = map[string]bool{
255 "area": true,
256 "base": true,
257 "br": true,
258 "col": true,
259 "command": true,
260 "embed": true,
261 "hr": true,
262 "img": true,
263 "input": true,
264 "keygen": true,
265 "link": true,
266 "meta": true,
267 "param": true,
268 "source": true,
269 "track": true,
270 "wbr": true,
271}
diff --git a/vendor/golang.org/x/net/html/token.go b/vendor/golang.org/x/net/html/token.go
new file mode 100644
index 0000000..893e272
--- /dev/null
+++ b/vendor/golang.org/x/net/html/token.go
@@ -0,0 +1,1219 @@
1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package html
6
7import (
8 "bytes"
9 "errors"
10 "io"
11 "strconv"
12 "strings"
13
14 "golang.org/x/net/html/atom"
15)
16
17// A TokenType is the type of a Token.
18type TokenType uint32
19
20const (
21 // ErrorToken means that an error occurred during tokenization.
22 ErrorToken TokenType = iota
23 // TextToken means a text node.
24 TextToken
25 // A StartTagToken looks like <a>.
26 StartTagToken
27 // An EndTagToken looks like </a>.
28 EndTagToken
29 // A SelfClosingTagToken tag looks like <br/>.
30 SelfClosingTagToken
31 // A CommentToken looks like <!--x-->.
32 CommentToken
33 // A DoctypeToken looks like <!DOCTYPE x>
34 DoctypeToken
35)
36
37// ErrBufferExceeded means that the buffering limit was exceeded.
38var ErrBufferExceeded = errors.New("max buffer exceeded")
39
40// String returns a string representation of the TokenType.
41func (t TokenType) String() string {
42 switch t {
43 case ErrorToken:
44 return "Error"
45 case TextToken:
46 return "Text"
47 case StartTagToken:
48 return "StartTag"
49 case EndTagToken:
50 return "EndTag"
51 case SelfClosingTagToken:
52 return "SelfClosingTag"
53 case CommentToken:
54 return "Comment"
55 case DoctypeToken:
56 return "Doctype"
57 }
58 return "Invalid(" + strconv.Itoa(int(t)) + ")"
59}
60
61// An Attribute is an attribute namespace-key-value triple. Namespace is
62// non-empty for foreign attributes like xlink, Key is alphabetic (and hence
63// does not contain escapable characters like '&', '<' or '>'), and Val is
64// unescaped (it looks like "a<b" rather than "a&lt;b").
65//
66// Namespace is only used by the parser, not the tokenizer.
67type Attribute struct {
68 Namespace, Key, Val string
69}
70
71// A Token consists of a TokenType and some Data (tag name for start and end
72// tags, content for text, comments and doctypes). A tag Token may also contain
73// a slice of Attributes. Data is unescaped for all Tokens (it looks like "a<b"
74// rather than "a&lt;b"). For tag Tokens, DataAtom is the atom for Data, or
75// zero if Data is not a known tag name.
76type Token struct {
77 Type TokenType
78 DataAtom atom.Atom
79 Data string
80 Attr []Attribute
81}
82
83// tagString returns a string representation of a tag Token's Data and Attr.
84func (t Token) tagString() string {
85 if len(t.Attr) == 0 {
86 return t.Data
87 }
88 buf := bytes.NewBufferString(t.Data)
89 for _, a := range t.Attr {
90 buf.WriteByte(' ')
91 buf.WriteString(a.Key)
92 buf.WriteString(`="`)
93 escape(buf, a.Val)
94 buf.WriteByte('"')
95 }
96 return buf.String()
97}
98
99// String returns a string representation of the Token.
100func (t Token) String() string {
101 switch t.Type {
102 case ErrorToken:
103 return ""
104 case TextToken:
105 return EscapeString(t.Data)
106 case StartTagToken:
107 return "<" + t.tagString() + ">"
108 case EndTagToken:
109 return "</" + t.tagString() + ">"
110 case SelfClosingTagToken:
111 return "<" + t.tagString() + "/>"
112 case CommentToken:
113 return "<!--" + t.Data + "-->"
114 case DoctypeToken:
115 return "<!DOCTYPE " + t.Data + ">"
116 }
117 return "Invalid(" + strconv.Itoa(int(t.Type)) + ")"
118}
119
120// span is a range of bytes in a Tokenizer's buffer. The start is inclusive,
121// the end is exclusive.
122type span struct {
123 start, end int
124}
125
126// A Tokenizer returns a stream of HTML Tokens.
127type Tokenizer struct {
128 // r is the source of the HTML text.
129 r io.Reader
130 // tt is the TokenType of the current token.
131 tt TokenType
132 // err is the first error encountered during tokenization. It is possible
133 // for tt != Error && err != nil to hold: this means that Next returned a
134 // valid token but the subsequent Next call will return an error token.
135 // For example, if the HTML text input was just "plain", then the first
136 // Next call would set z.err to io.EOF but return a TextToken, and all
137 // subsequent Next calls would return an ErrorToken.
138 // err is never reset. Once it becomes non-nil, it stays non-nil.
139 err error
140 // readErr is the error returned by the io.Reader r. It is separate from
141 // err because it is valid for an io.Reader to return (n int, err1 error)
142 // such that n > 0 && err1 != nil, and callers should always process the
143 // n > 0 bytes before considering the error err1.
144 readErr error
145 // buf[raw.start:raw.end] holds the raw bytes of the current token.
146 // buf[raw.end:] is buffered input that will yield future tokens.
147 raw span
148 buf []byte
149 // maxBuf limits the data buffered in buf. A value of 0 means unlimited.
150 maxBuf int
151 // buf[data.start:data.end] holds the raw bytes of the current token's data:
152 // a text token's text, a tag token's tag name, etc.
153 data span
154 // pendingAttr is the attribute key and value currently being tokenized.
155 // When complete, pendingAttr is pushed onto attr. nAttrReturned is
156 // incremented on each call to TagAttr.
157 pendingAttr [2]span
158 attr [][2]span
159 nAttrReturned int
160 // rawTag is the "script" in "</script>" that closes the next token. If
161 // non-empty, the subsequent call to Next will return a raw or RCDATA text
162 // token: one that treats "<p>" as text instead of an element.
163 // rawTag's contents are lower-cased.
164 rawTag string
165 // textIsRaw is whether the current text token's data is not escaped.
166 textIsRaw bool
167 // convertNUL is whether NUL bytes in the current token's data should
168 // be converted into \ufffd replacement characters.
169 convertNUL bool
170 // allowCDATA is whether CDATA sections are allowed in the current context.
171 allowCDATA bool
172}
173
174// AllowCDATA sets whether or not the tokenizer recognizes <![CDATA[foo]]> as
175// the text "foo". The default value is false, which means to recognize it as
176// a bogus comment "<!-- [CDATA[foo]] -->" instead.
177//
178// Strictly speaking, an HTML5 compliant tokenizer should allow CDATA if and
179// only if tokenizing foreign content, such as MathML and SVG. However,
180// tracking foreign-contentness is difficult to do purely in the tokenizer,
181// as opposed to the parser, due to HTML integration points: an <svg> element
182// can contain a <foreignObject> that is foreign-to-SVG but not foreign-to-
183// HTML. For strict compliance with the HTML5 tokenization algorithm, it is the
184// responsibility of the user of a tokenizer to call AllowCDATA as appropriate.
185// In practice, if using the tokenizer without caring whether MathML or SVG
186// CDATA is text or comments, such as tokenizing HTML to find all the anchor
187// text, it is acceptable to ignore this responsibility.
188func (z *Tokenizer) AllowCDATA(allowCDATA bool) {
189 z.allowCDATA = allowCDATA
190}
191
192// NextIsNotRawText instructs the tokenizer that the next token should not be
193// considered as 'raw text'. Some elements, such as script and title elements,
194// normally require the next token after the opening tag to be 'raw text' that
195// has no child elements. For example, tokenizing "<title>a<b>c</b>d</title>"
196// yields a start tag token for "<title>", a text token for "a<b>c</b>d", and
197// an end tag token for "</title>". There are no distinct start tag or end tag
198// tokens for the "<b>" and "</b>".
199//
200// This tokenizer implementation will generally look for raw text at the right
201// times. Strictly speaking, an HTML5 compliant tokenizer should not look for
202// raw text if in foreign content: <title> generally needs raw text, but a
203// <title> inside an <svg> does not. Another example is that a <textarea>
204// generally needs raw text, but a <textarea> is not allowed as an immediate
205// child of a <select>; in normal parsing, a <textarea> implies </select>, but
206// one cannot close the implicit element when parsing a <select>'s InnerHTML.
207// Similarly to AllowCDATA, tracking the correct moment to override raw-text-
208// ness is difficult to do purely in the tokenizer, as opposed to the parser.
209// For strict compliance with the HTML5 tokenization algorithm, it is the
210// responsibility of the user of a tokenizer to call NextIsNotRawText as
211// appropriate. In practice, like AllowCDATA, it is acceptable to ignore this
212// responsibility for basic usage.
213//
214// Note that this 'raw text' concept is different from the one offered by the
215// Tokenizer.Raw method.
216func (z *Tokenizer) NextIsNotRawText() {
217 z.rawTag = ""
218}
219
220// Err returns the error associated with the most recent ErrorToken token.
221// This is typically io.EOF, meaning the end of tokenization.
222func (z *Tokenizer) Err() error {
223 if z.tt != ErrorToken {
224 return nil
225 }
226 return z.err
227}
228
229// readByte returns the next byte from the input stream, doing a buffered read
230// from z.r into z.buf if necessary. z.buf[z.raw.start:z.raw.end] remains a contiguous byte
231// slice that holds all the bytes read so far for the current token.
232// It sets z.err if the underlying reader returns an error.
233// Pre-condition: z.err == nil.
234func (z *Tokenizer) readByte() byte {
235 if z.raw.end >= len(z.buf) {
236 // Our buffer is exhausted and we have to read from z.r. Check if the
237 // previous read resulted in an error.
238 if z.readErr != nil {
239 z.err = z.readErr
240 return 0
241 }
242 // We copy z.buf[z.raw.start:z.raw.end] to the beginning of z.buf. If the length
243 // z.raw.end - z.raw.start is more than half the capacity of z.buf, then we
244 // allocate a new buffer before the copy.
245 c := cap(z.buf)
246 d := z.raw.end - z.raw.start
247 var buf1 []byte
248 if 2*d > c {
249 buf1 = make([]byte, d, 2*c)
250 } else {
251 buf1 = z.buf[:d]
252 }
253 copy(buf1, z.buf[z.raw.start:z.raw.end])
254 if x := z.raw.start; x != 0 {
255 // Adjust the data/attr spans to refer to the same contents after the copy.
256 z.data.start -= x
257 z.data.end -= x
258 z.pendingAttr[0].start -= x
259 z.pendingAttr[0].end -= x
260 z.pendingAttr[1].start -= x
261 z.pendingAttr[1].end -= x
262 for i := range z.attr {
263 z.attr[i][0].start -= x
264 z.attr[i][0].end -= x
265 z.attr[i][1].start -= x
266 z.attr[i][1].end -= x
267 }
268 }
269 z.raw.start, z.raw.end, z.buf = 0, d, buf1[:d]
270 // Now that we have copied the live bytes to the start of the buffer,
271 // we read from z.r into the remainder.
272 var n int
273 n, z.readErr = readAtLeastOneByte(z.r, buf1[d:cap(buf1)])
274 if n == 0 {
275 z.err = z.readErr
276 return 0
277 }
278 z.buf = buf1[:d+n]
279 }
280 x := z.buf[z.raw.end]
281 z.raw.end++
282 if z.maxBuf > 0 && z.raw.end-z.raw.start >= z.maxBuf {
283 z.err = ErrBufferExceeded
284 return 0
285 }
286 return x
287}
288
289// Buffered returns a slice containing data buffered but not yet tokenized.
290func (z *Tokenizer) Buffered() []byte {
291 return z.buf[z.raw.end:]
292}
293
294// readAtLeastOneByte wraps an io.Reader so that reading cannot return (0, nil).
295// It returns io.ErrNoProgress if the underlying r.Read method returns (0, nil)
296// too many times in succession.
297func readAtLeastOneByte(r io.Reader, b []byte) (int, error) {
298 for i := 0; i < 100; i++ {
299 n, err := r.Read(b)
300 if n != 0 || err != nil {
301 return n, err
302 }
303 }
304 return 0, io.ErrNoProgress
305}
306
307// skipWhiteSpace skips past any white space.
308func (z *Tokenizer) skipWhiteSpace() {
309 if z.err != nil {
310 return
311 }
312 for {
313 c := z.readByte()
314 if z.err != nil {
315 return
316 }
317 switch c {
318 case ' ', '\n', '\r', '\t', '\f':
319 // No-op.
320 default:
321 z.raw.end--
322 return
323 }
324 }
325}
326
327// readRawOrRCDATA reads until the next "</foo>", where "foo" is z.rawTag and
328// is typically something like "script" or "textarea".
329func (z *Tokenizer) readRawOrRCDATA() {
330 if z.rawTag == "script" {
331 z.readScript()
332 z.textIsRaw = true
333 z.rawTag = ""
334 return
335 }
336loop:
337 for {
338 c := z.readByte()
339 if z.err != nil {
340 break loop
341 }
342 if c != '<' {
343 continue loop
344 }
345 c = z.readByte()
346 if z.err != nil {
347 break loop
348 }
349 if c != '/' {
350 continue loop
351 }
352 if z.readRawEndTag() || z.err != nil {
353 break loop
354 }
355 }
356 z.data.end = z.raw.end
357 // A textarea's or title's RCDATA can contain escaped entities.
358 z.textIsRaw = z.rawTag != "textarea" && z.rawTag != "title"
359 z.rawTag = ""
360}
361
362// readRawEndTag attempts to read a tag like "</foo>", where "foo" is z.rawTag.
363// If it succeeds, it backs up the input position to reconsume the tag and
364// returns true. Otherwise it returns false. The opening "</" has already been
365// consumed.
366func (z *Tokenizer) readRawEndTag() bool {
367 for i := 0; i < len(z.rawTag); i++ {
368 c := z.readByte()
369 if z.err != nil {
370 return false
371 }
372 if c != z.rawTag[i] && c != z.rawTag[i]-('a'-'A') {
373 z.raw.end--
374 return false
375 }
376 }
377 c := z.readByte()
378 if z.err != nil {
379 return false
380 }
381 switch c {
382 case ' ', '\n', '\r', '\t', '\f', '/', '>':
383 // The 3 is 2 for the leading "</" plus 1 for the trailing character c.
384 z.raw.end -= 3 + len(z.rawTag)
385 return true
386 }
387 z.raw.end--
388 return false
389}
390
391// readScript reads until the next </script> tag, following the byzantine
392// rules for escaping/hiding the closing tag.
393func (z *Tokenizer) readScript() {
394 defer func() {
395 z.data.end = z.raw.end
396 }()
397 var c byte
398
399scriptData:
400 c = z.readByte()
401 if z.err != nil {
402 return
403 }
404 if c == '<' {
405 goto scriptDataLessThanSign
406 }
407 goto scriptData
408
409scriptDataLessThanSign:
410 c = z.readByte()
411 if z.err != nil {
412 return
413 }
414 switch c {
415 case '/':
416 goto scriptDataEndTagOpen
417 case '!':
418 goto scriptDataEscapeStart
419 }
420 z.raw.end--
421 goto scriptData
422
423scriptDataEndTagOpen:
424 if z.readRawEndTag() || z.err != nil {
425 return
426 }
427 goto scriptData
428
429scriptDataEscapeStart:
430 c = z.readByte()
431 if z.err != nil {
432 return
433 }
434 if c == '-' {
435 goto scriptDataEscapeStartDash
436 }
437 z.raw.end--
438 goto scriptData
439
440scriptDataEscapeStartDash:
441 c = z.readByte()
442 if z.err != nil {
443 return
444 }
445 if c == '-' {
446 goto scriptDataEscapedDashDash
447 }
448 z.raw.end--
449 goto scriptData
450
451scriptDataEscaped:
452 c = z.readByte()
453 if z.err != nil {
454 return
455 }
456 switch c {
457 case '-':
458 goto scriptDataEscapedDash
459 case '<':
460 goto scriptDataEscapedLessThanSign
461 }
462 goto scriptDataEscaped
463
464scriptDataEscapedDash:
465 c = z.readByte()
466 if z.err != nil {
467 return
468 }
469 switch c {
470 case '-':
471 goto scriptDataEscapedDashDash
472 case '<':
473 goto scriptDataEscapedLessThanSign
474 }
475 goto scriptDataEscaped
476
477scriptDataEscapedDashDash:
478 c = z.readByte()
479 if z.err != nil {
480 return
481 }
482 switch c {
483 case '-':
484 goto scriptDataEscapedDashDash
485 case '<':
486 goto scriptDataEscapedLessThanSign
487 case '>':
488 goto scriptData
489 }
490 goto scriptDataEscaped
491
492scriptDataEscapedLessThanSign:
493 c = z.readByte()
494 if z.err != nil {
495 return
496 }
497 if c == '/' {
498 goto scriptDataEscapedEndTagOpen
499 }
500 if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
501 goto scriptDataDoubleEscapeStart
502 }
503 z.raw.end--
504 goto scriptData
505
506scriptDataEscapedEndTagOpen:
507 if z.readRawEndTag() || z.err != nil {
508 return
509 }
510 goto scriptDataEscaped
511
512scriptDataDoubleEscapeStart:
513 z.raw.end--
514 for i := 0; i < len("script"); i++ {
515 c = z.readByte()
516 if z.err != nil {
517 return
518 }
519 if c != "script"[i] && c != "SCRIPT"[i] {
520 z.raw.end--
521 goto scriptDataEscaped
522 }
523 }
524 c = z.readByte()
525 if z.err != nil {
526 return
527 }
528 switch c {
529 case ' ', '\n', '\r', '\t', '\f', '/', '>':
530 goto scriptDataDoubleEscaped
531 }
532 z.raw.end--
533 goto scriptDataEscaped
534
535scriptDataDoubleEscaped:
536 c = z.readByte()
537 if z.err != nil {
538 return
539 }
540 switch c {
541 case '-':
542 goto scriptDataDoubleEscapedDash
543 case '<':
544 goto scriptDataDoubleEscapedLessThanSign
545 }
546 goto scriptDataDoubleEscaped
547
548scriptDataDoubleEscapedDash:
549 c = z.readByte()
550 if z.err != nil {
551 return
552 }
553 switch c {
554 case '-':
555 goto scriptDataDoubleEscapedDashDash
556 case '<':
557 goto scriptDataDoubleEscapedLessThanSign
558 }
559 goto scriptDataDoubleEscaped
560
561scriptDataDoubleEscapedDashDash:
562 c = z.readByte()
563 if z.err != nil {
564 return
565 }
566 switch c {
567 case '-':
568 goto scriptDataDoubleEscapedDashDash
569 case '<':
570 goto scriptDataDoubleEscapedLessThanSign
571 case '>':
572 goto scriptData
573 }
574 goto scriptDataDoubleEscaped
575
576scriptDataDoubleEscapedLessThanSign:
577 c = z.readByte()
578 if z.err != nil {
579 return
580 }
581 if c == '/' {
582 goto scriptDataDoubleEscapeEnd
583 }
584 z.raw.end--
585 goto scriptDataDoubleEscaped
586
587scriptDataDoubleEscapeEnd:
588 if z.readRawEndTag() {
589 z.raw.end += len("</script>")
590 goto scriptDataEscaped
591 }
592 if z.err != nil {
593 return
594 }
595 goto scriptDataDoubleEscaped
596}
597
598// readComment reads the next comment token starting with "<!--". The opening
599// "<!--" has already been consumed.
600func (z *Tokenizer) readComment() {
601 z.data.start = z.raw.end
602 defer func() {
603 if z.data.end < z.data.start {
604 // It's a comment with no data, like <!-->.
605 z.data.end = z.data.start
606 }
607 }()
608 for dashCount := 2; ; {
609 c := z.readByte()
610 if z.err != nil {
611 // Ignore up to two dashes at EOF.
612 if dashCount > 2 {
613 dashCount = 2
614 }
615 z.data.end = z.raw.end - dashCount
616 return
617 }
618 switch c {
619 case '-':
620 dashCount++
621 continue
622 case '>':
623 if dashCount >= 2 {
624 z.data.end = z.raw.end - len("-->")
625 return
626 }
627 case '!':
628 if dashCount >= 2 {
629 c = z.readByte()
630 if z.err != nil {
631 z.data.end = z.raw.end
632 return
633 }
634 if c == '>' {
635 z.data.end = z.raw.end - len("--!>")
636 return
637 }
638 }
639 }
640 dashCount = 0
641 }
642}
643
644// readUntilCloseAngle reads until the next ">".
645func (z *Tokenizer) readUntilCloseAngle() {
646 z.data.start = z.raw.end
647 for {
648 c := z.readByte()
649 if z.err != nil {
650 z.data.end = z.raw.end
651 return
652 }
653 if c == '>' {
654 z.data.end = z.raw.end - len(">")
655 return
656 }
657 }
658}
659
660// readMarkupDeclaration reads the next token starting with "<!". It might be
661// a "<!--comment-->", a "<!DOCTYPE foo>", a "<![CDATA[section]]>" or
662// "<!a bogus comment". The opening "<!" has already been consumed.
663func (z *Tokenizer) readMarkupDeclaration() TokenType {
664 z.data.start = z.raw.end
665 var c [2]byte
666 for i := 0; i < 2; i++ {
667 c[i] = z.readByte()
668 if z.err != nil {
669 z.data.end = z.raw.end
670 return CommentToken
671 }
672 }
673 if c[0] == '-' && c[1] == '-' {
674 z.readComment()
675 return CommentToken
676 }
677 z.raw.end -= 2
678 if z.readDoctype() {
679 return DoctypeToken
680 }
681 if z.allowCDATA && z.readCDATA() {
682 z.convertNUL = true
683 return TextToken
684 }
685 // It's a bogus comment.
686 z.readUntilCloseAngle()
687 return CommentToken
688}
689
690// readDoctype attempts to read a doctype declaration and returns true if
691// successful. The opening "<!" has already been consumed.
692func (z *Tokenizer) readDoctype() bool {
693 const s = "DOCTYPE"
694 for i := 0; i < len(s); i++ {
695 c := z.readByte()
696 if z.err != nil {
697 z.data.end = z.raw.end
698 return false
699 }
700 if c != s[i] && c != s[i]+('a'-'A') {
701 // Back up to read the fragment of "DOCTYPE" again.
702 z.raw.end = z.data.start
703 return false
704 }
705 }
706 if z.skipWhiteSpace(); z.err != nil {
707 z.data.start = z.raw.end
708 z.data.end = z.raw.end
709 return true
710 }
711 z.readUntilCloseAngle()
712 return true
713}
714
715// readCDATA attempts to read a CDATA section and returns true if
716// successful. The opening "<!" has already been consumed.
717func (z *Tokenizer) readCDATA() bool {
718 const s = "[CDATA["
719 for i := 0; i < len(s); i++ {
720 c := z.readByte()
721 if z.err != nil {
722 z.data.end = z.raw.end
723 return false
724 }
725 if c != s[i] {
726 // Back up to read the fragment of "[CDATA[" again.
727 z.raw.end = z.data.start
728 return false
729 }
730 }
731 z.data.start = z.raw.end
732 brackets := 0
733 for {
734 c := z.readByte()
735 if z.err != nil {
736 z.data.end = z.raw.end
737 return true
738 }
739 switch c {
740 case ']':
741 brackets++
742 case '>':
743 if brackets >= 2 {
744 z.data.end = z.raw.end - len("]]>")
745 return true
746 }
747 brackets = 0
748 default:
749 brackets = 0
750 }
751 }
752}
753
754// startTagIn returns whether the start tag in z.buf[z.data.start:z.data.end]
755// case-insensitively matches any element of ss.
756func (z *Tokenizer) startTagIn(ss ...string) bool {
757loop:
758 for _, s := range ss {
759 if z.data.end-z.data.start != len(s) {
760 continue loop
761 }
762 for i := 0; i < len(s); i++ {
763 c := z.buf[z.data.start+i]
764 if 'A' <= c && c <= 'Z' {
765 c += 'a' - 'A'
766 }
767 if c != s[i] {
768 continue loop
769 }
770 }
771 return true
772 }
773 return false
774}
775
776// readStartTag reads the next start tag token. The opening "<a" has already
777// been consumed, where 'a' means anything in [A-Za-z].
778func (z *Tokenizer) readStartTag() TokenType {
779 z.readTag(true)
780 if z.err != nil {
781 return ErrorToken
782 }
783 // Several tags flag the tokenizer's next token as raw.
784 c, raw := z.buf[z.data.start], false
785 if 'A' <= c && c <= 'Z' {
786 c += 'a' - 'A'
787 }
788 switch c {
789 case 'i':
790 raw = z.startTagIn("iframe")
791 case 'n':
792 raw = z.startTagIn("noembed", "noframes", "noscript")
793 case 'p':
794 raw = z.startTagIn("plaintext")
795 case 's':
796 raw = z.startTagIn("script", "style")
797 case 't':
798 raw = z.startTagIn("textarea", "title")
799 case 'x':
800 raw = z.startTagIn("xmp")
801 }
802 if raw {
803 z.rawTag = strings.ToLower(string(z.buf[z.data.start:z.data.end]))
804 }
805 // Look for a self-closing token like "<br/>".
806 if z.err == nil && z.buf[z.raw.end-2] == '/' {
807 return SelfClosingTagToken
808 }
809 return StartTagToken
810}
811
812// readTag reads the next tag token and its attributes. If saveAttr, those
813// attributes are saved in z.attr, otherwise z.attr is set to an empty slice.
814// The opening "<a" or "</a" has already been consumed, where 'a' means anything
815// in [A-Za-z].
816func (z *Tokenizer) readTag(saveAttr bool) {
817 z.attr = z.attr[:0]
818 z.nAttrReturned = 0
819 // Read the tag name and attribute key/value pairs.
820 z.readTagName()
821 if z.skipWhiteSpace(); z.err != nil {
822 return
823 }
824 for {
825 c := z.readByte()
826 if z.err != nil || c == '>' {
827 break
828 }
829 z.raw.end--
830 z.readTagAttrKey()
831 z.readTagAttrVal()
832 // Save pendingAttr if saveAttr and that attribute has a non-empty key.
833 if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end {
834 z.attr = append(z.attr, z.pendingAttr)
835 }
836 if z.skipWhiteSpace(); z.err != nil {
837 break
838 }
839 }
840}
841
842// readTagName sets z.data to the "div" in "<div k=v>". The reader (z.raw.end)
843// is positioned such that the first byte of the tag name (the "d" in "<div")
844// has already been consumed.
845func (z *Tokenizer) readTagName() {
846 z.data.start = z.raw.end - 1
847 for {
848 c := z.readByte()
849 if z.err != nil {
850 z.data.end = z.raw.end
851 return
852 }
853 switch c {
854 case ' ', '\n', '\r', '\t', '\f':
855 z.data.end = z.raw.end - 1
856 return
857 case '/', '>':
858 z.raw.end--
859 z.data.end = z.raw.end
860 return
861 }
862 }
863}
864
865// readTagAttrKey sets z.pendingAttr[0] to the "k" in "<div k=v>".
866// Precondition: z.err == nil.
867func (z *Tokenizer) readTagAttrKey() {
868 z.pendingAttr[0].start = z.raw.end
869 for {
870 c := z.readByte()
871 if z.err != nil {
872 z.pendingAttr[0].end = z.raw.end
873 return
874 }
875 switch c {
876 case ' ', '\n', '\r', '\t', '\f', '/':
877 z.pendingAttr[0].end = z.raw.end - 1
878 return
879 case '=', '>':
880 z.raw.end--
881 z.pendingAttr[0].end = z.raw.end
882 return
883 }
884 }
885}
886
887// readTagAttrVal sets z.pendingAttr[1] to the "v" in "<div k=v>".
888func (z *Tokenizer) readTagAttrVal() {
889 z.pendingAttr[1].start = z.raw.end
890 z.pendingAttr[1].end = z.raw.end
891 if z.skipWhiteSpace(); z.err != nil {
892 return
893 }
894 c := z.readByte()
895 if z.err != nil {
896 return
897 }
898 if c != '=' {
899 z.raw.end--
900 return
901 }
902 if z.skipWhiteSpace(); z.err != nil {
903 return
904 }
905 quote := z.readByte()
906 if z.err != nil {
907 return
908 }
909 switch quote {
910 case '>':
911 z.raw.end--
912 return
913
914 case '\'', '"':
915 z.pendingAttr[1].start = z.raw.end
916 for {
917 c := z.readByte()
918 if z.err != nil {
919 z.pendingAttr[1].end = z.raw.end
920 return
921 }
922 if c == quote {
923 z.pendingAttr[1].end = z.raw.end - 1
924 return
925 }
926 }
927
928 default:
929 z.pendingAttr[1].start = z.raw.end - 1
930 for {
931 c := z.readByte()
932 if z.err != nil {
933 z.pendingAttr[1].end = z.raw.end
934 return
935 }
936 switch c {
937 case ' ', '\n', '\r', '\t', '\f':
938 z.pendingAttr[1].end = z.raw.end - 1
939 return
940 case '>':
941 z.raw.end--
942 z.pendingAttr[1].end = z.raw.end
943 return
944 }
945 }
946 }
947}
948
949// Next scans the next token and returns its type.
950func (z *Tokenizer) Next() TokenType {
951 z.raw.start = z.raw.end
952 z.data.start = z.raw.end
953 z.data.end = z.raw.end
954 if z.err != nil {
955 z.tt = ErrorToken
956 return z.tt
957 }
958 if z.rawTag != "" {
959 if z.rawTag == "plaintext" {
960 // Read everything up to EOF.
961 for z.err == nil {
962 z.readByte()
963 }
964 z.data.end = z.raw.end
965 z.textIsRaw = true
966 } else {
967 z.readRawOrRCDATA()
968 }
969 if z.data.end > z.data.start {
970 z.tt = TextToken
971 z.convertNUL = true
972 return z.tt
973 }
974 }
975 z.textIsRaw = false
976 z.convertNUL = false
977
978loop:
979 for {
980 c := z.readByte()
981 if z.err != nil {
982 break loop
983 }
984 if c != '<' {
985 continue loop
986 }
987
988 // Check if the '<' we have just read is part of a tag, comment
989 // or doctype. If not, it's part of the accumulated text token.
990 c = z.readByte()
991 if z.err != nil {
992 break loop
993 }
994 var tokenType TokenType
995 switch {
996 case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
997 tokenType = StartTagToken
998 case c == '/':
999 tokenType = EndTagToken
1000 case c == '!' || c == '?':
1001 // We use CommentToken to mean any of "<!--actual comments-->",
1002 // "<!DOCTYPE declarations>" and "<?xml processing instructions?>".
1003 tokenType = CommentToken
1004 default:
1005 // Reconsume the current character.
1006 z.raw.end--
1007 continue
1008 }
1009
1010 // We have a non-text token, but we might have accumulated some text
1011 // before that. If so, we return the text first, and return the non-
1012 // text token on the subsequent call to Next.
1013 if x := z.raw.end - len("<a"); z.raw.start < x {
1014 z.raw.end = x
1015 z.data.end = x
1016 z.tt = TextToken
1017 return z.tt
1018 }
1019 switch tokenType {
1020 case StartTagToken:
1021 z.tt = z.readStartTag()
1022 return z.tt
1023 case EndTagToken:
1024 c = z.readByte()
1025 if z.err != nil {
1026 break loop
1027 }
1028 if c == '>' {
1029 // "</>" does not generate a token at all. Generate an empty comment
1030 // to allow passthrough clients to pick up the data using Raw.
1031 // Reset the tokenizer state and start again.
1032 z.tt = CommentToken
1033 return z.tt
1034 }
1035 if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
1036 z.readTag(false)
1037 if z.err != nil {
1038 z.tt = ErrorToken
1039 } else {
1040 z.tt = EndTagToken
1041 }
1042 return z.tt
1043 }
1044 z.raw.end--
1045 z.readUntilCloseAngle()
1046 z.tt = CommentToken
1047 return z.tt
1048 case CommentToken:
1049 if c == '!' {
1050 z.tt = z.readMarkupDeclaration()
1051 return z.tt
1052 }
1053 z.raw.end--
1054 z.readUntilCloseAngle()
1055 z.tt = CommentToken
1056 return z.tt
1057 }
1058 }
1059 if z.raw.start < z.raw.end {
1060 z.data.end = z.raw.end
1061 z.tt = TextToken
1062 return z.tt
1063 }
1064 z.tt = ErrorToken
1065 return z.tt
1066}
1067
1068// Raw returns the unmodified text of the current token. Calling Next, Token,
1069// Text, TagName or TagAttr may change the contents of the returned slice.
1070func (z *Tokenizer) Raw() []byte {
1071 return z.buf[z.raw.start:z.raw.end]
1072}
1073
1074// convertNewlines converts "\r" and "\r\n" in s to "\n".
1075// The conversion happens in place, but the resulting slice may be shorter.
1076func convertNewlines(s []byte) []byte {
1077 for i, c := range s {
1078 if c != '\r' {
1079 continue
1080 }
1081
1082 src := i + 1
1083 if src >= len(s) || s[src] != '\n' {
1084 s[i] = '\n'
1085 continue
1086 }
1087
1088 dst := i
1089 for src < len(s) {
1090 if s[src] == '\r' {
1091 if src+1 < len(s) && s[src+1] == '\n' {
1092 src++
1093 }
1094 s[dst] = '\n'
1095 } else {
1096 s[dst] = s[src]
1097 }
1098 src++
1099 dst++
1100 }
1101 return s[:dst]
1102 }
1103 return s
1104}
1105
1106var (
1107 nul = []byte("\x00")
1108 replacement = []byte("\ufffd")
1109)
1110
1111// Text returns the unescaped text of a text, comment or doctype token. The
1112// contents of the returned slice may change on the next call to Next.
1113func (z *Tokenizer) Text() []byte {
1114 switch z.tt {
1115 case TextToken, CommentToken, DoctypeToken:
1116 s := z.buf[z.data.start:z.data.end]
1117 z.data.start = z.raw.end
1118 z.data.end = z.raw.end
1119 s = convertNewlines(s)
1120 if (z.convertNUL || z.tt == CommentToken) && bytes.Contains(s, nul) {
1121 s = bytes.Replace(s, nul, replacement, -1)
1122 }
1123 if !z.textIsRaw {
1124 s = unescape(s, false)
1125 }
1126 return s
1127 }
1128 return nil
1129}
1130
1131// TagName returns the lower-cased name of a tag token (the `img` out of
1132// `<IMG SRC="foo">`) and whether the tag has attributes.
1133// The contents of the returned slice may change on the next call to Next.
1134func (z *Tokenizer) TagName() (name []byte, hasAttr bool) {
1135 if z.data.start < z.data.end {
1136 switch z.tt {
1137 case StartTagToken, EndTagToken, SelfClosingTagToken:
1138 s := z.buf[z.data.start:z.data.end]
1139 z.data.start = z.raw.end
1140 z.data.end = z.raw.end
1141 return lower(s), z.nAttrReturned < len(z.attr)
1142 }
1143 }
1144 return nil, false
1145}
1146
1147// TagAttr returns the lower-cased key and unescaped value of the next unparsed
1148// attribute for the current tag token and whether there are more attributes.
1149// The contents of the returned slices may change on the next call to Next.
1150func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) {
1151 if z.nAttrReturned < len(z.attr) {
1152 switch z.tt {
1153 case StartTagToken, SelfClosingTagToken:
1154 x := z.attr[z.nAttrReturned]
1155 z.nAttrReturned++
1156 key = z.buf[x[0].start:x[0].end]
1157 val = z.buf[x[1].start:x[1].end]
1158 return lower(key), unescape(convertNewlines(val), true), z.nAttrReturned < len(z.attr)
1159 }
1160 }
1161 return nil, nil, false
1162}
1163
1164// Token returns the next Token. The result's Data and Attr values remain valid
1165// after subsequent Next calls.
1166func (z *Tokenizer) Token() Token {
1167 t := Token{Type: z.tt}
1168 switch z.tt {
1169 case TextToken, CommentToken, DoctypeToken:
1170 t.Data = string(z.Text())
1171 case StartTagToken, SelfClosingTagToken, EndTagToken:
1172 name, moreAttr := z.TagName()
1173 for moreAttr {
1174 var key, val []byte
1175 key, val, moreAttr = z.TagAttr()
1176 t.Attr = append(t.Attr, Attribute{"", atom.String(key), string(val)})
1177 }
1178 if a := atom.Lookup(name); a != 0 {
1179 t.DataAtom, t.Data = a, a.String()
1180 } else {
1181 t.DataAtom, t.Data = 0, string(name)
1182 }
1183 }
1184 return t
1185}
1186
1187// SetMaxBuf sets a limit on the amount of data buffered during tokenization.
1188// A value of 0 means unlimited.
1189func (z *Tokenizer) SetMaxBuf(n int) {
1190 z.maxBuf = n
1191}
1192
1193// NewTokenizer returns a new HTML Tokenizer for the given Reader.
1194// The input is assumed to be UTF-8 encoded.
1195func NewTokenizer(r io.Reader) *Tokenizer {
1196 return NewTokenizerFragment(r, "")
1197}
1198
1199// NewTokenizerFragment returns a new HTML Tokenizer for the given Reader, for
1200// tokenizing an existing element's InnerHTML fragment. contextTag is that
1201// element's tag, such as "div" or "iframe".
1202//
1203// For example, how the InnerHTML "a<b" is tokenized depends on whether it is
1204// for a <p> tag or a <script> tag.
1205//
1206// The input is assumed to be UTF-8 encoded.
1207func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer {
1208 z := &Tokenizer{
1209 r: r,
1210 buf: make([]byte, 0, 4096),
1211 }
1212 if contextTag != "" {
1213 switch s := strings.ToLower(contextTag); s {
1214 case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "title", "textarea", "xmp":
1215 z.rawTag = s
1216 }
1217 }
1218 return z
1219}
diff --git a/vendor/vendor.json b/vendor/vendor.json
index 9a3f454..8b44fbd 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -1,6 +1,6 @@
1{ 1{
2 "comment": "", 2 "comment": "",
3 "ignore": "appengine test github.com/hashicorp/nomad/", 3 "ignore": "appengine test github.com/hashicorp/nomad/ github.com/hashicorp/terraform/backend",
4 "package": [ 4 "package": [
5 { 5 {
6 "checksumSHA1": "MV5JueYPwNkLZ+KNqmDcNDhsKi4=", 6 "checksumSHA1": "MV5JueYPwNkLZ+KNqmDcNDhsKi4=",
@@ -227,6 +227,12 @@
227 "revisionTime": "2014-04-22T17:41:19Z" 227 "revisionTime": "2014-04-22T17:41:19Z"
228 }, 228 },
229 { 229 {
230 "checksumSHA1": "OT4XN9z5k69e2RsMSpwW74B+yk4=",
231 "path": "github.com/blang/semver",
232 "revision": "2ee87856327ba09384cabd113bc6b5d174e9ec0f",
233 "revisionTime": "2017-07-27T06:48:18Z"
234 },
235 {
230 "checksumSHA1": "dvabztWVQX8f6oMLRyv4dLH+TGY=", 236 "checksumSHA1": "dvabztWVQX8f6oMLRyv4dLH+TGY=",
231 "path": "github.com/davecgh/go-spew/spew", 237 "path": "github.com/davecgh/go-spew/spew",
232 "revision": "346938d642f2ec3594ed81d874461961cd0faa76", 238 "revision": "346938d642f2ec3594ed81d874461961cd0faa76",
@@ -252,6 +258,12 @@
252 "revision": "7554cd9344cec97297fa6649b055a8c98c2a1e55" 258 "revision": "7554cd9344cec97297fa6649b055a8c98c2a1e55"
253 }, 259 },
254 { 260 {
261 "checksumSHA1": "b8F628srIitj5p7Y130xc9k0QWs=",
262 "path": "github.com/hashicorp/go-cleanhttp",
263 "revision": "3573b8b52aa7b37b9358d966a898feb387f62437",
264 "revisionTime": "2017-02-11T01:34:15Z"
265 },
266 {
255 "checksumSHA1": "nsL2kI426RMuq1jw15e7igFqdIY=", 267 "checksumSHA1": "nsL2kI426RMuq1jw15e7igFqdIY=",
256 "path": "github.com/hashicorp/go-getter", 268 "path": "github.com/hashicorp/go-getter",
257 "revision": "c3d66e76678dce180a7b452653472f949aedfbcd", 269 "revision": "c3d66e76678dce180a7b452653472f949aedfbcd",
@@ -370,116 +382,130 @@
370 "revisionTime": "2015-06-09T07:04:31Z" 382 "revisionTime": "2015-06-09T07:04:31Z"
371 }, 383 },
372 { 384 {
373 "checksumSHA1": "BcxYPk5ME2ZyrHS1yK7gK9mzS1A=", 385 "checksumSHA1": "KPrCMDPNcLmO7K6xPcJSl86LwPk=",
374 "path": "github.com/hashicorp/terraform/config", 386 "path": "github.com/hashicorp/terraform/config",
375 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 387 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
376 "revisionTime": "2017-06-08T00:14:54Z", 388 "revisionTime": "2017-08-02T18:39:14Z",
377 "version": "v0.9.8", 389 "version": "v0.10.0",
378 "versionExact": "v0.9.8" 390 "versionExact": "v0.10.0"
379 }, 391 },
380 { 392 {
381 "checksumSHA1": "YiREjXkb7CDMZuUmkPGK0yySe8A=", 393 "checksumSHA1": "uPCJ6seQo9kvoNSfwNWKX9KzVMk=",
382 "path": "github.com/hashicorp/terraform/config/module", 394 "path": "github.com/hashicorp/terraform/config/module",
383 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 395 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
384 "revisionTime": "2017-06-08T00:14:54Z", 396 "revisionTime": "2017-08-02T18:39:14Z",
385 "version": "v0.9.8", 397 "version": "v0.10.0",
386 "versionExact": "v0.9.8" 398 "versionExact": "v0.10.0"
387 }, 399 },
388 { 400 {
389 "checksumSHA1": "w+l+UGTmwYNJ+L0p2vTd6+yqjok=", 401 "checksumSHA1": "w+l+UGTmwYNJ+L0p2vTd6+yqjok=",
390 "path": "github.com/hashicorp/terraform/dag", 402 "path": "github.com/hashicorp/terraform/dag",
391 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 403 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
392 "revisionTime": "2017-06-08T00:14:54Z", 404 "revisionTime": "2017-08-02T18:39:14Z",
393 "version": "v0.9.8", 405 "version": "v0.10.0",
394 "versionExact": "v0.9.8" 406 "versionExact": "v0.10.0"
395 }, 407 },
396 { 408 {
397 "checksumSHA1": "p4y7tbu9KD/3cKQKe92I3DyjgRc=", 409 "checksumSHA1": "P8gNPDuOzmiK4Lz9xG7OBy4Rlm8=",
398 "path": "github.com/hashicorp/terraform/flatmap", 410 "path": "github.com/hashicorp/terraform/flatmap",
399 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 411 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
400 "revisionTime": "2017-06-08T00:14:54Z", 412 "revisionTime": "2017-08-02T18:39:14Z",
401 "version": "v0.9.8", 413 "version": "v0.10.0",
402 "versionExact": "v0.9.8" 414 "versionExact": "v0.10.0"
403 }, 415 },
404 { 416 {
405 "checksumSHA1": "uT6Q9RdSRAkDjyUgQlJ2XKJRab4=", 417 "checksumSHA1": "uT6Q9RdSRAkDjyUgQlJ2XKJRab4=",
406 "path": "github.com/hashicorp/terraform/helper/config", 418 "path": "github.com/hashicorp/terraform/helper/config",
407 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 419 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
408 "revisionTime": "2017-06-08T00:14:54Z", 420 "revisionTime": "2017-08-02T18:39:14Z",
409 "version": "v0.9.8", 421 "version": "v0.10.0",
410 "versionExact": "v0.9.8" 422 "versionExact": "v0.10.0"
411 }, 423 },
412 { 424 {
413 "checksumSHA1": "Vbo55GDzPgG/L/+W2pcvDhxrPZc=", 425 "checksumSHA1": "Vbo55GDzPgG/L/+W2pcvDhxrPZc=",
414 "path": "github.com/hashicorp/terraform/helper/experiment", 426 "path": "github.com/hashicorp/terraform/helper/experiment",
415 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 427 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
416 "revisionTime": "2017-06-08T00:14:54Z", 428 "revisionTime": "2017-08-02T18:39:14Z",
417 "version": "v0.9.8", 429 "version": "v0.10.0",
418 "versionExact": "v0.9.8" 430 "versionExact": "v0.10.0"
419 }, 431 },
420 { 432 {
421 "checksumSHA1": "BmIPKTr0zDutSJdyq7pYXrK1I3E=", 433 "checksumSHA1": "BmIPKTr0zDutSJdyq7pYXrK1I3E=",
422 "path": "github.com/hashicorp/terraform/helper/hashcode", 434 "path": "github.com/hashicorp/terraform/helper/hashcode",
423 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 435 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
424 "revisionTime": "2017-06-08T00:14:54Z", 436 "revisionTime": "2017-08-02T18:39:14Z",
425 "version": "v0.9.8", 437 "version": "v0.10.0",
426 "versionExact": "v0.9.8" 438 "versionExact": "v0.10.0"
427 }, 439 },
428 { 440 {
429 "checksumSHA1": "B267stWNQd0/pBTXHfI/tJsxzfc=", 441 "checksumSHA1": "B267stWNQd0/pBTXHfI/tJsxzfc=",
430 "path": "github.com/hashicorp/terraform/helper/hilmapstructure", 442 "path": "github.com/hashicorp/terraform/helper/hilmapstructure",
431 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 443 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
432 "revisionTime": "2017-06-08T00:14:54Z", 444 "revisionTime": "2017-08-02T18:39:14Z",
433 "version": "v0.9.8", 445 "version": "v0.10.0",
434 "versionExact": "v0.9.8" 446 "versionExact": "v0.10.0"
435 }, 447 },
436 { 448 {
437 "checksumSHA1": "2wJa9F3BGlbe2DNqH5lb5POayRI=", 449 "checksumSHA1": "2wJa9F3BGlbe2DNqH5lb5POayRI=",
438 "path": "github.com/hashicorp/terraform/helper/logging", 450 "path": "github.com/hashicorp/terraform/helper/logging",
439 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 451 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
440 "revisionTime": "2017-06-08T00:14:54Z", 452 "revisionTime": "2017-08-02T18:39:14Z",
441 "version": "v0.9.8", 453 "version": "v0.10.0",
442 "versionExact": "v0.9.8" 454 "versionExact": "v0.10.0"
443 }, 455 },
444 { 456 {
445 "checksumSHA1": "8VL90fHe5YRasHcZwv2q2qms/Jo=", 457 "checksumSHA1": "dhU2woQaSEI2OnbYLdkHxf7/nu8=",
446 "path": "github.com/hashicorp/terraform/helper/resource", 458 "path": "github.com/hashicorp/terraform/helper/resource",
447 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 459 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
448 "revisionTime": "2017-06-08T00:14:54Z", 460 "revisionTime": "2017-08-02T18:39:14Z",
449 "version": "v0.9.8", 461 "version": "v0.10.0",
450 "versionExact": "v0.9.8" 462 "versionExact": "v0.10.0"
451 }, 463 },
452 { 464 {
453 "checksumSHA1": "bgaeB6ivKIK5H+7JCsp7w8aAdAg=", 465 "checksumSHA1": "0smlb90amL15c/6nWtW4DV6Lqh8=",
454 "path": "github.com/hashicorp/terraform/helper/schema", 466 "path": "github.com/hashicorp/terraform/helper/schema",
455 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 467 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
456 "revisionTime": "2017-06-08T00:14:54Z", 468 "revisionTime": "2017-08-02T18:39:14Z",
457 "version": "v0.9.8", 469 "version": "v0.10.0",
458 "versionExact": "v0.9.8" 470 "versionExact": "v0.10.0"
459 }, 471 },
460 { 472 {
461 "checksumSHA1": "oLui7dYxhzfAczwwdNZDm4tzHtk=", 473 "checksumSHA1": "1yCGh/Wl4H4ODBBRmIRFcV025b0=",
462 "path": "github.com/hashicorp/terraform/helper/shadow", 474 "path": "github.com/hashicorp/terraform/helper/shadow",
463 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 475 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
464 "revisionTime": "2017-06-08T00:14:54Z", 476 "revisionTime": "2017-08-02T18:39:14Z",
465 "version": "v0.9.8", 477 "version": "v0.10.0",
466 "versionExact": "v0.9.8" 478 "versionExact": "v0.10.0"
467 }, 479 },
468 { 480 {
469 "checksumSHA1": "6AA7ZAzswfl7SOzleP6e6he0lq4=", 481 "checksumSHA1": "yFWmdS6yEJZpRJzUqd/mULqCYGk=",
482 "path": "github.com/hashicorp/terraform/moduledeps",
483 "revision": "5bcc1bae5925f44208a83279b6d4d250da01597b",
484 "revisionTime": "2017-08-09T21:54:59Z"
485 },
486 {
487 "checksumSHA1": "4ODNVUds3lyBf7gV02X1EeYR4GA=",
470 "path": "github.com/hashicorp/terraform/plugin", 488 "path": "github.com/hashicorp/terraform/plugin",
471 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 489 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
472 "revisionTime": "2017-06-08T00:14:54Z", 490 "revisionTime": "2017-08-02T18:39:14Z",
473 "version": "v0.9.8", 491 "version": "v0.10.0",
474 "versionExact": "v0.9.8" 492 "versionExact": "v0.10.0"
475 }, 493 },
476 { 494 {
477 "checksumSHA1": "GfGSXndpVIh9sSeNf+b1TjxBEpQ=", 495 "checksumSHA1": "mujz3BDg1X82ynvJncCFUT6/7XI=",
496 "path": "github.com/hashicorp/terraform/plugin/discovery",
497 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
498 "revisionTime": "2017-08-02T18:39:14Z",
499 "version": "v0.10.0",
500 "versionExact": "v0.10.0"
501 },
502 {
503 "checksumSHA1": "ksfNQjZs/6llziARojABd6iuvdw=",
478 "path": "github.com/hashicorp/terraform/terraform", 504 "path": "github.com/hashicorp/terraform/terraform",
479 "revision": "8d560482c34e865458fd884cb0790b4f73f09ad1", 505 "revision": "2041053ee9444fa8175a298093b55a89586a1823",
480 "revisionTime": "2017-06-08T00:14:54Z", 506 "revisionTime": "2017-08-02T18:39:14Z",
481 "version": "v0.9.8", 507 "version": "v0.10.0",
482 "versionExact": "v0.9.8" 508 "versionExact": "v0.10.0"
483 }, 509 },
484 { 510 {
485 "checksumSHA1": "ZhK6IO2XN81Y+3RAjTcVm1Ic7oU=", 511 "checksumSHA1": "ZhK6IO2XN81Y+3RAjTcVm1Ic7oU=",
@@ -548,6 +574,60 @@
548 "revisionTime": "2016-10-31T15:37:30Z" 574 "revisionTime": "2016-10-31T15:37:30Z"
549 }, 575 },
550 { 576 {
577 "checksumSHA1": "TT1rac6kpQp2vz24m5yDGUNQ/QQ=",
578 "path": "golang.org/x/crypto/cast5",
579 "revision": "b176d7def5d71bdd214203491f89843ed217f420",
580 "revisionTime": "2017-07-23T04:49:35Z"
581 },
582 {
583 "checksumSHA1": "IIhFTrLlmlc6lEFSitqi4aw2lw0=",
584 "path": "golang.org/x/crypto/openpgp",
585 "revision": "b176d7def5d71bdd214203491f89843ed217f420",
586 "revisionTime": "2017-07-23T04:49:35Z"
587 },
588 {
589 "checksumSHA1": "olOKkhrdkYQHZ0lf1orrFQPQrv4=",
590 "path": "golang.org/x/crypto/openpgp/armor",
591 "revision": "b176d7def5d71bdd214203491f89843ed217f420",
592 "revisionTime": "2017-07-23T04:49:35Z"
593 },
594 {
595 "checksumSHA1": "eo/KtdjieJQXH7Qy+faXFcF70ME=",
596 "path": "golang.org/x/crypto/openpgp/elgamal",
597 "revision": "b176d7def5d71bdd214203491f89843ed217f420",
598 "revisionTime": "2017-07-23T04:49:35Z"
599 },
600 {
601 "checksumSHA1": "rlxVSaGgqdAgwblsErxTxIfuGfg=",
602 "path": "golang.org/x/crypto/openpgp/errors",
603 "revision": "b176d7def5d71bdd214203491f89843ed217f420",
604 "revisionTime": "2017-07-23T04:49:35Z"
605 },
606 {
607 "checksumSHA1": "Pq88+Dgh04UdXWZN6P+bLgYnbRc=",
608 "path": "golang.org/x/crypto/openpgp/packet",
609 "revision": "b176d7def5d71bdd214203491f89843ed217f420",
610 "revisionTime": "2017-07-23T04:49:35Z"
611 },
612 {
613 "checksumSHA1": "s2qT4UwvzBSkzXuiuMkowif1Olw=",
614 "path": "golang.org/x/crypto/openpgp/s2k",
615 "revision": "b176d7def5d71bdd214203491f89843ed217f420",
616 "revisionTime": "2017-07-23T04:49:35Z"
617 },
618 {
619 "checksumSHA1": "vqc3a+oTUGX8PmD0TS+qQ7gmN8I=",
620 "path": "golang.org/x/net/html",
621 "revision": "1c05540f6879653db88113bc4a2b70aec4bd491f",
622 "revisionTime": "2017-08-04T00:04:37Z"
623 },
624 {
625 "checksumSHA1": "z79z5msRzgU48FCZxSuxfU8b4rs=",
626 "path": "golang.org/x/net/html/atom",
627 "revision": "1c05540f6879653db88113bc4a2b70aec4bd491f",
628 "revisionTime": "2017-08-04T00:04:37Z"
629 },
630 {
551 "checksumSHA1": "wICWAGQfZcHD2y0dHesz9R2YSiw=", 631 "checksumSHA1": "wICWAGQfZcHD2y0dHesz9R2YSiw=",
552 "path": "k8s.io/kubernetes/pkg/apimachinery", 632 "path": "k8s.io/kubernetes/pkg/apimachinery",
553 "revision": "b0b7a323cc5a4a2019b2e9520c21c7830b7f708e", 633 "revision": "b0b7a323cc5a4a2019b2e9520c21c7830b7f708e",