10 "golang.org/x/net/html"
13 // ErrUnknownVersion is the error returned when the first character inside the
14 // element encoding (but outside the base64 encoding) is not '0'.
15 type ErrUnknownVersion
byte
17 func (err ErrUnknownVersion
) Error() string {
18 return fmt
.Sprintf("unknown armor version indicator %+q", byte(err
))
21 func isASCIIWhitespace(b
byte) bool {
23 // https://infra.spec.whatwg.org/#ascii-whitespace
24 case '\x09', '\x0a', '\x0c', '\x0d', '\x20':
31 func splitASCIIWhitespace(data
[]byte, atEOF
bool) (advance
int, token
[]byte, err error
) {
33 // Skip initial whitespace.
34 for i
= 0; i
< len(data
); i
++ {
35 if !isASCIIWhitespace(data
[i
]) {
39 // Look for next whitespace.
40 for j
= i
; j
< len(data
); j
++ {
41 if isASCIIWhitespace(data
[j
]) {
42 return j
+ 1, data
[i
:j
], nil
45 // We reached the end of data without finding more whitespace. Only
46 // consider it a token if we are at EOF.
48 return j
, data
[i
:j
], nil
50 // Otherwise, request more data.
54 func decodeToWriter(w io
.Writer
, r io
.Reader
) (int64, error
) {
55 tokenizer
:= html
.NewTokenizer(r
)
56 // Set a memory limit on token sizes, otherwise the tokenizer will
57 // buffer text indefinitely if it is not broken up by other token types.
58 tokenizer
.SetMaxBuf(elementSizeLimit
)
62 tt
:= tokenizer
.Next()
65 err
:= tokenizer
.Err()
69 if err
== nil && active
{
70 return total
, fmt
.Errorf("missing </pre> tag")
75 // Re-join the separate chunks of text and
76 // feed them to the decoder.
77 scanner
:= bufio
.NewScanner(bytes
.NewReader(tokenizer
.Text()))
78 scanner
.Split(splitASCIIWhitespace
)
80 n
, err
:= w
.Write(scanner
.Bytes())
86 if err
:= scanner
.Err(); err
!= nil {
90 case html
.StartTagToken
:
91 tn
, _
:= tokenizer
.TagName()
92 if string(tn
) == "pre" {
94 // nesting not allowed
95 return total
, fmt
.Errorf("unexpected %s", tokenizer
.Token())
99 case html
.EndTagToken
:
100 tn
, _
:= tokenizer
.TagName()
101 if string(tn
) == "pre" {
104 return total
, fmt
.Errorf("unexpected %s", tokenizer
.Token())
112 // NewDecoder returns a new AMP armor decoder.
113 func NewDecoder(r io
.Reader
) (io
.Reader
, error
) {
116 _
, err
:= decodeToWriter(pw
, r
)
117 pw
.CloseWithError(err
)
120 // The first byte inside the element encoding is a server–client
121 // protocol version indicator.
123 _
, err
:= pr
.Read(version
[:])
125 pr
.CloseWithError(err
)
130 return base64
.NewDecoder(base64
.StdEncoding
, pr
), nil
132 err
:= ErrUnknownVersion(version
[0])
133 pr
.CloseWithError(err
)