aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/google/safehtml
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2025-01-22 16:07:17 +0100
committerTaras Madan <tarasmadan@google.com>2025-01-23 10:42:36 +0000
commit7b4377ad9d8a7205416df8d6217ef2b010f89481 (patch)
treee6fec4fd12ff807a16d847923f501075bf71d16c /vendor/github.com/google/safehtml
parent475a4c203afb8b7d3af51c4fd32bb170ff32a45e (diff)
vendor: delete
Diffstat (limited to 'vendor/github.com/google/safehtml')
-rw-r--r--vendor/github.com/google/safehtml/CONTRIBUTING.md29
-rw-r--r--vendor/github.com/google/safehtml/LICENSE27
-rw-r--r--vendor/github.com/google/safehtml/README.md17
-rw-r--r--vendor/github.com/google/safehtml/doc.go11
-rw-r--r--vendor/github.com/google/safehtml/html.go117
-rw-r--r--vendor/github.com/google/safehtml/identifier.go83
-rw-r--r--vendor/github.com/google/safehtml/init.go58
-rw-r--r--vendor/github.com/google/safehtml/internal/raw/raw.go31
-rw-r--r--vendor/github.com/google/safehtml/internal/safehtmlutil/safehtmlutil.go180
-rw-r--r--vendor/github.com/google/safehtml/internal/template/raw/raw.go16
-rw-r--r--vendor/github.com/google/safehtml/script.go90
-rw-r--r--vendor/github.com/google/safehtml/style.go304
-rw-r--r--vendor/github.com/google/safehtml/stylesheet.go111
-rw-r--r--vendor/github.com/google/safehtml/template/context.go183
-rw-r--r--vendor/github.com/google/safehtml/template/delim_string.go16
-rw-r--r--vendor/github.com/google/safehtml/template/doc.go291
-rw-r--r--vendor/github.com/google/safehtml/template/error.go280
-rw-r--r--vendor/github.com/google/safehtml/template/escape.go884
-rw-r--r--vendor/github.com/google/safehtml/template/init.go28
-rw-r--r--vendor/github.com/google/safehtml/template/sanitize.go258
-rw-r--r--vendor/github.com/google/safehtml/template/sanitizers.go599
-rw-r--r--vendor/github.com/google/safehtml/template/state_string.go16
-rw-r--r--vendor/github.com/google/safehtml/template/template.go651
-rw-r--r--vendor/github.com/google/safehtml/template/transition.go312
-rw-r--r--vendor/github.com/google/safehtml/template/trustedfs.go98
-rw-r--r--vendor/github.com/google/safehtml/template/trustedsource.go105
-rw-r--r--vendor/github.com/google/safehtml/template/trustedtemplate.go36
-rw-r--r--vendor/github.com/google/safehtml/template/url.go122
-rw-r--r--vendor/github.com/google/safehtml/trustedresourceurl.go195
-rw-r--r--vendor/github.com/google/safehtml/uncheckedconversions/uncheckedconversions.go131
-rw-r--r--vendor/github.com/google/safehtml/url.go127
-rw-r--r--vendor/github.com/google/safehtml/urlset.go167
32 files changed, 0 insertions, 5573 deletions
diff --git a/vendor/github.com/google/safehtml/CONTRIBUTING.md b/vendor/github.com/google/safehtml/CONTRIBUTING.md
deleted file mode 100644
index 22b241cb7..000000000
--- a/vendor/github.com/google/safehtml/CONTRIBUTING.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# How to Contribute
-
-We'd love to accept your patches and contributions to this project. There are
-just a few small guidelines you need to follow.
-
-## Contributor License Agreement
-
-Contributions to this project must be accompanied by a Contributor License
-Agreement (CLA). You (or your employer) retain the copyright to your
-contribution; this simply gives us permission to use and redistribute your
-contributions as part of the project. Head over to
-<https://cla.developers.google.com/> to see your current agreements on file or
-to sign a new one.
-
-You generally only need to submit a CLA once, so if you've already submitted one
-(even if it was for a different project), you probably don't need to do it
-again.
-
-## Code reviews
-
-All submissions, including submissions by project members, require review. We
-use GitHub pull requests for this purpose. Consult
-[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
-information on using pull requests.
-
-## Community Guidelines
-
-This project follows
-[Google's Open Source Community Guidelines](https://opensource.google/conduct/).
diff --git a/vendor/github.com/google/safehtml/LICENSE b/vendor/github.com/google/safehtml/LICENSE
deleted file mode 100644
index dec93b16e..000000000
--- a/vendor/github.com/google/safehtml/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-Copyright (c) 2017 The Go Authors. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google LLC nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/vendor/github.com/google/safehtml/README.md b/vendor/github.com/google/safehtml/README.md
deleted file mode 100644
index d3c9676d1..000000000
--- a/vendor/github.com/google/safehtml/README.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Safe HTML for Go
-
-`safehtml` provides immutable string-like types that wrap web types such as
-HTML, JavaScript and CSS. These wrappers are safe by construction against XSS
-and similar web vulnerabilities, and they can only be interpolated in safe ways.
-You can read more about our approach to web security in our
-[whitepaper](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/42934.pdf),
-or this [OWASP talk](https://www.youtube.com/watch?v=ccfEu-Jj0as).
-
-Additional subpackages provide APIs for managing exceptions to the
-safety rules, and a template engine with a syntax and interface that closely
-matches [`html/template`](https://golang.org/pkg/html/template/). You can refer
-to the [godoc](https://pkg.go.dev/github.com/google/safehtml?tab=doc)
-for each (sub)package for the API documentation and code examples.
-More end-to-end demos are available in `example_test.go`.
-
-This is not an officially supported Google product.
diff --git a/vendor/github.com/google/safehtml/doc.go b/vendor/github.com/google/safehtml/doc.go
deleted file mode 100644
index 4c5c1bf78..000000000
--- a/vendor/github.com/google/safehtml/doc.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-// Package safehtml provides immutable string-like types which represent values that
-// are guaranteed to be safe, by construction or by escaping or sanitization, to use
-// in various HTML contexts and with various DOM APIs.
-//
-package safehtml
diff --git a/vendor/github.com/google/safehtml/html.go b/vendor/github.com/google/safehtml/html.go
deleted file mode 100644
index 27c0f337d..000000000
--- a/vendor/github.com/google/safehtml/html.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package safehtml
-
-import (
- "bytes"
- "html"
- "unicode"
-
- "golang.org/x/text/unicode/rangetable"
-)
-
-// An HTML is an immutable string-like type that is safe to use in HTML
-// contexts in DOM APIs and HTML documents.
-//
-// HTML guarantees that its value as a string will not cause untrusted script
-// execution when evaluated as HTML in a browser.
-//
-// Values of this type are guaranteed to be safe to use in HTML contexts,
-// such as assignment to the innerHTML DOM property, or interpolation into an
-// HTML template in HTML PC_DATA context, in the sense that the use will not
-// result in a Cross-site Scripting (XSS) vulnerability.
-type HTML struct {
- // We declare an HTML not as a string but as a struct wrapping a string
- // to prevent construction of HTML values through string conversion.
- str string
-}
-
-// HTMLer is implemented by any value that has an HTML method, which defines the
-// safe HTML format for that value.
-type HTMLer interface {
- HTML() HTML
-}
-
-// HTMLEscaped returns an HTML whose value is text, with the characters [&<>"'] escaped.
-//
-// text is coerced to interchange valid, so the resulting HTML contains only
-// valid UTF-8 characters which are legal in HTML and XML.
-//
-func HTMLEscaped(text string) HTML {
- return HTML{escapeAndCoerceToInterchangeValid(text)}
-}
-
-// HTMLConcat returns an HTML which contains, in order, the string representations
-// of the given htmls.
-func HTMLConcat(htmls ...HTML) HTML {
- var b bytes.Buffer
- for _, html := range htmls {
- b.WriteString(html.String())
- }
- return HTML{b.String()}
-}
-
-// String returns the string form of the HTML.
-func (h HTML) String() string {
- return h.str
-}
-
-// escapeAndCoerceToInterchangeValid coerces the string to interchange-valid
-// UTF-8 and then HTML-escapes it.
-func escapeAndCoerceToInterchangeValid(str string) string {
- return html.EscapeString(coerceToUTF8InterchangeValid(str))
-}
-
-// coerceToUTF8InterchangeValid coerces a string to interchange-valid UTF-8.
-// Illegal UTF-8 bytes are replaced with the Unicode replacement character
-// ('\uFFFD'). C0 and C1 control codes (other than CR LF HT FF) and
-// non-characters are also replaced with the Unicode replacement character.
-func coerceToUTF8InterchangeValid(s string) string {
- // TODO: Replace this entire function with stdlib function if https://golang.org/issue/25805 gets addressed.
- runes := make([]rune, 0, len(s))
- // If s contains any invalid UTF-8 byte sequences, range will have rune
- // contain the Unicode replacement character and there's no need to call
- // utf8.ValidRune. I.e. iteration over the string implements
- // CoerceToStructurallyValid() from C++/Java.
- // See https://blog.golang.org/strings.
- for _, rune := range s {
- if unicode.Is(controlAndNonCharacter, rune) {
- runes = append(runes, unicode.ReplacementChar)
- } else {
- runes = append(runes, rune)
- }
- }
- return string(runes)
-}
-
-// controlAndNonCharacters contains the non-interchange-valid codepoints.
-//
-// See http://www.w3.org/TR/html5/syntax.html#preprocessing-the-input-stream
-//
-// safehtml functions do a lot of lookups on these tables, so merging them is probably
-// worth it to avoid comparing against both tables each time.
-var controlAndNonCharacter = rangetable.Merge(unicode.Noncharacter_Code_Point, controlChar)
-
-// controlChar contains Unicode control characters disallowed in interchange
-// valid UTF-8. This table is slightly different from unicode.Cc:
-// - Disallows null.
-// - Allows LF, CR, HT, and FF.
-//
-// unicode.C is mentioned in unicode.IsControl; it contains "special" characters
-// which includes at least control characters, surrogate code points, and
-// formatting codepoints (e.g. word joiner). We don't need to exclude all of
-// those. In particular, surrogates are handled by the for loop converting
-// invalid UTF-8 byte sequences to the Unicode replacement character.
-var controlChar = &unicode.RangeTable{
- R16: []unicode.Range16{
- {0x0000, 0x0008, 1},
- {0x000B, 0x000B, 1},
- {0x000E, 0x001F, 1},
- {0x007F, 0x009F, 1},
- },
- LatinOffset: 4,
-}
diff --git a/vendor/github.com/google/safehtml/identifier.go b/vendor/github.com/google/safehtml/identifier.go
deleted file mode 100644
index ffad26423..000000000
--- a/vendor/github.com/google/safehtml/identifier.go
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package safehtml
-
-import (
- "fmt"
- "regexp"
-)
-
-// A Identifier is an immutable string-like type that is safe to use in HTML
-// contexts as an identifier for HTML elements. For example, it is unsafe to
-// insert an untrusted string into a
-//
-// <img name="..."></img>
-//
-// context since the string may be controlled by an attacker who can assign it
-// a value that masks existing DOM properties (i.e. DOM Clobbering). An
-// attacker may also be able to force legitimate Javascript code, which uses
-// document.getElementsByName(...) to read DOM elements, to refer to this
-// element. This may lead to unintended side effects, particularly if that
-// element contains attacker-controlled data. It is, however, safe to use an
-// Identifier in this context since its value is known to be partially or fully
-// under application control.
-//
-// In order to ensure that an attacker cannot influence the Identifier value,
-// an Identifier can only be instantiated from a compile-time constant string
-// literal prefix.
-//
-// Note that Identifier is Go-specific and therefore does not have a Proto form
-// for cross-language use.
-type Identifier struct {
- // We declare a Identifier not as a string but as a struct wrapping a string
- // to prevent construction of Identifier values through string conversion.
- str string
-}
-
-// To minimize the risk of parsing errors, Identifier values must start with an
-// alphabetical rune, and comprise of only alphanumeric, '-', and '_' runes.
-
-// startsWithAlphabetPattern matches strings that start with an alphabetical rune.
-var startsWithAlphabetPattern = regexp.MustCompile(`^[a-zA-Z]`)
-
-// onlyAlphanumericsOrHyphenPattern matches strings that only contain alphanumeric,
-// '-' and '_' runes.
-var onlyAlphanumericsOrHyphenPattern = regexp.MustCompile(`^[-_a-zA-Z0-9]*$`)
-
-// IdentifierFromConstant constructs an Identifier with its underlying identifier
-// set to the given string value, which must be an untyped string constant. It
-// panics if value does not start with an alphabetic rune or contains any
-// non-alphanumeric runes other than '-' and '_'.
-func IdentifierFromConstant(value stringConstant) Identifier {
- if !startsWithAlphabetPattern.MatchString(string(value)) ||
- !onlyAlphanumericsOrHyphenPattern.MatchString(string(value)) {
- panic(fmt.Sprintf("invalid identifier %q", string(value)))
- }
- return Identifier{string(value)}
-}
-
-// IdentifierFromConstantPrefix constructs an Identifier with its underlying string
-// set to the string formed by joining prefix, which must be an untyped string
-// constant, and value with a hyphen. It panics if prefix or value contain any
-// non-alphanumeric runes other than '-' and '_', or if prefix does not start with
-// an alphabetic rune.
-func IdentifierFromConstantPrefix(prefix stringConstant, value string) Identifier {
- prefixString := string(prefix)
- if !startsWithAlphabetPattern.MatchString(string(prefix)) ||
- !onlyAlphanumericsOrHyphenPattern.MatchString(string(prefix)) {
- panic(fmt.Sprintf("invalid prefix %q", string(prefix)))
- }
- if !onlyAlphanumericsOrHyphenPattern.MatchString(value) {
- panic(fmt.Sprintf("value %q contains non-alphanumeric runes", value))
- }
- return Identifier{prefixString + "-" + value}
-}
-
-// String returns the string form of the Identifier.
-func (i Identifier) String() string {
- return i.str
-}
diff --git a/vendor/github.com/google/safehtml/init.go b/vendor/github.com/google/safehtml/init.go
deleted file mode 100644
index d37547d72..000000000
--- a/vendor/github.com/google/safehtml/init.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package safehtml
-
-import (
- "github.com/google/safehtml/internal/raw"
-)
-
-// stringConstant is an unexported string type. Users of this package cannot
-// create values of this type except by passing an untyped string constant to
-// functions which expect a stringConstant. This type should only be used in
-// function and method parameters.
-type stringConstant string
-
-// The following functions are used by package uncheckedconversions
-// (via package raw) to create safe HTML types from plain strings.
-
-func htmlRaw(s string) HTML {
- return HTML{s}
-}
-
-func scriptRaw(s string) Script {
- return Script{s}
-}
-
-func style(s string) Style {
- return Style{s}
-}
-
-func styleSheetRaw(s string) StyleSheet {
- return StyleSheet{s}
-}
-
-func urlRaw(s string) URL {
- return URL{s}
-}
-
-func trustedResourceURLRaw(s string) TrustedResourceURL {
- return TrustedResourceURL{s}
-}
-
-func identifierRaw(s string) Identifier {
- return Identifier{s}
-}
-
-func init() {
- raw.HTML = htmlRaw
- raw.Script = scriptRaw
- raw.Style = style
- raw.StyleSheet = styleSheetRaw
- raw.URL = urlRaw
- raw.TrustedResourceURL = trustedResourceURLRaw
- raw.Identifier = identifierRaw
-}
diff --git a/vendor/github.com/google/safehtml/internal/raw/raw.go b/vendor/github.com/google/safehtml/internal/raw/raw.go
deleted file mode 100644
index 3bedb6a6d..000000000
--- a/vendor/github.com/google/safehtml/internal/raw/raw.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-// Package raw provides a coordination point for package safehtml, package
-// uncheckedconversions, package legacyconversions, and package testconversions.
-// raw must only be imported by these four packages.
-package raw
-
-// HTML is the raw constructor for a safehtml.HTML.
-var HTML interface{}
-
-// Script is the raw constructor for a safehtml.Script.
-var Script interface{}
-
-// Style is the raw constructor for a safehtml.Style.
-var Style interface{}
-
-// StyleSheet is the raw constructor for a safehtml.StyleSheet.
-var StyleSheet interface{}
-
-// URL is the raw constructor for a safehtml.URL.
-var URL interface{}
-
-// TrustedResourceURL is the raw constructor for a safehtml.TrustedResourceURL.
-var TrustedResourceURL interface{}
-
-// Identifier is the raw constructor for a safehtml.Identifier.
-var Identifier interface{}
diff --git a/vendor/github.com/google/safehtml/internal/safehtmlutil/safehtmlutil.go b/vendor/github.com/google/safehtml/internal/safehtmlutil/safehtmlutil.go
deleted file mode 100644
index dd8e7fe36..000000000
--- a/vendor/github.com/google/safehtml/internal/safehtmlutil/safehtmlutil.go
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-// Package safehtmlutil contains functions shared by package safehtml and safehtml/template.
-package safehtmlutil
-
-import (
- "bytes"
- "fmt"
- "reflect"
- "regexp"
-)
-
-// IsSafeTrustedResourceURLPrefix returns whether the given prefix is safe to use as a
-// TrustedResourceURL prefix.
-//
-// TrustedResourceURL prefixes must start with one of the following:
-// * `https://<origin>/`
-// * `//<origin>/`
-// * `/<pathStart>`
-// * `about:blank#`
-//
-// `<origin>` must contain only alphanumerics, '.', ':', '[', ']', or '-'.
-// These restrictions do not enforce a well-formed domain name, so '.' and '1.2' are valid.
-//
-// `<pathStart>` is any character except `/` and `\`. Based on
-// https://url.spec.whatwg.org/commit-snapshots/56b74ce7cca8883eab62e9a12666e2fac665d03d/#url-parsing,
-// an initial / which is not followed by another / or \ will end up in the "path state" and from there
-// it can only go to the "fragment state" and "query state".
-func IsSafeTrustedResourceURLPrefix(prefix string) bool {
- return safeTrustedResourceURLPrefixPattern.MatchString(prefix)
-}
-
-var safeTrustedResourceURLPrefixPattern = regexp.MustCompile(`(?i)^(?:` +
- `(?:https:)?//[0-9a-z.:\[\]-]+/|` +
- `/[^/\\]|` +
- `about:blank#)`)
-
-// URLContainsDoubleDotSegment returns whether the given URL or URL substring
-// contains the double dot-segment ".." (RFC3986 3.3) in its percent-encoded or
-// unencoded form.
-func URLContainsDoubleDotSegment(url string) bool {
- return urlDoubleDotSegmentPattern.MatchString(url)
-}
-
-var urlDoubleDotSegmentPattern = regexp.MustCompile(`(?i)(?:\.|%2e)(?:\.|%2e)`)
-
-// QueryEscapeURL produces an output that can be embedded in a URL query.
-// The output can be embedded in an HTML attribute without further escaping.
-func QueryEscapeURL(args ...interface{}) string {
- return urlProcessor(false, Stringify(args...))
-}
-
-// NormalizeURL normalizes URL content so it can be embedded in a quote-delimited
-// string or parenthesis delimited url(...).
-// The normalizer does not encode all HTML specials. Specifically, it does not
-// encode '&' so correct embedding in an HTML attribute requires escaping of
-// '&' to '&amp;'.
-func NormalizeURL(args ...interface{}) string {
- return urlProcessor(true, Stringify(args...))
-}
-
-// urlProcessor normalizes (when norm is true) or escapes its input to produce
-// a valid hierarchical or opaque URL part.
-func urlProcessor(norm bool, s string) string {
- var b bytes.Buffer
- written := 0
- // The byte loop below assumes that all URLs use UTF-8 as the
- // content-encoding. This is similar to the URI to IRI encoding scheme
- // defined in section 3.1 of RFC 3987, and behaves the same as the
- // EcmaScript builtin encodeURIComponent.
- // It should not cause any misencoding of URLs in pages with
- // Content-type: text/html;charset=UTF-8.
- for i, n := 0, len(s); i < n; i++ {
- c := s[i]
- switch c {
- // Single quote and parens are sub-delims in RFC 3986, but we
- // escape them so the output can be embedded in single
- // quoted attributes and unquoted CSS url(...) constructs.
- // Single quotes are reserved in URLs, but are only used in
- // the obsolete "mark" rule in an appendix in RFC 3986
- // so can be safely encoded.
- case '!', '#', '$', '&', '*', '+', ',', '/', ':', ';', '=', '?', '@', '[', ']':
- if norm {
- continue
- }
- // Unreserved according to RFC 3986 sec 2.3
- // "For consistency, percent-encoded octets in the ranges of
- // ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D),
- // period (%2E), underscore (%5F), or tilde (%7E) should not be
- // created by URI producers
- case '-', '.', '_', '~':
- continue
- case '%':
- // When normalizing do not re-encode valid escapes.
- if norm && i+2 < len(s) && isHex(s[i+1]) && isHex(s[i+2]) {
- continue
- }
- default:
- // Unreserved according to RFC 3986 sec 2.3
- if 'a' <= c && c <= 'z' {
- continue
- }
- if 'A' <= c && c <= 'Z' {
- continue
- }
- if '0' <= c && c <= '9' {
- continue
- }
- }
- b.WriteString(s[written:i])
- fmt.Fprintf(&b, "%%%02x", c)
- written = i + 1
- }
- if written == 0 {
- return s
- }
- b.WriteString(s[written:])
- return b.String()
-}
-
-// isHex reports whether the given character is a hex digit.
-func isHex(c byte) bool {
- return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'
-}
-
-// Stringify converts its arguments to a string. It is equivalent to
-// fmt.Sprint(args...), except that it deferences all pointers.
-func Stringify(args ...interface{}) string {
- // Optimization for simple common case of a single string argument.
- if len(args) == 1 {
- if s, ok := args[0].(string); ok {
- return s
- }
- }
- for i, arg := range args {
- args[i] = indirectToStringerOrError(arg)
- }
- return fmt.Sprint(args...)
-}
-
-var (
- errorType = reflect.TypeOf((*error)(nil)).Elem()
- fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
-)
-
-// indirectToStringerOrError dereferences a as many times
-// as necessary to reach the base type, an implementation of fmt.Stringer,
-// or an implementation of error, and returns a value of that type. It returns
-// nil if a is nil.
-func indirectToStringerOrError(a interface{}) interface{} {
- if a == nil {
- return nil
- }
- v := reflect.ValueOf(a)
- for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
- v = v.Elem()
- }
- return v.Interface()
-}
-
-// Indirect returns the value, after dereferencing as many times
-// as necessary to reach the base type (or nil).
-func Indirect(a interface{}) interface{} {
- if a == nil {
- return nil
- }
- if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr {
- // Avoid creating a reflect.Value if it's not a pointer.
- return a
- }
- v := reflect.ValueOf(a)
- for v.Kind() == reflect.Ptr && !v.IsNil() {
- v = v.Elem()
- }
- return v.Interface()
-}
diff --git a/vendor/github.com/google/safehtml/internal/template/raw/raw.go b/vendor/github.com/google/safehtml/internal/template/raw/raw.go
deleted file mode 100644
index b69599bd2..000000000
--- a/vendor/github.com/google/safehtml/internal/template/raw/raw.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-// Package raw provides a coordination point for package safehtml/template and
-// package safehtml/template/uncheckedconversions. raw must be imported only by
-// these two packages.
-package raw
-
-// TrustedSource is the raw constructor for a template.TrustedSource.
-var TrustedSource interface{}
-
-// TrustedTemplate is the raw constructor for a template.TrustedTemplate.
-var TrustedTemplate interface{}
diff --git a/vendor/github.com/google/safehtml/script.go b/vendor/github.com/google/safehtml/script.go
deleted file mode 100644
index c9e0fd298..000000000
--- a/vendor/github.com/google/safehtml/script.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package safehtml
-
-import (
- "encoding/json"
- "fmt"
- "regexp"
-)
-
-// A Script is an immutable string-like type which represents JavaScript
-// code and guarantees that its value, as a string, will not cause execution
-// of unconstrained attacker controlled code (cross-site scripting) when
-// evaluated as JavaScript in a browser.
-//
-// Script's string representation can safely be interpolated as the
-// content of a script element within HTML, and can safely be passed to DOM
-// properties and functions which expect JavaScript. In these cases, the Script
-// string should not be escaped. Script's string representation can also be safely
-// used as the value for on* attribute handlers in HTML, though the Script string
-// must be escaped before such use.
-//
-// Note that the Script might contain text that is attacker-controlled but
-// that text should have been interpolated with appropriate escaping,
-// sanitization and/or validation into the right location in the script, such
-// that it is highly constrained in its effect (for example, it had to match a
-// set of allowed words).
-//
-// In order to ensure that an attacker cannot influence the Script
-// value, a Script can only be instantiated from compile-time
-// constant string literals or security-reviewed unchecked conversions,
-// but never from arbitrary string values potentially representing untrusted
-// user input.
-type Script struct {
- // We declare a Script not as a string but as a struct wrapping a string
- // to prevent construction of Script values through string conversion.
- str string
-}
-
-// ScriptFromConstant constructs a Script with its underlying script set
-// to the given script, which must be an untyped string constant.
-//
-// No runtime validation or sanitization is performed on script; being under
-// application control, it is simply assumed to comply with the Script
-// contract.
-func ScriptFromConstant(script stringConstant) Script {
- return Script{string(script)}
-}
-
-// ScriptFromDataAndConstant constructs a Script of the form
-//
-// var name = data; script
-//
-// where name is the supplied variable name, data is the supplied data value
-// encoded as JSON using encoding/json.Marshal, and script is the supplied
-// JavaScript statement or sequence of statements. The supplied name and script
-// must both be untyped string constants. It returns an error if name is not a
-// valid Javascript identifier or JSON encoding fails.
-//
-// No runtime validation or sanitization is performed on script; being under
-// application control, it is simply assumed to comply with the Script
-// contract.
-func ScriptFromDataAndConstant(name stringConstant, data interface{}, script stringConstant) (Script, error) {
- if !jsIdentifierPattern.MatchString(string(name)) {
- return Script{}, fmt.Errorf("variable name %q is an invalid Javascript identifier", string(name))
- }
- json, err := json.Marshal(data)
- if err != nil {
- return Script{}, err
- }
- return Script{fmt.Sprintf("var %s = %s;\n%s", name, json, string(script))}, nil
-}
-
-// jsIdentifierPattern matches strings that are valid Javascript identifiers.
-//
-// This pattern accepts only a subset of valid identifiers defined in
-// https://tc39.github.io/ecma262/#sec-names-and-keywords. In particular,
-// it does not match identifiers that contain non-ASCII letters, Unicode
-// escape sequences, and the Unicode format-control characters
-// \u200C (zero-width non-joiner) and \u200D (zero-width joiner).
-var jsIdentifierPattern = regexp.MustCompile(`^[$_a-zA-Z][$_a-zA-Z0-9]+$`)
-
-// String returns the string form of the Script.
-func (s Script) String() string {
- return s.str
-}
diff --git a/vendor/github.com/google/safehtml/style.go b/vendor/github.com/google/safehtml/style.go
deleted file mode 100644
index c11ac9d96..000000000
--- a/vendor/github.com/google/safehtml/style.go
+++ /dev/null
@@ -1,304 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package safehtml
-
-import (
- "bytes"
- "fmt"
- "regexp"
- "strings"
-)
-
-// A Style is an immutable string-like type which represents a sequence of CSS
-// declarations (property_name1: property_value1; property_name2: property_value2; ...)
-// and guarantees that its value will not cause untrusted script execution
-// (cross-site scripting) when evaluated as CSS in a browser.
-//
-// Style's string representation can safely be:
-// * Interpolated as the content of a quoted HTML style attribute. However, the
-// Style string must be HTML-attribute-escaped before interpolation.
-// * Interpolated as the content of a {}-wrapped block within a StyleSheet.
-// '<' runes in the Style string must be CSS-escaped before interpolation.
-// The Style string is also guaranteed not to be able to introduce new
-// properties or elide existing ones.
-// * Interpolated as the content of a {}-wrapped block within an HTML <style>
-// element. '<' runes in the Style string must be CSS-escaped before interpolation.
-// * Assigned to the style property of a DOM node. The Style string should not
-// be escaped before being assigned to the property.
-//
-// In addition, values of this type are composable, that is, for any two Style
-// values |style1| and |style2|, style1.style() + style2.style() is itself a
-// value that satisfies the Style type constraint.
-type Style struct {
- // We declare a Style not as a string but as a struct wrapping a string
- // to prevent construction of Style values through string conversion.
- str string
-}
-
-// StyleFromConstant constructs a Style with its underlying style set to the
-// given style, which must be an untyped string constant, and panics if the
-// style string does not pass basic syntax checks.
-//
-// Users of this function must ensure themselves that the style:
-// * Does not contain unsafe CSS.
-// * Does not contain literal angle brackets. Otherwise, it could be unsafe to
-// place a Style into the contents of a <style> element where it can't be
-// HTML escaped (see http://www.w3.org/International/questions/qa-escapes).
-// For example, if the Style containing
-// "font: 'foo <style/><script>evil</script>'" was interpolated within a
-// <style> tag, it would then break out of the style context into HTML.
-// * Does not end in a property value or property name context.
-// For example, a value of "background:url(\"" or "font-" does not satisfy
-// the Style type contract. This rule is enforced to ensure composability:
-// concatenating two incomplete strings that themselves do not contain unsafe
-// CSS can result in an overall string that does. For example, if
-// "javascript:evil())\"" is appended to "background:url(\"", the resulting
-// string may result in the execution of a malicious script.
-//
-// The style may, however, contain literal single or double quotes (for example,
-// in the "content" property). Therefore, the entire style string must be
-// escaped when used in a style attribute.
-//
-// The following example values comply with Style's type contract:
-// width: 1em;
-// height:1em;
-// width: 1em;height: 1em;
-// background:url('http://url');
-//
-// In addition, the empty string is safe for use in a style attribute.
-//
-// The following example values do NOT comply with this type's contract:
-// background: red --- missing a trailing semi-colon
-// background: --- missing a value and a trailing semi-colon
-// 1em --- missing an attribute name, which provides context
-// for the value
-//
-// See also http://www.w3.org/TR/css3-syntax/.
-func StyleFromConstant(style stringConstant) Style {
- // TODO: implement UTF-8 interchange-validity checks and blocking of newlines
- // (including Unicode ones) and other whitespace characters (\t, \f) for Style and other safe types
- // in this package.
- if strings.ContainsAny(string(style), "<>") {
- panic(fmt.Sprintf("style string %q contains angle brackets", style))
- }
- if !strings.HasSuffix(string(style), ";") {
- panic(fmt.Sprintf("style string %q must end with ';'", style))
- }
- if !strings.Contains(string(style), ":") {
- panic(fmt.Sprintf("style string %q must contain at least one ':' to specify a property-value pair", style))
- }
- return Style{string(style)}
-}
-
-// String returns the string form of the Style.
-func (s Style) String() string {
- return s.str
-}
-
-// StyleProperties contains property values for CSS properties whose names are
-// the hyphen-separated form of the field names. These values will be validated
-// by StyleFromProperties before being included in a Style.
-//
-// For example, BackgroundPosition contains the value for the
-// "background-position" property, and Display contains the value for the "display"
-// property.
-//
-type StyleProperties struct {
- // BackgroundImageURLs contains URL values for the background-image property.
- // These values val_1, val_2, ..., val_n will be passed through URLSanitized and CSS-escaped in
- // StyleFromProperties, then interpolated into to a comma-separated list of CSS URLs of the form
- // url("val_1"), url("val_2"), ..., url("val_n")
- // See https://www.w3.org/TR/CSS2/syndata.html#value-def-uri and https://drafts.csswg.org/css-backgrounds-3/#layering.
- BackgroundImageURLs []string
- // FontFamily values are used, comma-separated, as the font-family property.
- // * Names starting with a Latin alphabet runes and containing only Latin alphabets and hyphens will be included unquoted.
- // * Names enclosed in double quote literals (e.g. `"21st Century"`) will be CSS-escaped without the outermost quotes,
- // then included within double quotes.
- // * All other names will be CSS-escaped, and included within double quotes.
- // See https://drafts.csswg.org/css-fonts-3/#font-family-prop.
- FontFamily []string
- // Display must consist of only ASCII alphabetic or '-' runes.
- // Non-conforming values will be replaced by InnocuousPropertyValue in
- // StyleFromProperties.
- Display string
- // The following values can only contain allowed runes, that is, alphanumerics,
- // space, tab, and the set [+-.!#%_/*]. In addition, comment markers "//", "/*",
- // and "*/" are disallowed. Non-conforming values will be replaced by
- // InnocuousPropertyValue in StyleFromProperties.
- BackgroundColor string
- BackgroundPosition string
- BackgroundRepeat string
- BackgroundSize string
- Color string
- Height string
- Width string
- Left string
- Right string
- Top string
- Bottom string
- FontWeight string
- Padding string
- // Note: this property might allow clickjacking, but the risk is limited without
- // the ability to set the position property to "absolute" or "fixed".
- ZIndex string
-}
-
-// identifierPattern matches a subset of valid <ident-token> values defined in
-// https://www.w3.org/TR/css-syntax-3/#ident-token-diagram. This pattern matches all generic family name
-// keywords defined in https://drafts.csswg.org/css-fonts-3/#family-name-value.
-var identifierPattern = regexp.MustCompile(`^[a-zA-Z][-a-zA-Z]+$`)
-
-// StyleFromProperties constructs a Style containining properties whose values
-// are set in properties. The contents of the returned Style will be of the form
-// property_1:val_1;property2:val_2; ... ;property_n:val_n;
-// This syntax is defined in https://www.w3.org/TR/css-style-attr/.
-//
-// All property values are validated and, if necessary, modified to ensure that their
-// inclusion in a HTML style attribute does not result in untrusted script execution,
-// the addition of new properties, or the removal of existing properties. Please refer
-// to the StyleProperties documentation for validation rules.
-//
-// The constructed Style is guaranteed to fulfill its type contract, but is not
-// guaranteed to be semantically valid CSS.
-func StyleFromProperties(properties StyleProperties) Style {
- // TODO: if this boilerplate code grows large, consider generating property names from Field names using reflection.
- var buf bytes.Buffer
- if len(properties.BackgroundImageURLs) > 0 {
- buf.WriteString("background-image:")
- for i, url := range properties.BackgroundImageURLs {
- if i > 0 {
- buf.WriteString(", ")
- }
- fmt.Fprintf(&buf, "url(\"%s\")", cssEscapeString(URLSanitized(url).String()))
- }
- buf.WriteString(";")
- }
- if len(properties.FontFamily) > 0 {
- buf.WriteString("font-family:")
- for i, name := range properties.FontFamily {
- if i > 0 {
- buf.WriteString(", ")
- }
- if identifierPattern.MatchString(name) {
- buf.WriteString(name)
- continue
- }
- unescaped := name
- if len(name) >= 3 && strings.HasPrefix(name, `"`) && strings.HasSuffix(name, `"`) {
- unescaped = name[1 : len(name)-1]
- }
- fmt.Fprintf(&buf, `"%s"`, cssEscapeString(unescaped))
- }
- buf.WriteByte(';')
- }
- if properties.Display != "" {
- fmt.Fprintf(&buf, "display:%s;", filter(properties.Display, safeEnumPropertyValuePattern))
- }
- if properties.BackgroundColor != "" {
- fmt.Fprintf(&buf, "background-color:%s;", filter(properties.BackgroundColor, safeRegularPropertyValuePattern))
- }
- if properties.BackgroundPosition != "" {
- fmt.Fprintf(&buf, "background-position:%s;", filter(properties.BackgroundPosition, safeRegularPropertyValuePattern))
- }
- if properties.BackgroundRepeat != "" {
- fmt.Fprintf(&buf, "background-repeat:%s;", filter(properties.BackgroundRepeat, safeRegularPropertyValuePattern))
- }
- if properties.BackgroundSize != "" {
- fmt.Fprintf(&buf, "background-size:%s;", filter(properties.BackgroundSize, safeRegularPropertyValuePattern))
- }
- if properties.Color != "" {
- fmt.Fprintf(&buf, "color:%s;", filter(properties.Color, safeRegularPropertyValuePattern))
- }
- if properties.Height != "" {
- fmt.Fprintf(&buf, "height:%s;", filter(properties.Height, safeRegularPropertyValuePattern))
- }
- if properties.Width != "" {
- fmt.Fprintf(&buf, "width:%s;", filter(properties.Width, safeRegularPropertyValuePattern))
- }
- if properties.Left != "" {
- fmt.Fprintf(&buf, "left:%s;", filter(properties.Left, safeRegularPropertyValuePattern))
- }
- if properties.Right != "" {
- fmt.Fprintf(&buf, "right:%s;", filter(properties.Right, safeRegularPropertyValuePattern))
- }
- if properties.Top != "" {
- fmt.Fprintf(&buf, "top:%s;", filter(properties.Top, safeRegularPropertyValuePattern))
- }
- if properties.Bottom != "" {
- fmt.Fprintf(&buf, "bottom:%s;", filter(properties.Bottom, safeRegularPropertyValuePattern))
- }
- if properties.FontWeight != "" {
- fmt.Fprintf(&buf, "font-weight:%s;", filter(properties.FontWeight, safeRegularPropertyValuePattern))
- }
- if properties.Padding != "" {
- fmt.Fprintf(&buf, "padding:%s;", filter(properties.Padding, safeRegularPropertyValuePattern))
- }
- if properties.ZIndex != "" {
- fmt.Fprintf(&buf, "z-index:%s;", filter(properties.ZIndex, safeRegularPropertyValuePattern))
- }
-
- return Style{buf.String()}
-}
-
-// InnocuousPropertyValue is an innocuous property generated by filter when its input unsafe.
-const InnocuousPropertyValue = "zGoSafezInvalidPropertyValue"
-
-// safeRegularPropertyValuePattern matches strings that are safe to use as property values.
-// Specifically, it matches string where every '*' or '/' is followed by end-of-text or a safe rune
-// (i.e. alphanumberics or runes in the set [+-.!#%_ \t]). This regex ensures that the following
-// are disallowed:
-// * "/*" and "*/", which are CSS comment markers.
-// * "//", even though this is not a comment marker in the CSS specification. Disallowing
-// this string minimizes the chance that browser peculiarities or parsing bugs will allow
-// sanitization to be bypassed.
-// * '(' and ')', which can be used to call functions.
-// * ',', since it can be used to inject extra values into a property.
-// * Runes which could be matched on CSS error recovery of a previously malformed token, such as '@'
-// and ':'. See http://www.w3.org/TR/css3-syntax/#error-handling.
-var safeRegularPropertyValuePattern = regexp.MustCompile(`^(?:[*/]?(?:[0-9a-zA-Z+-.!#%_ \t]|$))*$`)
-
-// safeEnumPropertyValuePattern matches strings that are safe to use as enumerated property values.
-// Specifically, it matches strings that contain only alphabetic and '-' runes.
-var safeEnumPropertyValuePattern = regexp.MustCompile(`^[a-zA-Z-]*$`)
-
-// filter returns value if it matches pattern. Otherwise, it returns InnocuousPropertyValue.
-func filter(value string, pattern *regexp.Regexp) string {
- if !pattern.MatchString(value) {
- return InnocuousPropertyValue
- }
- return value
-}
-
-// cssEscapeString escapes s so that it is safe to put between "" to form a CSS <string-token>.
-// See syntax at https://www.w3.org/TR/css-syntax-3/#string-token-diagram.
-//
-// On top of the escape sequences required in <string-token>, this function also escapes
-// control runes to minimize the risk of these runes triggering browser-specific bugs.
-func cssEscapeString(s string) string {
- var b bytes.Buffer
- b.Grow(len(s))
- // TODO: consider optmizations (e.g. ranging over bytes, batching writes of contiguous sequences of unescaped runes) if
- // performance becomes an issue.
- for _, c := range s {
- switch {
- case c == '\u0000':
- // Replace the NULL byte according to https://www.w3.org/TR/css-syntax-3/#input-preprocessing.
- // We take this extra precaution in case the user agent fails to handle NULL properly.
- b.WriteString("\uFFFD")
- case c == '<', // Prevents breaking out of a style element with `</style>`. Escape this in case the Style user forgets to.
- c == '"', c == '\\', // Must be CSS-escaped in <string-token>. U+000A line feed is handled in the next case.
- c <= '\u001F', c == '\u007F', // C0 control codes
- c >= '\u0080' && c <= '\u009F', // C1 control codes
- c == '\u2028', c == '\u2029': // Unicode newline characters
- // See CSS escape sequence syntax at https://www.w3.org/TR/css-syntax-3/#escape-diagram.
- fmt.Fprintf(&b, "\\%06X", c)
- default:
- b.WriteRune(c)
- }
- }
- return b.String()
-}
diff --git a/vendor/github.com/google/safehtml/stylesheet.go b/vendor/github.com/google/safehtml/stylesheet.go
deleted file mode 100644
index 17de8a517..000000000
--- a/vendor/github.com/google/safehtml/stylesheet.go
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package safehtml
-
-import (
- "container/list"
- "fmt"
- "regexp"
- "strings"
-)
-
-// A StyleSheet is an immutable string-like type which represents a CSS
-// style sheet and guarantees that its value, as a string, will not cause
-// untrusted script execution (cross-site scripting) when evaluated as CSS
-// in a browser.
-//
-// StyleSheet's string representation can safely be interpolated as the
-// content of a style element within HTML. The StyleSheet string should
-// not be escaped before interpolation.
-type StyleSheet struct {
- // We declare a StyleSheet not as a string but as a struct wrapping a string
- // to prevent construction of StyleSheet values through string conversion.
- str string
-}
-
-// StyleSheetFromConstant constructs a StyleSheet with the
-// underlying stylesheet set to the given styleSheet, which must be an untyped string
-// constant.
-//
-// No runtime validation or sanitization is performed on script; being under
-// application control, it is simply assumed to comply with the StyleSheet
-// contract.
-func StyleSheetFromConstant(styleSheet stringConstant) StyleSheet {
- return StyleSheet{string(styleSheet)}
-}
-
-// CSSRule constructs a StyleSheet containng a CSS rule of the form:
-// selector{style}
-// It returns an error if selector contains disallowed characters or unbalanced
-// brackets.
-//
-// The constructed StyleSheet value is guaranteed to fulfill its type contract,
-// but is not guaranteed to be semantically valid CSS.
-func CSSRule(selector string, style Style) (StyleSheet, error) {
- if strings.ContainsRune(selector, '<') {
- return StyleSheet{}, fmt.Errorf("selector %q contains '<'", selector)
- }
- selectorWithoutStrings := cssStringPattern.ReplaceAllString(selector, "")
- if matches := invalidCSSSelectorRune.FindStringSubmatch(selectorWithoutStrings); matches != nil {
- return StyleSheet{}, fmt.Errorf("selector %q contains %q, which is disallowed outside of CSS strings", selector, matches[0])
- }
- if !hasBalancedBrackets(selectorWithoutStrings) {
- return StyleSheet{}, fmt.Errorf("selector %q contains unbalanced () or [] brackets", selector)
- }
- return StyleSheet{fmt.Sprintf("%s{%s}", selector, style.String())}, nil
-}
-
-var (
- // cssStringPattern matches a single- or double-quoted CSS string.
- cssStringPattern = regexp.MustCompile(
- `"([^"\r\n\f\\]|\\[\s\S])*"|` + // Double-quoted string literal
- `'([^'\r\n\f\\]|\\[\s\S])*'`) // Single-quoted string literal
-
- // invalidCSSSelectorRune matches a rune that is not allowed in a CSS3
- // selector that does not contain string literals.
- // See https://w3.org/TR/css3-selectors/#selectors.
- invalidCSSSelectorRune = regexp.MustCompile(`[^-_a-zA-Z0-9#.:* ,>+~[\]()=^$|]`)
-)
-
-// hasBalancedBrackets returns whether s has balanced () and [] brackets.
-func hasBalancedBrackets(s string) bool {
- stack := list.New()
- for i := 0; i < len(s); i++ {
- c := s[i]
- if expected, ok := matchingBrackets[c]; ok {
- e := stack.Back()
- if e == nil {
- return false
- }
- // Skip success check for this type assertion since it is trivial to
- // see that only bytes are pushed onto this stack.
- if v := e.Value.(byte); v != expected {
- return false
- }
- stack.Remove(e)
- continue
- }
- for _, openBracket := range matchingBrackets {
- if c == openBracket {
- stack.PushBack(c)
- break
- }
- }
- }
- return stack.Len() == 0
-}
-
-// matchingBrackets[x] is the opening bracket that matches closing bracket x.
-var matchingBrackets = map[byte]byte{
- ')': '(',
- ']': '[',
-}
-
-// String returns the string form of the StyleSheet.
-func (s StyleSheet) String() string {
- return s.str
-}
diff --git a/vendor/github.com/google/safehtml/template/context.go b/vendor/github.com/google/safehtml/template/context.go
deleted file mode 100644
index dd7886dc6..000000000
--- a/vendor/github.com/google/safehtml/template/context.go
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package template
-
-import (
- "strings"
-)
-
-// context describes the state an HTML parser must be in when it reaches the
-// portion of HTML produced by evaluating a particular template node.
-//
-// The zero value of type Context is the start context for a template that
-// produces an HTML fragment as defined at
-// http://www.w3.org/TR/html5/syntax.html#the-end
-// where the context element is null.
-type context struct {
- state state
- delim delim
- element element
- attr attr
- err *Error
- // scriptType is the lowercase value of the "type" attribute inside the current "script"
- // element (see https://dev.w3.org/html5/spec-preview/the-script-element.html#attr-script-type).
- // This field will be empty if the parser is currently not in a script element,
- // the type attribute has not already been parsed in the current element, or if the
- // value of the type attribute cannot be determined at parse time.
- scriptType string
- // linkRel is the value of the "rel" attribute inside the current "link"
- // element (see https://html.spec.whatwg.org/multipage/semantics.html#attr-link-rel).
- // This value has been normalized to lowercase with exactly one space between tokens
- // and exactly one space at start and end, so that a lookup of any token foo can
- // be performed by searching for the substring " foo ".
- // This field will be empty if the parser is currently not in a link element,
- // the rel attribute has not already been parsed in the current element, or if the
- // value of the rel attribute cannot be determined at parse time.
- linkRel string
-}
-
-// eq returns whether Context c is equal to Context d.
-func (c context) eq(d context) bool {
- return c.state == d.state &&
- c.delim == d.delim &&
- c.element.eq(d.element) &&
- c.attr.eq(d.attr) &&
- c.err == d.err &&
- c.scriptType == d.scriptType &&
- c.linkRel == d.linkRel
-}
-
-// state describes a high-level HTML parser state.
-//
-// It bounds the top of the element stack, and by extension the HTML insertion
-// mode, but also contains state that does not correspond to anything in the
-// HTML5 parsing algorithm because a single token production in the HTML
-// grammar may contain embedded actions in a template. For instance, the quoted
-// HTML attribute produced by
-// <div title="Hello {{.World}}">
-// is a single token in HTML's grammar but in a template spans several nodes.
-type state uint8
-
-//go:generate stringer -type state
-
-const (
- // stateText is parsed character data. An HTML parser is in
- // this state when its parse position is outside an HTML tag,
- // directive, comment, and special element body.
- stateText state = iota
- // stateSpecialElementBody occurs inside a specal HTML element body.
- stateSpecialElementBody
- // stateTag occurs before an HTML attribute or the end of a tag.
- stateTag
- // stateAttrName occurs inside an attribute name.
- // It occurs between the ^'s in ` ^name^ = value`.
- stateAttrName
- // stateAfterName occurs after an attr name has ended but before any
- // equals sign. It occurs between the ^'s in ` name^ ^= value`.
- stateAfterName
- // stateBeforeValue occurs after the equals sign but before the value.
- // It occurs between the ^'s in ` name =^ ^value`.
- stateBeforeValue
- // stateHTMLCmt occurs inside an <!-- HTML comment -->.
- stateHTMLCmt
- // stateAttr occurs inside an HTML attribute whose content is text.
- stateAttr
- // stateError is an infectious error state outside any valid
- // HTML/CSS/JS construct.
- stateError
-)
-
-// isComment reports whether a state contains content meant for template
-// authors & maintainers, not for end-users or machines.
-func isComment(s state) bool {
- switch s {
- case stateHTMLCmt:
- return true
- }
- return false
-}
-
-// isInTag reports whether s occurs solely inside an HTML tag.
-func isInTag(s state) bool {
- switch s {
- case stateTag, stateAttrName, stateAfterName, stateBeforeValue, stateAttr:
- return true
- }
- return false
-}
-
-// delim is the delimiter that will end the current HTML attribute.
-type delim uint8
-
-//go:generate stringer -type delim
-
-const (
- // delimNone occurs outside any attribute.
- delimNone delim = iota
- // delimDoubleQuote occurs when a double quote (") closes the attribute.
- delimDoubleQuote
- // delimSingleQuote occurs when a single quote (') closes the attribute.
- delimSingleQuote
- // delimSpaceOrTagEnd occurs when a space or right angle bracket (>)
- // closes the attribute.
- delimSpaceOrTagEnd
-)
-
-type element struct {
- // name is the lowercase name of the element. If context joining has occurred, name
- // will be arbitrarily assigned the element name from one of the joined contexts.
- name string
- // names contains all possible names the element could assume because of context joining.
- // For example, after joining the contexts in the "if" and "else" branches of
- // {{if .C}}<img{{else}}<audio{{end}} src="/some/path">`,
- // names will contain "img" and "audio".
- // names can also contain empty strings, which represent joined contexts with no element name.
- // names will be empty if no context joining occurred.
- names []string
-}
-
-// eq reports whether a and b have the same name. All other fields are ignored.
-func (e element) eq(d element) bool {
- return e.name == d.name
-}
-
-// String returns the string representation of the element.
-func (e element) String() string {
- return "element" + strings.Title(e.name)
-}
-
-// attr represents the attribute that the parser is in, that is,
-// starting from stateAttrName until stateTag/stateText (exclusive).
-type attr struct {
- // name is the lowercase name of the attribute. If context joining has occurred, name
- // will be arbitrarily assigned the attribute name from one of the joined contexts.
- name string
- // value is the value of the attribute. If context joining has occurred, value
- // will be arbitrarily assigned the attribute value from one of the joined contexts.
- // If there are multiple actions in the attribute value, value will contain the
- // concatenation of all values seen so far. For example, in
- // <a name="foo{{.X}}bar{{.Y}}">
- // value is "foo" at "{{.X}}" and "foobar" at "{{.Y}}".
- value string
- // ambiguousValue indicates whether value contains an ambiguous value due to context-joining.
- ambiguousValue bool
- // names contains all possible names the attribute could assume because of context joining.
- // For example, after joining the contexts in the "if" and "else" branches of
- // <a {{if .C}}title{{else}}name{{end}}="foo">
- // names will contain "title" and "name".
- // names can also contain empty strings, which represent joined contexts with no attribute name.
- // names will be empty if no context joining occurred.
- names []string
-}
-
-// eq reports whether a and b have the same name. All other fields are ignored.
-func (a attr) eq(b attr) bool {
- return a.name == b.name
-}
-
-// String returns the string representation of the attr.
-func (a attr) String() string {
- return "attr" + strings.Title(a.name)
-}
diff --git a/vendor/github.com/google/safehtml/template/delim_string.go b/vendor/github.com/google/safehtml/template/delim_string.go
deleted file mode 100644
index 0ef2c2510..000000000
--- a/vendor/github.com/google/safehtml/template/delim_string.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Code generated by "stringer -type Delim"; DO NOT EDIT
-
-package template
-
-import "fmt"
-
-const _Delim_name = "DelimNoneDelimDoubleQuoteDelimSingleQuoteDelimSpaceOrTagEnd"
-
-var _Delim_index = [...]uint8{0, 9, 25, 41, 59}
-
-func (i delim) String() string {
- if i >= delim(len(_Delim_index)-1) {
- return fmt.Sprintf("delim(%d)", i)
- }
- return _Delim_name[_Delim_index[i]:_Delim_index[i+1]]
-}
diff --git a/vendor/github.com/google/safehtml/template/doc.go b/vendor/github.com/google/safehtml/template/doc.go
deleted file mode 100644
index fab552b25..000000000
--- a/vendor/github.com/google/safehtml/template/doc.go
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-/*
-Package template (safehtml/template) implements data-driven templates for
-generating HTML output safe against code injection. It provides an interface
-similar to that of package html/template, but produces HTML output that is more
-secure. Therefore, it should be used instead of html/template to render HTML.
-
-The documentation here focuses on the security features of the package. For
-information about how to program the templates themselves, see the
-documentation for text/template.
-
-
-Basic usage
-
-This package provides an API almost identical to that of text/template and
-html/template to parse and execute HTML templates safely.
-
- tmpl := template.Must(template.New("name").Parse(`<div>Hello {{.}}</div>`))
- err := tmpl.Execute(out, data)
-
-If successful, out will contain code-injection-safe HTML. Otherwise, err's
-string representation will describe the error that occurred.
-
-Elements of data might be modified at run time before being included in out, or
-rejected completely if such a conversion is not possible. Pass values of
-appropriate types from package safehtml to ensure that they are included in the
-template's HTML output in their expected form. More details are provided below
-in "Contextual autosanitization" and "Sanitization contexts".
-
-
-Security improvements
-
-safehtml/template produces HTML more resistant to code injection than
-html/template because it:
- * Allows values of types only from package safehtml to bypass run-time
- sanitization. These types represent values that are known---by construction
- or by run-time sanitization---to be safe for use in various HTML contexts
- without being processed by certain sanitization functions.
- * Does not attempt to escape CSS or JavaScript. Instead of attempting to
- parse and escape these complex languages, safehtml/template allows values
- of only the appropriate types from package safehtml (e.g. safehtml.Style,
- safehtml.Script) to be used in these contexts, since they are already
- guaranteed to be safe.
- * Emits an error if user data is interpolated in unsafe contexts, such as
- within disallowed elements or unquoted attribute values.
- * Only loads templates from trusted sources. This ensures that the contents
- of the template are always under programmer control. More details are
- provided below in "Trusted template sources".
- * Differentiates between URLs that load code and those that do not. URLs in
- the former category must be supplied to the template as values of type
- safehtml.TrustedResourceURL, whose type contract promises that the URL
- identifies a trustworthy resource. URLs in the latter category can be
- sanitized at run time.
-
-
-Threat model
-
-safehtml/template assumes that programmers are trustworthy. Therefore, data
-fully under programmer control, such as string literals, are considered safe.
-The types from package safehtml are designed around this same assumption, so
-their type contracts are trusted by this package.
-
-safehtml/template considers all other data values untrustworthy and
-conservatively assumes that such values could result in a code-injection
-vulnerability if included verbatim in HTML.
-
-
-Trusted template sources
-
-safehtml/template loads templates only from trusted sources. Therefore, template
-text, file paths, and file patterns passed to Parse* functions and methods must
-be entirely under programmer control.
-
-This constraint is enforced by using unexported string types for the parameters
-of Parse* functions and methods, such as trustedFilePattern for ParseGlob.
-The only values that may be assigned to these types (and thus provided as
-arguments) are untyped string constants such as string literals, which are
-always under programmer control.
-
-
-Contextual autosanitization
-
-Code injection vulnerabilities, such as cross-site scripting (XSS), occur when
-untrusted data values are embedded in a HTML document. For example,
-
- import "text/template"
- ...
- var t = template.Must(template.New("foo").Parse(`<a href="{{ .X }}">{{ .Y }}</a>`))
- func renderHTML(x, y string) string {
- var out bytes.Buffer
- err := t.Execute(&out, struct{ X, Y string }{x, y})
- // Error checking elided
- return out.String()
- }
-
-If x and y originate from user-provided data, an attacker who controls these
-strings could arrange for them to contain the following values:
-
- x = "javascript:evil()"
- y = "</a><script>alert('pwned')</script><a>"
-
-which will cause renderHTML to return the following unsafe HTML:
-
- <a href="javascript:evil()"></a><script>alert('pwned')</script><a></a>
-
-To prevent such vulnerabilities, untrusted data must be sanitized before being
-included in HTML. A sanitization function takes untrusted data and returns a
-string that will not create a code-injection vulnerability in the destination
-context. The function might return the input unchanged if it deems it safe,
-escape special runes in the input's string representation to prevent them from
-triggering undesired state changes in the HTML parser, or entirely replace the
-input by an innocuous string (also known as "filtering"). If none of these
-conversions are possible, the sanitization function aborts template processing.
-
-safehtml/template contextually autosanitizes untrusted data by adding
-appropriate sanitization functions to template actions to ensure that the
-action output is safe to include in the HTML context in which the action
-appears. For example, in
-
- import "safehtml/template"
- ...
- var t = template.Must(template.New("foo").Parse(`<a href="{{ .X }}">{{ .Y }}</a>`))
- func renderHTML(x, y string) string {
- var out bytes.Buffer
- err := t.Execute(&out, struct{ X, Y string }{x, y})
- // Error checking elided
- return out.String()
- }
-
-the contextual autosanitizer rewrites the template to
-
- <a href="{{ .X | _sanitizeTrustedResourceURLOrURL | _sanitizeHTML }}">{{ .Y | _sanitizeHTML }}</a>
-
-so that the template produces the following safe, sanitized HTML output (split
-across multiple lines for clarity):
-
- <a href="about:invalid#zGoSafez">
- &lt;/a&gt;&lt;script&gt;alert(&#39;pwned&#39;)&lt;/script&gt;&lt;a&gt;
- </a>
-
-Similar template systems such as html/template, Soy, and Angular, refer to this
-functionality as "contextual autoescaping". safehtml/template uses the term
-"autosanitization" instead of "autoescaping" since "sanitization" broadly
-captures the operations of escaping and filtering.
-
-
-Sanitization contexts
-
-The types of sanitization functions inserted into an action depend on the
-action's sanitization context, which is determined by its surrounding text.
-The following table describes these sanitization contexts.
-
- +--------------------+----------------------------------+------------------------------+-----------------------+
- | Context | Examples | Safe types | Run-time sanitizer |
- |--------------------+----------------------------------+------------------------------+-----------------------+
- | HTMLContent | Hello {{.}} | safehtml.HTML | safehtml.HTMLEscaped |
- | | <title>{{.}}</title> | | |
- +--------------------------------------------------------------------------------------------------------------+
- | HTMLValOnly | <iframe srcdoc="{{.}}"></iframe> | safehtml.HTML* | N/A |
- +--------------------------------------------------------------------------------------------------------------+
- | URL | <q cite="{{.}}">Cite</q> | safehtml.URL | safehtml.URLSanitized |
- +--------------------------------------------------------------------------------------------------------------+
- | URL or | <a href="{{.}}">Link</a> | safehtml.URL | safehtml.URLSanitized |
- | TrustedResourceURL | | safehtml.TrustedResourceURL | |
- +--------------------------------------------------------------------------------------------------------------+
- | TrustedResourceURL | <script src="{{.}}"></script> | safehtml.TrustedResourceURL† | N/A |
- +--------------------------------------------------------------------------------------------------------------+
- | Script | <script>{{.}}</script> | safehtml.Script* | N/A |
- +--------------------------------------------------------------------------------------------------------------+
- | Style | <p style="{{.}}">Paragraph</p> | safehtml.Style* | N/A |
- +--------------------------------------------------------------------------------------------------------------+
- | Stylesheet | <style>{{.}}</style> | safehtml.StyleSheet* | N/A |
- +--------------------------------------------------------------------------------------------------------------+
- | Identifier | <h1 id="{{.}}">Hello</h1> | safehtml.Identifier* | N/A |
- +--------------------------------------------------------------------------------------------------------------+
- | Enumerated value | <a target="{{.}}">Link</a> | Allowed string values | N/A |
- | | | ("_self" or "_blank" for | |
- | | | the given example) | |
- +--------------------------------------------------------------------------------------------------------------+
- | None | <h1 class="{{.}}">Hello</h1> | N/A (any type allowed) | N/A (any type |
- | | | | allowed) |
- +--------------------+----------------------------------+------------------------------+-----------------------+
- *: Values only of this type are allowed in this context. Other values will trigger a run-time error.
- †: If the action is a prefix of the attribute value, values only of this type are allowed.
- Otherwise, values of any type are allowed. See "Substitutions in URLs" for more details.
-
-For each context, the function named in "Run-time sanitizer" is called to
-sanitize the output of the action. However, if the action outputs a value of
-any of the types listed in "Safe types", the run-time sanitizer is not called.
-For example, in
-
- <title>{{ .X }}</title>
-
-if X is a string value, a HTML sanitizer that calls safehtml.HTMLEscaped will be
-added to the action to sanitize X.
-
- // _sanitizeHTML calls safehtml.HTMLEscaped.
- <title>{{ .X | _sanitizeHTML }}</title>
-
-However, if X is a safehtml.HTML value, _sanitizeHTML will not change its
-value, since safehtml.HTML values are already safe to use in HTML contexts.
-Therefore, the string contents of X will bypass context-specific
-sanitization (in this case, HTML escaping) and appear unchanged in the
-template's HTML output. Note that in attribute value contexts, HTML escaping
-will always take place, whether or not context-specific sanitization is
-performed. More details can be found at the end of this section.
-
-In certain contexts, the autosanitizer allows values only of that context's
-"Safe types". Any other values will trigger an error and abort template
-processing. For example, the template
-
- <style>{{ .X }}</style>
-
-triggers a run-time error if X is not a safehtml.StyleSheet. Otherwise, the
-string form of X will appear unchanged in the output. The only exception to
-this behavior is in TrustedResourceURL sanitization contexts, where actions may
-output data of any type if the action occurs after a safe attribute value prefix.
-More details can be found below in "Substitutions in URLs".
-
-
-Unconditional sanitization
-
-In attribute value contexts, action outputs are always HTML-escaped after
-context-specific sanitization to ensure that the attribute values cannot change
-change the structure of the surrounding HTML tag. In URL or TrustedResourceURL
-sanitization contexts, action outputs are additionally URL-normalized to reduce
-the likelihood of downstream URL-parsing bugs. For example, the template
-
- <a href="{{ .X }}">Link</a>
- <p id="{{ .Y }}">Text</p>
-
-is rewritten by the autosanitizer into
-
- // _sanitizeHTML calls safehtml.HTMLEscaped.
- <a href="{{ .X | _sanitizeTrustedResourceURLOrURL | _normalizeURL | _sanitizeHTML }}">Link</a>
- <p id="{{ .Y | _sanitizeIdentifier | _sanitizeHTML }}">Text</p>
-
-Even if X is a safehtml.URL or safehtml.TrustedResourceURL value, which
-remains unchanged after _sanitizeTrustedResourceURLOrURL, X will still be
-URL-normalized and HTML-escaped. Likewise, Y will still be HTML-escaped even if
-its string form is left unchanged by _sanitizeIdentifier.
-
-
-Substitutions in URLs
-
-Values of any type may be substituted into attribute values in URL and
-TrustedResourceURL sanitization contexts only if the action is preceded by a
-safe URL prefix. For example, in
-
- <q cite="http://www.foo.com/{{ .PathComponent }}">foo</q>
-
-Since "http://www.foo.com/" is a safe URL prefix, PathComponent can safely be
-interpolated into this URL sanitization context after URL normalization.
-Similarly, in
-
- <script src="https://www.bar.com/{{ .PathComponent }}"></script>
-
-Since "https://www.bar.com/" is a safe TrustedResourceURL prefix, PathComponent
-can safely be interpolated into this TrustedResourceURL sanitization context
-after URL escaping. Substitutions after a safe TrustedResourceURL prefix are
-escaped instead of normalized to prevent the injection of any new URL
-components, including additional path components. URL escaping also takes place
-in URL sanitization contexts where the substitutions occur in the query or
-fragment part of the URL, such as in:
-
- <a href="/foo?q={{ .Query }}&hl={{ .LangCode }}">Link</a>
-
-A URL prefix is considered safe in a URL sanitization context if it does
-not end in an incomplete HTML character reference (e.g. https&#1) or incomplete
-percent-encoding character triplet (e.g. /fo%6), does not contain whitespace or control
-characters, and one of the following is true:
- * The prefix has a safe scheme (i.e. http, https, mailto, or ftp).
- * The prefix has the data scheme with base64 encoding and an allowed audio, image,
- or video MIME type (e.g. data:img/jpeg;base64, data:video/mp4;base64).
- * The prefix has no scheme at all, and cannot be interpreted as a scheme prefix (e.g. /path).
-
-A URL prefix is considered safe in a TrustedResourceURL sanitization context if it does
-not end in an incomplete HTML character reference (e.g. https&#1) or incomplete
-percent-encoding character triplet (e.g. /fo%6), does not contain white space or control
-characters, and one of the following is true:
- * The prefix has the https scheme and contains a domain name (e.g. https://www.foo.com).
- * The prefix is scheme-relative and contains a domain name (e.g. //www.foo.com/).
- * The prefix is path-absolute and contains a path (e.g. /path).
- * The prefix is "about:blank".
-*/
-package template
diff --git a/vendor/github.com/google/safehtml/template/error.go b/vendor/github.com/google/safehtml/template/error.go
deleted file mode 100644
index fe7821433..000000000
--- a/vendor/github.com/google/safehtml/template/error.go
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package template
-
-import (
- "fmt"
- "text/template/parse"
-)
-
-// Error describes a problem encountered during template Escaping.
-type Error struct {
- // ErrorCode describes the kind of error.
- ErrorCode ErrorCode
- // Node is the node that caused the problem, if known.
- // If not nil, it overrides Name and Line.
- Node parse.Node
- // Name is the name of the template in which the error was encountered.
- Name string
- // Line is the line number of the error in the template source or 0.
- Line int
- // Description is a human-readable description of the problem.
- Description string
-}
-
-// ErrorCode is a code for a kind of error.
-type ErrorCode int
-
-// We define codes for each error that manifests while escaping templates, but
-// escaped templates may also fail at runtime.
-//
-// Output: "ZgotmplZ"
-// Example:
-// <img src="{{.X}}">
-// where {{.X}} evaluates to `javascript:...`
-// Discussion:
-// "ZgotmplZ" is a special value that indicates that unsafe content reached a
-// CSS or URL context at runtime. The output of the example will be
-// <img src="#ZgotmplZ">
-// If the data comes from a trusted source, use content types to exempt it
-// from filtering: URL(`javascript:...`).
-const (
- // OK indicates the lack of an error.
- OK ErrorCode = iota
-
- // ErrAmbigContext: "... appears in an ambiguous context within a URL"
- // Example:
- // <a href="
- // {{if .C}}
- // /path/
- // {{else}}
- // /search?q=
- // {{end}}
- // {{.X}}
- // ">
- // Discussion:
- // {{.X}} is in an ambiguous URL context since, depending on {{.C}},
- // it may be either a URL suffix or a query parameter.
- // Moving {{.X}} into the condition removes the ambiguity:
- // <a href="{{if .C}}/path/{{.X}}{{else}}/search?q={{.X}}">
- ErrAmbigContext
-
- // ErrBadHTML: "expected space, attr name, or end of tag, but got ...",
- // "... in unquoted attr", "... in attribute name"
- // Example:
- // <a href = /search?q=foo>
- // <href=foo>
- // <form na<e=...>
- // <option selected<
- // Discussion:
- // This is often due to a typo in an HTML element, but some runes
- // are banned in tag names, attribute names, and unquoted attribute
- // values because they can tickle parser ambiguities.
- // Quoting all attributes is the best policy.
- ErrBadHTML
-
- // ErrBranchEnd: "{{if}} branches end in different contexts"
- // Example:
- // {{if .C}}<a href="{{end}}{{.X}}
- // Discussion:
- // Package html/template statically examines each path through an
- // {{if}}, {{range}}, or {{with}} to escape any following pipelines.
- // The example is ambiguous since {{.X}} might be an HTML text node,
- // or a URL prefix in an HTML attribute. The context of {{.X}} is
- // used to figure out how to escape it, but that context depends on
- // the run-time value of {{.C}} which is not statically known.
- //
- // The problem is usually something like missing quotes or angle
- // brackets, or can be avoided by refactoring to put the two contexts
- // into different branches of an if, range or with. If the problem
- // is in a {{range}} over a collection that should never be empty,
- // adding a dummy {{else}} can help.
- ErrBranchEnd
-
- // ErrEndContext: "... ends in a non-text context: ..."
- // Examples:
- // <div
- // <div title="no close quote>
- // <script>f()
- // Discussion:
- // Executed templates should produce a DocumentFragment of HTML.
- // Templates that end without closing tags will trigger this error.
- // Templates that should not be used in an HTML context or that
- // produce incomplete Fragments should not be executed directly.
- //
- // {{define "main"}} <script>{{template "helper"}}</script> {{end}}
- // {{define "helper"}} document.write(' <div title=" ') {{end}}
- //
- // "helper" does not produce a valid document fragment, so should
- // not be Executed directly.
- ErrEndContext
-
- // ErrNoSuchTemplate: "no such template ..."
- // Examples:
- // {{define "main"}}<div {{template "attrs"}}>{{end}}
- // {{define "attrs"}}href="{{.URL}}"{{end}}
- // Discussion:
- // Package html/template looks through template calls to compute the
- // context.
- // Here the {{.URL}} in "attrs" must be treated as a URL when called
- // from "main", but you will get this error if "attrs" is not defined
- // when "main" is parsed.
- ErrNoSuchTemplate
-
- // ErrOutputContext: "cannot compute output context for template ..."
- // Examples:
- // {{define "t"}}{{if .T}}{{template "t" .T}}{{end}}{{.H}}",{{end}}
- // Discussion:
- // A recursive template does not end in the same context in which it
- // starts, and a reliable output context cannot be computed.
- // Look for typos in the named template.
- // If the template should not be called in the named start context,
- // look for calls to that template in unexpected contexts.
- // Maybe refactor recursive templates to not be recursive.
- ErrOutputContext
-
- // ErrPartialCharset: "unfinished JS regexp charset in ..."
- // Example:
- // <script>var pattern = /foo[{{.Chars}}]/</script>
- // Discussion:
- // Package html/template does not support interpolation into regular
- // expression literal character sets.
- ErrPartialCharset
-
- // ErrPartialEscape: "unfinished escape sequence in ..."
- // Example:
- // <script>alert("\{{.X}}")</script>
- // Discussion:
- // Package html/template does not support actions following a
- // backslash.
- // This is usually an error and there are better solutions; for
- // example
- // <script>alert("{{.X}}")</script>
- // should work, and if {{.X}} is a partial escape sequence such as
- // "xA0", mark the whole sequence as safe content: JSStr(`\xA0`)
- ErrPartialEscape
-
- // ErrRangeLoopReentry: "on range loop re-entry: ..."
- // Example:
- // <script>var x = [{{range .}}'{{.}},{{end}}]</script>
- // Discussion:
- // If an iteration through a range would cause it to end in a
- // different context than an earlier pass, there is no single context.
- // In the example, there is missing a quote, so it is not clear
- // whether {{.}} is meant to be inside a JS string or in a JS value
- // context. The second iteration would produce something like
- //
- // <script>var x = ['firstValue,'secondValue]</script>
- ErrRangeLoopReentry
-
- // ErrSlashAmbig: '/' could start a division or regexp.
- // Example:
- // <script>
- // {{if .C}}var x = 1{{end}}
- // /-{{.N}}/i.test(x) ? doThis : doThat();
- // </script>
- // Discussion:
- // The example above could produce `var x = 1/-2/i.test(s)...`
- // in which the first '/' is a mathematical division operator or it
- // could produce `/-2/i.test(s)` in which the first '/' starts a
- // regexp literal.
- // Look for missing semicolons inside branches, and maybe add
- // parentheses to make it clear which interpretation you intend.
- ErrSlashAmbig
-
- // ErrPredefinedEscaper: "predefined escaper ... disallowed in template"
- // Example:
- // <div class={{. | html}}>Hello<div>
- // Discussion:
- // Package html/template already contextually escapes all pipelines to
- // produce HTML output safe against code injection. Manually escaping
- // pipeline output using the predefined escapers "html" or "urlquery" is
- // unnecessary, and may affect the correctness or safety of the escaped
- // pipeline output in Go 1.8 and earlier.
- //
- // In most cases, such as the given example, this error can be resolved by
- // simply removing the predefined escaper from the pipeline and letting the
- // contextual autoescaper handle the escaping of the pipeline. In other
- // instances, where the predefined escaper occurs in the middle of a
- // pipeline where subsequent commands expect escaped input, e.g.
- // {{.X | html | makeALink}}
- // where makeALink does
- // return `<a href="`+input+`">link</a>`
- // consider refactoring the surrounding template to make use of the
- // contextual autoescaper, i.e.
- // <a href="{{.X}}">link</a>
- //
- // To ease migration to Go 1.9 and beyond, "html" and "urlquery" will
- // continue to be allowed as the last command in a pipeline. However, if the
- // pipeline occurs in an unquoted attribute value context, "html" is
- // disallowed. Avoid using "html" and "urlquery" entirely in new templates.
- ErrPredefinedEscaper
-
- // ErrEscapeAction: "cannot escape action ..."
- // Discussion:
- // Error returned while escaping an action using EscaperForContext.
- // Refer to error message for more details.
- // TODO: remove this error type and replace it with more informative sanitization errors.
- ErrEscapeAction
-
- // ErrCSPCompatibility: `"javascript:" URI disallowed for CSP compatibility`,
- // "inline event handler ... is disallowed for CSP compatibility
- // Examples:
- // <span onclick="doThings();">A thing.</span>
- // <a href="javascript:linkClicked()">foo</a>
- // Discussion:
- // Inline event handlers (onclick="...", onerror="...") and
- // <a href="javascript:..."> links can be used to run scripts,
- // so an attacker who finds an XSS bug could inject such HTML
- // and execute malicious JavaScript. These patterns must be
- // refactored into safer alternatives for compatibility with
- // Content Security Policy (CSP).
- //
- // For example, the following HTML that contains an inline event handler:
- // <script> function doThings() { ... } </script>
- // <span onclick="doThings();">A thing.</span>
- // can be refactored into:
- // <span id="things">A thing.</span>
- // <script nonce="${nonce}">
- // document.addEventListener('DOMContentLoaded', function () {
- // document.getElementById('things')
- // .addEventListener('click', function doThings() { ... });
- // });
- // </script>
- //
- // Likewise, the following HTML containng a javascript: URI:
- // <a href="javascript:linkClicked()">foo</a>
- // can be refactored into:
- // <a id="foo">foo</a>
- // <script nonce="${nonce}">
- // document.addEventListener('DOMContentLoaded', function () {
- // document.getElementById('foo')
- // .addEventListener('click', linkClicked);
- // });
- // </script>
- ErrCSPCompatibility
- // All JS templates inside script literals have to be balanced; otherwise a concatenation such as
- // <script>alert(`x{{.data}}`</script> can contain XSS if data contains user-controlled escaped strings (e.g. as JSON).
- ErrUnbalancedJsTemplate
-)
-
-func (e *Error) Error() string {
- switch {
- case e.Node != nil:
- loc, _ := (*parse.Tree)(nil).ErrorContext(e.Node)
- return fmt.Sprintf("html/template:%s: %s", loc, e.Description)
- case e.Line != 0:
- return fmt.Sprintf("html/template:%s:%d: %s", e.Name, e.Line, e.Description)
- case e.Name != "":
- return fmt.Sprintf("html/template:%s: %s", e.Name, e.Description)
- }
- return "html/template: " + e.Description
-}
-
-// errorf creates an error given a format string f and args.
-// The template Name still needs to be supplied.
-func errorf(k ErrorCode, node parse.Node, line int, f string, args ...interface{}) *Error {
- return &Error{k, node, "", line, fmt.Sprintf(f, args...)}
-}
diff --git a/vendor/github.com/google/safehtml/template/escape.go b/vendor/github.com/google/safehtml/template/escape.go
deleted file mode 100644
index 8a9d53dd5..000000000
--- a/vendor/github.com/google/safehtml/template/escape.go
+++ /dev/null
@@ -1,884 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package template
-
-import (
- "bytes"
- "fmt"
- "html"
- "reflect"
- "strings"
- "text/template"
- "text/template/parse"
-)
-
-// TODO: remove all unused escaping logic inherited from html/template.
-// TODO: replace "escape" with "sanitize" in file names and contents to maintain consistency with safehtml/template docs.
-
-// escapeTemplate rewrites the named template, which must be
-// associated with t, to guarantee that the output of any of the named
-// templates is properly escaped. If no error is returned, then the named templates have
-// been modified. Otherwise the named templates have been rendered
-// unusable.
-func escapeTemplate(tmpl *Template, node parse.Node, name string) error {
- c, _ := tmpl.esc.escapeTree(context{}, node, name, 0)
- var err error
- if c.err != nil {
- err, c.err.Name = c.err, name
- } else if c.state != stateText {
- err = &Error{ErrEndContext, nil, name, 0, fmt.Sprintf("ends in a non-text context: %+v", c)}
- }
- if err != nil {
- // Prevent execution of unsafe templates.
- if t := tmpl.set[name]; t != nil {
- t.escapeErr = err
- t.text.Tree = nil
- t.Tree = nil
- }
- return err
- }
- tmpl.esc.commit()
- if t := tmpl.set[name]; t != nil {
- t.escapeErr = errEscapeOK
- t.Tree = t.text.Tree
- }
- return nil
-}
-
-// evalArgs formats the list of arguments into a string. It is equivalent to
-// fmt.Sprint(args...), except that it deferences all pointers.
-func evalArgs(args ...interface{}) string {
- // Optimization for simple common case of a single string argument.
- if len(args) == 1 {
- if s, ok := args[0].(string); ok {
- return s
- }
- }
- for i, arg := range args {
- args[i] = indirectToStringerOrError(arg)
- }
- return fmt.Sprint(args...)
-}
-
-// escaper collects type inferences about templates and changes needed to make
-// templates injection safe.
-type escaper struct {
- // ns is the nameSpace that this escaper is associated with.
- ns *nameSpace
- // output[templateName] is the output context for a templateName that
- // has been mangled to include its input context.
- output map[string]context
- // derived[c.mangle(name)] maps to a template derived from the template
- // named name templateName for the start context c.
- derived map[string]*template.Template
- // called[templateName] is a set of called mangled template names.
- called map[string]bool
- // xxxNodeEdits are the accumulated edits to apply during commit.
- // Such edits are not applied immediately in case a template set
- // executes a given template in different escaping contexts.
- actionNodeEdits map[*parse.ActionNode][]string
- templateNodeEdits map[*parse.TemplateNode]string
- textNodeEdits map[*parse.TextNode][]byte
-}
-
-// makeEscaper creates a blank escaper for the given set.
-func makeEscaper(n *nameSpace) escaper {
- return escaper{
- n,
- map[string]context{},
- map[string]*template.Template{},
- map[string]bool{},
- map[*parse.ActionNode][]string{},
- map[*parse.TemplateNode]string{},
- map[*parse.TextNode][]byte{},
- }
-}
-
-// escape escapes a template node.
-func (e *escaper) escape(c context, n parse.Node) context {
- switch n := n.(type) {
- case *parse.ActionNode:
- return e.escapeAction(c, n)
- case *parse.IfNode:
- return e.escapeBranch(c, &n.BranchNode, "if")
- case *parse.ListNode:
- return e.escapeList(c, n)
- case *parse.RangeNode:
- return e.escapeBranch(c, &n.BranchNode, "range")
- case *parse.TemplateNode:
- return e.escapeTemplate(c, n)
- case *parse.TextNode:
- return e.escapeText(c, n)
- case *parse.WithNode:
- return e.escapeBranch(c, &n.BranchNode, "with")
- }
- panic("escaping " + n.String() + " is unimplemented")
-}
-
-// escapeAction escapes an action template node.
-func (e *escaper) escapeAction(c context, n *parse.ActionNode) context {
- if len(n.Pipe.Decl) != 0 {
- // A local variable assignment, not an interpolation.
- return c
- }
- c = nudge(c)
- // Check for disallowed use of predefined escapers in the pipeline.
- for pos, idNode := range n.Pipe.Cmds {
- node, ok := idNode.Args[0].(*parse.IdentifierNode)
- if !ok {
- // A predefined escaper "esc" will never be found as an identifier in a
- // Chain or Field node, since:
- // - "esc.x ..." is invalid, since predefined escapers return strings, and
- // strings do not have methods, keys or fields.
- // - "... .esc" is invalid, since predefined escapers are global functions,
- // not methods or fields of any types.
- // Therefore, it is safe to ignore these two node types.
- continue
- }
- ident := node.Ident
- if _, ok := predefinedEscapers[ident]; ok {
- if pos < len(n.Pipe.Cmds)-1 ||
- c.state == stateAttr && c.delim == delimSpaceOrTagEnd && ident == "html" {
- return context{
- state: stateError,
- err: errorf(ErrPredefinedEscaper, n, n.Line, "predefined escaper %q disallowed in template", ident),
- }
- }
- }
- }
- switch c.state {
- case stateError:
- return c
- case stateAttrName, stateTag:
- c.state = stateAttrName
- }
- // TODO: integrate sanitizerForContext into escapeAction.
- s, err := sanitizerForContext(c)
- if err != nil {
- return context{
- state: stateError,
- // TODO: return sanitization-specific errors.
- err: errorf(ErrEscapeAction, n, n.Line, "cannot escape action %v: %s", n, err),
- }
- }
- e.editActionNode(n, s)
- return c
-}
-
-// ensurePipelineContains ensures that the pipeline ends with the commands with
-// the identifiers in s in order. If the pipeline ends with a predefined escaper
-// (i.e. "html" or "urlquery"), merge it with the identifiers in s.c
-func ensurePipelineContains(p *parse.PipeNode, s []string) {
- if len(s) == 0 {
- // Do not rewrite pipeline if we have no escapers to insert.
- return
- }
- // Precondition: p.Cmds contains at most one predefined escaper and the
- // escaper will be present at p.Cmds[len(p.Cmds)-1]. This precondition is
- // always true because of the checks in escapeAction.
- pipelineLen := len(p.Cmds)
- if pipelineLen > 0 {
- lastCmd := p.Cmds[pipelineLen-1]
- if idNode, ok := lastCmd.Args[0].(*parse.IdentifierNode); ok {
- if esc := idNode.Ident; predefinedEscapers[esc] {
- // Pipeline ends with a predefined escaper.
- if len(p.Cmds) == 1 && len(lastCmd.Args) > 1 {
- // Special case: pipeline is of the form {{ esc arg1 arg2 ... argN }},
- // where esc is the predefined escaper, and arg1...argN are its arguments.
- // Convert this into the equivalent form
- // {{ _eval_args_ arg1 arg2 ... argN | esc }}, so that esc can be easily
- // merged with the escapers in s.
- lastCmd.Args[0] = parse.NewIdentifier(evalArgsFuncName).SetTree(nil).SetPos(lastCmd.Args[0].Position())
- p.Cmds = append(p.Cmds, newIdentCmd(esc, p.Position()))
- pipelineLen++
- }
- // If any of the commands in s that we are about to insert is equivalent
- // to the predefined escaper, use the predefined escaper instead.
- dup := false
- for i, escaper := range s {
- if escFnsEq(esc, escaper) {
- s[i] = idNode.Ident
- dup = true
- }
- }
- if dup {
- // The predefined escaper will already be inserted along with the
- // escapers in s, so do not copy it to the rewritten pipeline.
- pipelineLen--
- }
- }
- }
- }
- // Rewrite the pipeline, creating the escapers in s at the end of the pipeline.
- newCmds := make([]*parse.CommandNode, pipelineLen, pipelineLen+len(s))
- copy(newCmds, p.Cmds)
- for _, name := range s {
- newCmds = append(newCmds, newIdentCmd(name, p.Position()))
- }
- p.Cmds = newCmds
-}
-
-// predefinedEscapers contains template predefined escapers that are equivalent
-// to some contextual escapers. Keep in sync with equivEscapers.
-var predefinedEscapers = map[string]bool{
- "html": true,
- "urlquery": true,
-}
-
-// equivEscapers matches contextual escapers to equivalent predefined
-// template escapers.
-var equivEscapers = map[string]string{
- // The following pairs of HTML escapers provide equivalent security
- // guarantees, since they all escape '\000', '\'', '"', '&', '<', and '>'.
- sanitizeHTMLFuncName: "html",
- sanitizeRCDATAFuncName: "html",
- // These two URL escapers produce URLs safe for embedding in a URL query by
- // percent-encoding all the reserved characters specified in RFC 3986 Section
- // 2.2
- queryEscapeURLFuncName: "urlquery",
- // The normalizer function is not actually equivalent to urlquery; urlquery is
- // stricter as it escapes reserved characters (e.g. '#'), while the normalizer
- // function does not. It is therefore only safe to replace the normalizer with
- // with urlquery (this happens in ensurePipelineContains), but not the other
- // way around. We keep this entry around to preserve the behavior of templates
- // written before Go 1.9, which might depend on this substitution taking place.
- normalizeURLFuncName: "urlquery",
-}
-
-// escFnsEq reports whether the two escaping functions are equivalent.
-func escFnsEq(a, b string) bool {
- return normalizeEscFn(a) == normalizeEscFn(b)
-}
-
-// normalizeEscFn(a) is equal to normalizeEscFn(b) for any pair of names of
-// escaper functions a and b that are equivalent.
-func normalizeEscFn(e string) string {
- if norm := equivEscapers[e]; norm != "" {
- return norm
- }
- return e
-}
-
-// newIdentCmd produces a command containing a single identifier node.
-func newIdentCmd(identifier string, pos parse.Pos) *parse.CommandNode {
- return &parse.CommandNode{
- NodeType: parse.NodeCommand,
- Args: []parse.Node{parse.NewIdentifier(identifier).SetTree(nil).SetPos(pos)}, // TODO: SetTree.
- Pos: pos,
- }
-}
-
-// nudge returns the context that would result from following empty string
-// transitions from the input context.
-// For example, parsing:
-// `<a href=`
-// will end in context{stateBeforeValue, AttrURL}, but parsing one extra rune:
-// `<a href=x`
-// will end in context{stateURL, delimSpaceOrTagEnd, ...}.
-// There are two transitions that happen when the 'x' is seen:
-// (1) Transition from a before-value state to a start-of-value state without
-// consuming any character.
-// (2) Consume 'x' and transition past the first value character.
-// In this case, nudging produces the context after (1) happens.
-func nudge(c context) context {
- switch c.state {
- case stateTag:
- // In `<foo {{.}}`, the action should emit an attribute.
- c.state = stateAttrName
- case stateBeforeValue:
- // In `<foo bar={{.}}`, the action is an undelimited value.
- c.state, c.delim = stateAttr, delimSpaceOrTagEnd
- case stateAfterName:
- // In `<foo bar {{.}}`, the action is an attribute name.
- c.state = stateAttrName
- }
- return c
-}
-
-// join joins the two contexts of a branch template node. The result is an
-// error context if either of the input contexts are error contexts, or if the
-// input contexts differ.
-func join(a, b context, node parse.Node, nodeName string) context {
- if a.state == stateError {
- return a
- }
- if b.state == stateError {
- return b
- }
-
- // Accumulate the result of context-joining elements and attributes in a, since the
- // contents of a are always returned.
- a.element.names = joinNames(a.element.name, b.element.name, a.element.names, b.element.names)
- a.attr.names = joinNames(a.attr.name, b.attr.name, a.attr.names, b.attr.names)
- if a.attr.value != b.attr.value {
- a.attr.ambiguousValue = true
- }
-
- if a.eq(b) {
- return a
- }
-
- c := a
- c.element.name = b.element.name
- if c.eq(b) {
- // The contexts differ only by their element names. The element names from the conditional
- // branches that are accumulated in c.element.names will be checked during action sanitization
- // to ensure that they do not lead to different sanitization contexts.
- return c
- }
-
- c = a
- c.attr.name = b.attr.name
- if c.eq(b) {
- // The contexts differ only by their attribute name. The attribute names from the conditional
- // branches that are accumulated in c.attr.names will be checked during action sanitization
- // to ensure that they do not lead to different sanitization contexts.
- return c
- }
-
- // Allow a nudged context to join with an unnudged one.
- // This means that
- // <p title={{if .C}}{{.}}{{end}}
- // ends in an unquoted value state even though the else branch
- // ends in stateBeforeValue.
- if c, d := nudge(a), nudge(b); !(c.eq(a) && d.eq(b)) {
- if e := join(c, d, node, nodeName); e.state != stateError {
- return e
- }
- }
-
- return context{
- state: stateError,
- err: errorf(ErrBranchEnd, node, 0, "{{%s}} branches end in different contexts: %v, %v", nodeName, a, b),
- }
-}
-
-// joinNames returns the slice of all possible names that an element or attr could
-// assume after context joining the element or attr containing aName and aNames with the
-// element or attr containing bName and bNames.
-func joinNames(aName, bName string, aNames, bNames []string) []string {
- var ret []string
- if aName != bName {
- ret = append(ret, aName, bName)
- }
- aNamesSet := make(map[string]bool)
- for _, name := range aNames {
- aNamesSet[name] = true
- }
- for _, name := range bNames {
- if !aNamesSet[name] {
- ret = append(ret, name)
- }
- }
- return ret
-}
-
-// escapeBranch escapes a branch template node: "if", "range" and "with".
-func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) context {
- c0 := e.escapeList(c, n.List)
- if nodeName == "range" && c0.state != stateError {
- // The "true" branch of a "range" node can execute multiple times.
- // We check that executing n.List once results in the same context
- // as executing n.List twice.
- c1, _ := e.escapeListConditionally(c0, n.List, nil)
- c0 = join(c0, c1, n, nodeName)
- if c0.state == stateError {
- // Make clear that this is a problem on loop re-entry
- // since developers tend to overlook that branch when
- // debugging templates.
- c0.err.Line = n.Line
- c0.err.Description = "on range loop re-entry: " + c0.err.Description
- return c0
- }
- }
- c1 := e.escapeList(c, n.ElseList)
- return join(c0, c1, n, nodeName)
-}
-
-// escapeList escapes a list template node.
-func (e *escaper) escapeList(c context, n *parse.ListNode) context {
- if n == nil {
- return c
- }
- for _, m := range n.Nodes {
- c = e.escape(c, m)
- }
- return c
-}
-
-// escapeListConditionally escapes a list node but only preserves edits and
-// inferences in e if the inferences and output context satisfy filter.
-// It returns the best guess at an output context, and the result of the filter
-// which is the same as whether e was updated.
-func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, filter func(*escaper, context) bool) (context, bool) {
- e1 := makeEscaper(e.ns)
- // Make type inferences available to f.
- for k, v := range e.output {
- e1.output[k] = v
- }
- c = e1.escapeList(c, n)
- ok := filter != nil && filter(&e1, c)
- if ok {
- // Copy inferences and edits from e1 back into e.
- for k, v := range e1.output {
- e.output[k] = v
- }
- for k, v := range e1.derived {
- e.derived[k] = v
- }
- for k, v := range e1.called {
- e.called[k] = v
- }
- for k, v := range e1.actionNodeEdits {
- e.editActionNode(k, v)
- }
- for k, v := range e1.templateNodeEdits {
- e.editTemplateNode(k, v)
- }
- for k, v := range e1.textNodeEdits {
- e.editTextNode(k, v)
- }
- }
- return c, ok
-}
-
-// escapeTemplate escapes a {{template}} call node.
-func (e *escaper) escapeTemplate(c context, n *parse.TemplateNode) context {
- c, name := e.escapeTree(c, n, n.Name, n.Line)
- if name != n.Name {
- e.editTemplateNode(n, name)
- }
- return c
-}
-
-// mangle produces an identifier that includes a suffix that distinguishes it
-// from template names mangled with different contexts.
-func mangle(c context, templateName string) string {
- // The mangled name for the default context is the input templateName.
- if c.state == stateText {
- return templateName
- }
- s := templateName + "$htmltemplate_" + c.state.String()
- if c.delim != 0 {
- s += "_" + c.delim.String()
- }
- if c.attr.name != "" {
- s += "_" + c.attr.String()
- }
- if c.element.name != "" {
- s += "_" + c.element.String()
- }
- return s
-}
-
-// escapeTree escapes the named template starting in the given context as
-// necessary and returns its output context.
-func (e *escaper) escapeTree(c context, node parse.Node, name string, line int) (context, string) {
- // Mangle the template name with the input context to produce a reliable
- // identifier.
- dname := mangle(c, name)
- e.called[dname] = true
- if out, ok := e.output[dname]; ok {
- // Already escaped.
- return out, dname
- }
- t := e.template(name)
- if t == nil {
- // Two cases: The template exists but is empty, or has never been mentioned at
- // all. Distinguish the cases in the error messages.
- if e.ns.set[name] != nil {
- return context{
- state: stateError,
- err: errorf(ErrNoSuchTemplate, node, line, "%q is an incomplete or empty template", name),
- }, dname
- }
- return context{
- state: stateError,
- err: errorf(ErrNoSuchTemplate, node, line, "no such template %q", name),
- }, dname
- }
- if dname != name {
- // Use any template derived during an earlier call to escapeTemplate
- // with different top level templates, or clone if necessary.
- dt := e.template(dname)
- if dt == nil {
- dt = template.New(dname)
- dt.Tree = t.Tree.Copy()
- dt.Tree.Name = dname
- e.derived[dname] = dt
- }
- t = dt
- }
- return e.computeOutCtx(c, t), dname
-}
-
-// computeOutCtx takes a template and its start context and computes the output
-// context while storing any inferences in e.
-func (e *escaper) computeOutCtx(c context, t *template.Template) context {
- // Propagate context over the body.
- c1, ok := e.escapeTemplateBody(c, t)
- if !ok {
- // Look for a fixed point by assuming c1 as the output context.
- if c2, ok2 := e.escapeTemplateBody(c1, t); ok2 {
- c1, ok = c2, true
- }
- // Use c1 as the error context if neither assumption worked.
- }
- if !ok && c1.state != stateError {
- return context{
- state: stateError,
- err: errorf(ErrOutputContext, t.Tree.Root, 0, "cannot compute output context for template %s", t.Name()),
- }
- }
- return c1
-}
-
-// escapeTemplateBody escapes the given template assuming the given output
-// context, and returns the best guess at the output context and whether the
-// assumption was correct.
-func (e *escaper) escapeTemplateBody(c context, t *template.Template) (context, bool) {
- filter := func(e1 *escaper, c1 context) bool {
- if c1.state == stateError {
- // Do not update the input escaper, e.
- return false
- }
- if !e1.called[t.Name()] {
- // If t is not recursively called, then c1 is an
- // accurate output context.
- return true
- }
- // c1 is accurate if it matches our assumed output context.
- return c.eq(c1)
- }
- // We need to assume an output context so that recursive template calls
- // take the fast path out of escapeTree instead of infinitely recursing.
- // Naively assuming that the input context is the same as the output
- // works >90% of the time.
- e.output[t.Name()] = c
- return e.escapeListConditionally(c, t.Tree.Root, filter)
-}
-
-// delimEnds maps each delim to a string of characters that terminate it.
-var delimEnds = [...]string{
- delimDoubleQuote: `"`,
- delimSingleQuote: "'",
- // Determined empirically by running the below in various browsers.
- // var div = document.createElement("DIV");
- // for (var i = 0; i < 0x10000; ++i) {
- // div.innerHTML = "<span title=x" + String.fromCharCode(i) + "-bar>";
- // if (div.getElementsByTagName("SPAN")[0].title.indexOf("bar") < 0)
- // document.write("<p>U+" + i.toString(16));
- // }
- delimSpaceOrTagEnd: " \t\n\f\r>",
-}
-
-var doctypeBytes = []byte("<!DOCTYPE")
-
-// escapeText escapes a text template node.
-func (e *escaper) escapeText(c context, n *parse.TextNode) context {
- s, written, i, b := n.Text, 0, 0, new(bytes.Buffer)
- if e.ns.cspCompatible && bytes.Contains(s, []byte("javascript:")) {
- // This substring search is not perfect, but it is unlikely that this substring will
- // exist in template text for any other reason than to specify a javascript URI.
- return context{
- state: stateError,
- err: errorf(ErrCSPCompatibility, n, 0, `"javascript:" URI disallowed for CSP compatibility`),
- }
- }
- for i != len(s) {
- if e.ns.cspCompatible && strings.HasPrefix(c.attr.name, "on") {
- return context{
- state: stateError,
- err: errorf(ErrCSPCompatibility, n, 0, "inline event handler %q is disallowed for CSP compatibility", c.attr.name),
- }
- }
- c1, nread := contextAfterText(c, s[i:])
- i1 := i + nread
- sc, err := sanitizationContextForElementContent(c.element.name)
- if c.state == stateText || err == nil && sc == sanitizationContextRCDATA {
- end := i1
- if c1.state != c.state {
- for j := end - 1; j >= i; j-- {
- if s[j] == '<' {
- end = j
- break
- }
- }
- }
- for j := i; j < end; j++ {
- if s[j] == '<' && !bytes.HasPrefix(bytes.ToUpper(s[j:]), doctypeBytes) {
- b.Write(s[written:j])
- b.WriteString("&lt;")
- written = j + 1
- }
- }
- } else if isComment(c.state) && c.delim == delimNone {
- written = i1
- }
- if c.state == stateSpecialElementBody && c.element.name == "script" {
- if err := isJsTemplateBalanced(bytes.NewBuffer(s)); err != nil {
- return context{
- state: stateError,
- err: errorf(ErrUnbalancedJsTemplate, n, 0, "Mixing template systems can cause security vulnerabilites. Therefore, there can be no safehtml/template insertion points or actions inside an ES6 template, and all ES6 templates must be closed: %v", err.Error()),
- }
- }
- }
-
- if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone {
- // Preserve the portion between written and the comment start.
- cs := i1 - 2
- if c1.state == stateHTMLCmt {
- // "<!--" instead of "/*" or "//"
- cs -= 2
- }
- b.Write(s[written:cs])
- written = i1
- }
- if i == i1 && c.state == c1.state {
- panic(fmt.Sprintf("infinite loop from %v to %v on %q..%q", c, c1, s[:i], s[i:]))
- }
- c, i = c1, i1
- }
-
- if written != 0 && c.state != stateError {
- if !isComment(c.state) || c.delim != delimNone {
- b.Write(n.Text[written:])
- }
- e.editTextNode(n, b.Bytes())
- }
- return c
-}
-
-// contextAfterText starts in context c, consumes some tokens from the front of
-// s, then returns the context after those tokens and the unprocessed suffix.
-func contextAfterText(c context, s []byte) (context, int) {
- if c.delim == delimNone {
- c1, i := tSpecialTagEnd(c, s)
- if i == 0 {
- // A special end tag (`</script>`) has been seen and
- // all content preceding it has been consumed.
- return c1, 0
- }
- // Consider all content up to any end tag.
- return transitionFunc[c.state](c, s[:i])
- }
-
- // We are at the beginning of an attribute value.
-
- i := bytes.IndexAny(s, delimEnds[c.delim])
- if i == -1 {
- i = len(s)
- }
- if c.delim == delimSpaceOrTagEnd {
- // http://www.w3.org/TR/html5/syntax.html#attribute-value-(unquoted)-state
- // lists the runes below as error characters.
- // Error out because HTML parsers may differ on whether
- // "<a id= onclick=f(" ends inside id's or onclick's value,
- // "<a class=`foo " ends inside a value,
- // "<a style=font:'Arial'" needs open-quote fixup.
- // IE treats '`' as a quotation character.
- if j := bytes.IndexAny(s[:i], "\"'<=`"); j >= 0 {
- return context{
- state: stateError,
- err: errorf(ErrBadHTML, nil, 0, "%q in unquoted attr: %q", s[j:j+1], s[:i]),
- }, len(s)
- }
- }
- if i == len(s) {
- c.attr.value += string(s)
- // Remain inside the attribute.
- // Decode the value so non-HTML rules can easily handle
- // <button onclick="alert(&quot;Hi!&quot;)">
- // without having to entity decode token boundaries.
- for u := []byte(html.UnescapeString(string(s))); len(u) != 0; {
- c1, i1 := transitionFunc[c.state](c, u)
- c, u = c1, u[i1:]
- }
- return c, len(s)
- }
-
- // On exiting an attribute, we discard all state information
- // except the state, element, scriptType, and linkRel.
- ret := context{
- state: stateTag,
- element: c.element,
- scriptType: c.scriptType,
- linkRel: c.linkRel,
- }
- // Save the script element's type attribute value if we are parsing it for the first time.
- if c.state == stateAttr && c.element.name == "script" && c.attr.name == "type" {
- ret.scriptType = strings.ToLower(string(s[:i]))
- }
- // Save the link element's rel attribute value if we are parsing it for the first time.
- if c.state == stateAttr && c.element.name == "link" && c.attr.name == "rel" {
- ret.linkRel = " " + strings.Join(strings.Fields(strings.TrimSpace(strings.ToLower(string(s[:i])))), " ") + " "
- }
- if c.delim != delimSpaceOrTagEnd {
- // Consume any quote.
- i++
- }
- return ret, i
-}
-
-// editActionNode records a change to an action pipeline for later commit.
-func (e *escaper) editActionNode(n *parse.ActionNode, cmds []string) {
- if _, ok := e.actionNodeEdits[n]; ok {
- panic(fmt.Sprintf("node %s shared between templates", n))
- }
- e.actionNodeEdits[n] = cmds
-}
-
-// editTemplateNode records a change to a {{template}} callee for later commit.
-func (e *escaper) editTemplateNode(n *parse.TemplateNode, callee string) {
- if _, ok := e.templateNodeEdits[n]; ok {
- panic(fmt.Sprintf("node %s shared between templates", n))
- }
- e.templateNodeEdits[n] = callee
-}
-
-// editTextNode records a change to a text node for later commit.
-func (e *escaper) editTextNode(n *parse.TextNode, text []byte) {
- if _, ok := e.textNodeEdits[n]; ok {
- panic(fmt.Sprintf("node %s shared between templates", n))
- }
- e.textNodeEdits[n] = text
-}
-
-// commit applies changes to actions and template calls needed to contextually
-// autoescape content and adds any derived templates to the set.
-func (e *escaper) commit() {
- for name := range e.output {
- e.template(name).Funcs(funcs)
- }
- // Any template from the name space associated with this escaper can be used
- // to add derived templates to the underlying text/template name space.
- tmpl := e.arbitraryTemplate()
- for _, t := range e.derived {
- if _, err := tmpl.text.AddParseTree(t.Name(), t.Tree); err != nil {
- panic("error adding derived template")
- }
- }
- for n, s := range e.actionNodeEdits {
- ensurePipelineContains(n.Pipe, s)
- }
- for n, name := range e.templateNodeEdits {
- n.Name = name
- }
- for n, s := range e.textNodeEdits {
- n.Text = s
- }
- // Reset state that is specific to this commit so that the same changes are
- // not re-applied to the template on subsequent calls to commit.
- e.called = make(map[string]bool)
- e.actionNodeEdits = make(map[*parse.ActionNode][]string)
- e.templateNodeEdits = make(map[*parse.TemplateNode]string)
- e.textNodeEdits = make(map[*parse.TextNode][]byte)
-}
-
-// template returns the named template given a mangled template name.
-func (e *escaper) template(name string) *template.Template {
- // Any template from the name space associated with this escaper can be used
- // to look up templates in the underlying text/template name space.
- t := e.arbitraryTemplate().text.Lookup(name)
- if t == nil {
- t = e.derived[name]
- }
- return t
-}
-
-// arbitraryTemplate returns an arbitrary template from the name space
-// associated with e and panics if no templates are found.
-func (e *escaper) arbitraryTemplate() *Template {
- for _, t := range e.ns.set {
- return t
- }
- panic("no templates in name space")
-}
-
-var (
- errorType = reflect.TypeOf((*error)(nil)).Elem()
- fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
-)
-
-// indirectToStringerOrError returns the value, after dereferencing as many times
-// as necessary to reach the base type (or nil) or an implementation of fmt.Stringer
-// or error,
-func indirectToStringerOrError(a interface{}) interface{} {
- if a == nil {
- return nil
- }
- v := reflect.ValueOf(a)
- for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
- v = v.Elem()
- }
- return v.Interface()
-}
-
-var (
- jsTemplateSeparator = []byte("`")
- jsTemplateExprStart = []byte("${")
- jsTemplateExprEnd = []byte("}")
-)
-
-// Determine if a string has unbalanced (open) JS templates.
-func isJsTemplateBalanced(s *bytes.Buffer) error {
- for {
- index := bytes.Index(s.Bytes(), jsTemplateSeparator)
- if index == -1 {
- return nil
- }
- s.Next(index + 1)
- err := consumeJsTemplate(s)
- if err != nil {
- return err
- }
- }
-}
-
-// s is a JS template string (without the opening `); this function consumes s up to
-// the matching closing `.
-func consumeJsTemplate(s *bytes.Buffer) error {
- for {
- templateEnd := bytes.Index(s.Bytes(), jsTemplateSeparator)
- exprStart := bytes.Index(s.Bytes(), jsTemplateExprStart)
- if templateEnd == -1 {
- return fmt.Errorf("Missing closing ` in JS template")
- }
- if exprStart != -1 && exprStart < templateEnd {
- err := consumeJsTemplateExpr(s)
- if err != nil {
- return err
- }
- return consumeJsTemplate(s)
- } else {
- // The template expression occurs after this template, e.g. "`foo``bar${test}`".
- s.Next(templateEnd + 1)
- return nil
- }
- }
-}
-
-// s is a Js Template expression (starting with "${"). This function consumes up to and including the matching closing "}".
-func consumeJsTemplateExpr(s *bytes.Buffer) error {
- for {
- exprEnd := bytes.Index(s.Bytes(), jsTemplateExprEnd)
- if exprEnd == -1 {
- // Template expression isn't closed
- return fmt.Errorf("Missing closing } in JS template")
- }
- nestedTemplateStart := bytes.Index(s.Bytes(), jsTemplateSeparator)
- if nestedTemplateStart != -1 && nestedTemplateStart < exprEnd {
- s.Next(nestedTemplateStart + 1)
- err := consumeJsTemplate(s)
- if err != nil {
- return err
- }
- return consumeJsTemplateExpr(s)
- } else {
- s.Next(exprEnd + 1)
- return nil
- }
- }
-}
diff --git a/vendor/github.com/google/safehtml/template/init.go b/vendor/github.com/google/safehtml/template/init.go
deleted file mode 100644
index c9fa2de1d..000000000
--- a/vendor/github.com/google/safehtml/template/init.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package template
-
-import (
- "github.com/google/safehtml/internal/template/raw"
-)
-
-// The following functions are used by package uncheckedconversions
-// (via package raw) to create TrustedSource and TrustedTemplate values
-// from plain strings.
-
-func trustedSourceRaw(s string) TrustedSource {
- return TrustedSource{s}
-}
-
-func trustedTemplateRaw(s string) TrustedTemplate {
- return TrustedTemplate{s}
-}
-
-func init() {
- raw.TrustedSource = trustedSourceRaw
- raw.TrustedTemplate = trustedTemplateRaw
-}
diff --git a/vendor/github.com/google/safehtml/template/sanitize.go b/vendor/github.com/google/safehtml/template/sanitize.go
deleted file mode 100644
index c75e345e1..000000000
--- a/vendor/github.com/google/safehtml/template/sanitize.go
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package template
-
-import (
- "fmt"
- "regexp"
- "strings"
-)
-
-// sanitizerForContext returns an ordered list of function names that will be called to
-// sanitize data values found in the HTML context defined by c.
-func sanitizerForContext(c context) ([]string, error) {
- switch c.state {
- case stateTag, stateAttrName, stateAfterName:
- return nil, fmt.Errorf("actions must not affect element or attribute names")
- case stateHTMLCmt:
- return []string{sanitizeHTMLCommentFuncName}, nil
- }
- if len(c.element.names) == 0 && c.element.name == "" && c.state == stateText {
- // Not in an HTML element.
- return []string{sanitizeHTMLFuncName}, nil
- }
- if c.attr.name != "" || len(c.attr.names) > 0 {
- // We are in an attribute value context.
- if c.delim != delimDoubleQuote && c.delim != delimSingleQuote {
- // TODO: consider disallowing single-quoted or unquoted attribute values completely, even in hardcoded template text.
- return nil, fmt.Errorf("unquoted attribute values disallowed")
- }
- return sanitizersForAttributeValue(c)
- }
- // Otherwise, we are in an element content context.
- elementContentSanitizer, err := sanitizerForElementContent(c)
- return appendIfNotEmpty([]string{}, elementContentSanitizer), err
-}
-
-// appendIfNotEmpty appends the given strings that are non-empty to the given slice.
-func appendIfNotEmpty(slice []string, strings ...string) []string {
- for _, s := range strings {
- if s != "" {
- slice = append(slice, s)
- }
- }
- return slice
-}
-
-// sanitizersForAttributeValue returns a list of names of functions that will be
-// called in order to sanitize data values found the HTML attribtue value context c.
-func sanitizersForAttributeValue(c context) ([]string, error) {
- // Ensure that all combinations of element and attribute names for this context results
- // in the same attribute value sanitization context.
- var elems, attrs []string
- if len(c.element.names) == 0 {
- elems = []string{c.element.name}
- } else {
- elems = c.element.names
- }
- if len(c.attr.names) == 0 {
- attrs = []string{c.attr.name}
- } else {
- attrs = c.attr.names
- }
- var sc0 sanitizationContext
- var elem0, attr0 string
- for i, elem := range elems {
- for j, attr := range attrs {
- sc, err := sanitizationContextForAttrVal(elem, attr, c.linkRel)
- if err != nil {
- if len(elems) == 1 && len(attrs) == 1 {
- return nil, err
- }
- return nil, fmt.Errorf(`conditional branch with {element=%q, attribute=%q} results in sanitization error: %s`, elem, attr, err)
- }
- if i == 0 && j == 0 {
- sc0, elem0, attr0 = sc, elem, attr
- continue
- }
- if sc != sc0 {
- return nil, fmt.Errorf(
- `conditional branches end in different attribute value sanitization contexts: {element=%q, attribute=%q} has sanitization context %q, {element=%q, attribute=%q} has sanitization context %q`,
- elem0, attr0, sc0, elem, attr, sc)
- }
- }
- }
- if sc0.isEnum() && c.attr.value != "" {
- return nil, fmt.Errorf("partial substitutions are disallowed in the %q attribute value context of a %q element", c.attr.name, c.element.name)
- }
- if sc0 == sanitizationContextStyle && c.attr.value != "" {
- if err := validateDoesNotEndsWithCharRefPrefix(c.attr.value); err != nil {
- return nil, fmt.Errorf("action cannot be interpolated into the %q attribute value of this %q element: %s", c.attr.name, c.element.name, err)
- }
- }
- // ret is a stack of sanitizer names that will be built in reverse.
- var ret []string
- // All attribute values must be HTML-escaped at run time by sanitizeHTML to eliminate
- // any HTML markup that can cause the HTML parser to transition out of the attribute value state.
- // These attribute values will later be HTML-unescaped by the HTML parser in the browser.
- ret = append(ret, sanitizeHTMLFuncName)
- sanitizer := sc0.sanitizerName()
- if !sc0.isURLorTrustedResourceURL() {
- return reverse(appendIfNotEmpty(ret, sanitizer)), nil
- }
- urlAttrValPrefix := c.attr.value
- if urlAttrValPrefix == "" {
- // Attribute value prefixes in URL or TrustedResourceURL sanitization contexts
- // must sanitized and normalized.
- return reverse(appendIfNotEmpty(ret, normalizeURLFuncName, sanitizer)), nil
- }
- // Action occurs after a URL or TrustedResourceURL prefix.
- if c.attr.ambiguousValue {
- return nil, fmt.Errorf("actions must not occur after an ambiguous URL prefix in the %q attribute value context of a %q element", c.attr.name, c.element.name)
- }
- validator, ok := urlPrefixValidators[sc0]
- if !ok {
- return nil, fmt.Errorf("cannot validate attribute value prefix %q in the %q sanitization context", c.attr.value, sc0)
- }
- if err := validator(c.attr.value); err != nil {
- return nil, fmt.Errorf("action cannot be interpolated into the %q URL attribute value of this %q element: %s", c.attr.name, c.element.name, err)
- }
- switch {
- case sc0 == sanitizationContextTrustedResourceURL:
- // Untrusted data that occurs anywhere after TrustedResourceURL prefix must be query-escaped
- // to prevent the injection of any new path segments or URL components. Moreover, they must
- // not contain any ".." dot-segments.
- ret = append(ret, queryEscapeURLFuncName, validateTrustedResourceURLSubstitutionFuncName)
- case strings.ContainsAny(urlAttrValPrefix, "#?"):
- // For URLs, we only escape in the query or fragment part to prevent the injection of new query
- // parameters or fragments.
- ret = append(ret, queryEscapeURLFuncName)
- default:
- ret = append(ret, normalizeURLFuncName)
- }
- return reverse(ret), nil
-}
-
-// reverse reverses s and returns it.
-func reverse(s []string) []string {
- for head, tail := 0, len(s)-1; head < tail; head, tail = head+1, tail-1 {
- s[head], s[tail] = s[tail], s[head]
- }
- return s
-}
-
-// sanitizationContextForAttrVal returns the sanitization context for attr when it
-// appears within element.
-func sanitizationContextForAttrVal(element, attr, linkRel string) (sanitizationContext, error) {
- if element == "link" && attr == "href" {
- // Special case: safehtml.URL values are allowed in a link element's href attribute if that element's
- // rel attribute possesses certain values.
- relVals := strings.Fields(linkRel)
- for _, val := range relVals {
- if urlLinkRelVals[val] {
- return sanitizationContextTrustedResourceURLOrURL, nil
- }
- }
- }
- if dataAttributeNamePattern.MatchString(attr) {
- // Special case: data-* attributes are specified by HTML5 to hold custom data private to
- // the page or application; they should not be interpreted by browsers. Therefore, no
- // sanitization is required for these attribute values.
- return sanitizationContextNone, nil
- }
- if sc, ok := elementSpecificAttrValSanitizationContext[attr][element]; ok {
- return sc, nil
- }
- sc, isAllowedAttr := globalAttrValSanitizationContext[attr]
- _, isAllowedElement := elementContentSanitizationContext[element]
- if isAllowedAttr && (isAllowedElement || allowedVoidElements[element]) {
- // Only sanitize attributes that appear in elements whose semantics are known.
- // Thes attributes might have different semantics in other standard or custom
- // elements that our sanitization policy does not handle correctly.
- return sc, nil
- }
- return 0, fmt.Errorf("actions must not occur in the %q attribute value context of a %q element", attr, element)
-}
-
-// dataAttributeNamePattern matches valid data attribute names.
-// This pattern is conservative and matches only a subset of the valid names defined in
-// https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes
-var dataAttributeNamePattern = regexp.MustCompile(`^data-[a-z_][-a-z0-9_]*$`)
-
-// endsWithCharRefPrefixPattern matches strings that end in an incomplete
-// HTML character reference.
-//
-// See https://html.spec.whatwg.org/multipage/syntax.html#character-references.
-var endsWithCharRefPrefixPattern = regexp.MustCompile(
- `&(?:[[:alpha:]][[:alnum:]]*|#(?:[xX][[:xdigit:]]*|[[:digit:]]*))?$`)
-
-// validateDoesNotEndsWithCharRefPrefix returns an error only if the given prefix ends
-// with an incomplete HTML character reference.
-func validateDoesNotEndsWithCharRefPrefix(prefix string) error {
- if endsWithCharRefPrefixPattern.MatchString(prefix) {
- return fmt.Errorf(`prefix %q ends with an incomplete HTML character reference; did you mean "&amp;" instead of "&"?`, prefix)
- }
- return nil
-}
-
-// sanitizerForElementContent returns the name of the function that will be called
-// to sanitize data values found in the HTML element content context c.
-func sanitizerForElementContent(c context) (string, error) {
- // Ensure that all other possible element names for this context result in the same
- // element content sanitization context.
- var elems []string
- if len(c.element.names) == 0 {
- elems = []string{c.element.name}
- } else {
- elems = c.element.names
- }
- var sc0 sanitizationContext
- var elem0 string
- for i, elem := range elems {
- var sc sanitizationContext
- var err error
- if elem == "" {
- // Special case: an empty element name represents a context outside of a HTML element.
- sc = sanitizationContextHTML
- } else {
- sc, err = sanitizationContextForElementContent(elem)
- }
- if err != nil {
- if len(elems) == 1 {
- return "", err
- }
- return "", fmt.Errorf(`conditional branch with element %q results in sanitization error: %s`, elem, err)
- }
- if i == 0 {
- sc0, elem0 = sc, elem
- continue
- }
- if sc != sc0 {
- return "",
- fmt.Errorf(`conditional branches end in different element content sanitization contexts: element %q has sanitization context %q, element %q has sanitization context %q`,
- elem0, sc0, elem, sc)
- }
- }
- return sc0.sanitizerName(), nil
-}
-
-// sanitizationContextForElementContent returns the element content sanitization context for the given element.
-func sanitizationContextForElementContent(element string) (sanitizationContext, error) {
- sc, ok := elementContentSanitizationContext[element]
- if !ok {
- return 0, fmt.Errorf("actions must not occur in the element content context of a %q element", element)
- }
- return sc, nil
-}
-
-// sanitizeHTMLComment returns the empty string regardless of input.
-// Comment content does not correspond to any parsed structure or
-// human-readable content, so the simplest and most secure policy is to drop
-// content interpolated into comments.
-// This approach is equally valid whether or not static comment content is
-// removed from the template.
-func sanitizeHTMLComment(_ ...interface{}) string {
- return ""
-}
diff --git a/vendor/github.com/google/safehtml/template/sanitizers.go b/vendor/github.com/google/safehtml/template/sanitizers.go
deleted file mode 100644
index 782e931b8..000000000
--- a/vendor/github.com/google/safehtml/template/sanitizers.go
+++ /dev/null
@@ -1,599 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package template
-
-import (
- "fmt"
- "text/template"
-
- "github.com/google/safehtml/internal/safehtmlutil"
- "github.com/google/safehtml"
-)
-
-// sanitizationContext determines what type of sanitization to perform
-// on a template action.
-type sanitizationContext uint8
-
-const (
- _ = iota
- sanitizationContextAsyncEnum
- sanitizationContextDirEnum
- sanitizationContextHTML
- sanitizationContextHTMLValOnly
- sanitizationContextIdentifier
- sanitizationContextLoadingEnum
- sanitizationContextNone
- sanitizationContextRCDATA
- sanitizationContextScript
- sanitizationContextStyle
- sanitizationContextStyleSheet
- sanitizationContextTargetEnum
- sanitizationContextTrustedResourceURL
- sanitizationContextTrustedResourceURLOrURL
- sanitizationContextURL
- sanitizationContextURLSet
-)
-
-// String returns the string representation of sanitizationContext s.
-func (s sanitizationContext) String() string {
- if int(s) >= len(sanitizationContextInfo) {
- return fmt.Sprintf("invalid sanitization context %d", s)
- }
- return sanitizationContextInfo[s].name
-}
-
-// sanitizerName returns the name of the sanitizer to call in sanitizationContext s.
-// It returns an empty string if no sanitization is required in s.
-func (s sanitizationContext) sanitizerName() string {
- if int(s) >= len(sanitizationContextInfo) {
- return fmt.Sprintf("invalid sanitization context %d", s)
- }
- return sanitizationContextInfo[s].sanitizerName
-}
-
-// isEnum reports reports whether s is a sanitization context for enumerated values.
-func (s sanitizationContext) isEnum() bool {
- return s == sanitizationContextAsyncEnum || s == sanitizationContextDirEnum || s == sanitizationContextLoadingEnum || s == sanitizationContextTargetEnum
-}
-
-// isURLorTrustedResourceURL reports reports whether s is a sanitization context for URL or TrustedResourceURL values.
-func (s sanitizationContext) isURLorTrustedResourceURL() bool {
- return s == sanitizationContextTrustedResourceURL || s == sanitizationContextTrustedResourceURLOrURL || s == sanitizationContextURL
-}
-
-// sanitizationContextInfo[x] contains the name for sanitization context x and the
-// name of the sanitizer to call in that context.
-// If sanitizationContextInfo[x].sanitizerName is empty, then no sanitizer needs
-// to be called in x.
-var sanitizationContextInfo = [...]struct {
- name, sanitizerName string
-}{
- sanitizationContextAsyncEnum: {"AsyncEnum", sanitizeAsyncEnumFuncName},
- sanitizationContextDirEnum: {"DirEnum", sanitizeDirEnumFuncName},
- sanitizationContextHTML: {"HTML", sanitizeHTMLFuncName},
- sanitizationContextHTMLValOnly: {"HTMLValOnly", sanitizeHTMLValOnlyFuncName},
- sanitizationContextIdentifier: {"Identifier", sanitizeIdentifierFuncName},
- sanitizationContextLoadingEnum: {"LoadingEnum", sanitizeLoadingEnumFuncName},
- sanitizationContextNone: {"None", ""},
- sanitizationContextRCDATA: {"RCDATA", sanitizeRCDATAFuncName},
- sanitizationContextScript: {"Script", sanitizeScriptFuncName},
- sanitizationContextStyle: {"Style", sanitizeStyleFuncName},
- sanitizationContextStyleSheet: {"StyleSheet", sanitizeStyleSheetFuncName},
- sanitizationContextTargetEnum: {"TargetEnum", sanitizeTargetEnumFuncName},
- sanitizationContextTrustedResourceURL: {"TrustedResourceURL", sanitizeTrustedResourceURLFuncName},
- sanitizationContextTrustedResourceURLOrURL: {"TrustedResourceURLOrURL", sanitizeTrustedResourceURLOrURLFuncName},
- sanitizationContextURL: {"URL", sanitizeURLFuncName},
- sanitizationContextURLSet: {"URLSet", sanitizeURLSetFuncName},
-}
-
-var funcs = template.FuncMap{
- queryEscapeURLFuncName: safehtmlutil.QueryEscapeURL,
- normalizeURLFuncName: safehtmlutil.NormalizeURL,
- validateTrustedResourceURLSubstitutionFuncName: validateTrustedResourceURLSubstitution,
- evalArgsFuncName: evalArgs,
- sanitizeHTMLCommentFuncName: sanitizeHTMLComment,
- sanitizeAsyncEnumFuncName: sanitizeAsyncEnum,
- sanitizeDirEnumFuncName: sanitizeDirEnum,
- sanitizeHTMLFuncName: sanitizeHTML,
- sanitizeHTMLValOnlyFuncName: sanitizeHTMLValOnly,
- sanitizeIdentifierFuncName: sanitizeIdentifier,
- sanitizeLoadingEnumFuncName: sanitizeLoadingEnum,
- sanitizeRCDATAFuncName: sanitizeRCDATA,
- sanitizeScriptFuncName: sanitizeScript,
- sanitizeStyleFuncName: sanitizeStyle,
- sanitizeStyleSheetFuncName: sanitizeStyleSheet,
- sanitizeTargetEnumFuncName: sanitizeTargetEnum,
- sanitizeTrustedResourceURLFuncName: sanitizeTrustedResourceURL,
- sanitizeTrustedResourceURLOrURLFuncName: sanitizeTrustedResourceURLOrURL,
- sanitizeURLFuncName: sanitizeURL,
- sanitizeURLSetFuncName: sanitizeURLSet,
-}
-
-const (
- queryEscapeURLFuncName = "_queryEscapeURL"
- normalizeURLFuncName = "_normalizeURL"
- validateTrustedResourceURLSubstitutionFuncName = "_validateTrustedResourceURLSubstitution"
- evalArgsFuncName = "_evalArgs"
- sanitizeHTMLCommentFuncName = "_sanitizeHTMLComment"
- sanitizeAsyncEnumFuncName = "_sanitizeAsyncEnum"
- sanitizeDirEnumFuncName = "_sanitizeDirEnum"
- sanitizeHTMLFuncName = "_sanitizeHTML"
- sanitizeHTMLValOnlyFuncName = "_sanitizeHTMLValOnly"
- sanitizeIdentifierFuncName = "_sanitizeIdentifier"
- sanitizeLoadingEnumFuncName = "_sanitizeLoadingEnum"
- sanitizeRCDATAFuncName = "_sanitizeRCDATA"
- sanitizeScriptFuncName = "_sanitizeScript"
- sanitizeStyleFuncName = "_sanitizeStyle"
- sanitizeStyleSheetFuncName = "_sanitizeStyleSheet"
- sanitizeTargetEnumFuncName = "_sanitizeTargetEnum"
- sanitizeTrustedResourceURLFuncName = "_sanitizeTrustedResourceURL"
- sanitizeTrustedResourceURLOrURLFuncName = "_sanitizeTrustedResourceURLOrURL"
- sanitizeURLFuncName = "_sanitizeURL"
- sanitizeURLSetFuncName = "_sanitizeURLSet"
-)
-
-// urlLinkRelVals contains values for a link element's rel attribute that indicate that the same link
-// element's href attribute may contain a safehtml.URL value.
-var urlLinkRelVals = map[string]bool{
- "alternate": true,
- "author": true,
- "bookmark": true,
- "canonical": true,
- "cite": true,
- "dns-prefetch": true,
- "help": true,
- "icon": true,
- "license": true,
- "next": true,
- "preconnect": true,
- "prefetch": true,
- "preload": true,
- "prerender": true,
- "prev": true,
- "search": true,
- "subresource": true,
-}
-
-// elementSpecificAttrValSanitizationContext[x][y] is the sanitization context for
-// attribute x when it appears within element y.
-var elementSpecificAttrValSanitizationContext = map[string]map[string]sanitizationContext{
- "accept": {
- "input": sanitizationContextNone,
- },
- "action": {
- "form": sanitizationContextURL,
- },
- "defer": {
- "script": sanitizationContextNone,
- },
- "formaction": {
- "button": sanitizationContextURL,
- "input": sanitizationContextURL,
- },
- "formmethod": {
- "button": sanitizationContextNone,
- "input": sanitizationContextNone,
- },
- "href": {
- "a": sanitizationContextTrustedResourceURLOrURL,
- "area": sanitizationContextTrustedResourceURLOrURL,
- },
- "method": {
- "form": sanitizationContextNone,
- },
- "pattern": {
- "input": sanitizationContextNone,
- },
- "readonly": {
- "input": sanitizationContextNone,
- "textarea": sanitizationContextNone,
- },
- "src": {
- "audio": sanitizationContextTrustedResourceURLOrURL,
- "img": sanitizationContextTrustedResourceURLOrURL,
- "input": sanitizationContextTrustedResourceURLOrURL,
- "source": sanitizationContextTrustedResourceURLOrURL,
- "video": sanitizationContextTrustedResourceURLOrURL,
- },
- "srcdoc": {
- "iframe": sanitizationContextHTMLValOnly,
- },
-}
-
-// globalAttrValSanitizationContext[x] is the sanitization context for attribute x when
-// it appears within any element not in the key set of elementSpecificAttrValSanitizationContext[x].
-var globalAttrValSanitizationContext = map[string]sanitizationContext{
- "align": sanitizationContextNone,
- "alt": sanitizationContextNone,
- "aria-activedescendant": sanitizationContextIdentifier,
- "aria-atomic": sanitizationContextNone,
- "aria-autocomplete": sanitizationContextNone,
- "aria-busy": sanitizationContextNone,
- "aria-checked": sanitizationContextNone,
- "aria-controls": sanitizationContextIdentifier,
- "aria-current": sanitizationContextNone,
- "aria-disabled": sanitizationContextNone,
- "aria-dropeffect": sanitizationContextNone,
- "aria-expanded": sanitizationContextNone,
- "aria-haspopup": sanitizationContextNone,
- "aria-hidden": sanitizationContextNone,
- "aria-invalid": sanitizationContextNone,
- "aria-label": sanitizationContextNone,
- "aria-labelledby": sanitizationContextIdentifier,
- "aria-level": sanitizationContextNone,
- "aria-live": sanitizationContextNone,
- "aria-multiline": sanitizationContextNone,
- "aria-multiselectable": sanitizationContextNone,
- "aria-orientation": sanitizationContextNone,
- "aria-owns": sanitizationContextIdentifier,
- "aria-posinset": sanitizationContextNone,
- "aria-pressed": sanitizationContextNone,
- "aria-readonly": sanitizationContextNone,
- "aria-relevant": sanitizationContextNone,
- "aria-required": sanitizationContextNone,
- "aria-selected": sanitizationContextNone,
- "aria-setsize": sanitizationContextNone,
- "aria-sort": sanitizationContextNone,
- "aria-valuemax": sanitizationContextNone,
- "aria-valuemin": sanitizationContextNone,
- "aria-valuenow": sanitizationContextNone,
- "aria-valuetext": sanitizationContextNone,
- "async": sanitizationContextAsyncEnum,
- "autocapitalize": sanitizationContextNone,
- "autocomplete": sanitizationContextNone,
- "autocorrect": sanitizationContextNone,
- "autofocus": sanitizationContextNone,
- "autoplay": sanitizationContextNone,
- "bgcolor": sanitizationContextNone,
- "border": sanitizationContextNone,
- "cellpadding": sanitizationContextNone,
- "cellspacing": sanitizationContextNone,
- "checked": sanitizationContextNone,
- "cite": sanitizationContextURL,
- "class": sanitizationContextNone,
- "color": sanitizationContextNone,
- "cols": sanitizationContextNone,
- "colspan": sanitizationContextNone,
- "contenteditable": sanitizationContextNone,
- "controls": sanitizationContextNone,
- "datetime": sanitizationContextNone,
- "dir": sanitizationContextDirEnum,
- "disabled": sanitizationContextNone,
- "download": sanitizationContextNone,
- "draggable": sanitizationContextNone,
- "enctype": sanitizationContextNone,
- "face": sanitizationContextNone,
- "for": sanitizationContextIdentifier,
- "formenctype": sanitizationContextNone,
- "frameborder": sanitizationContextNone,
- "height": sanitizationContextNone,
- "hidden": sanitizationContextNone,
- "href": sanitizationContextTrustedResourceURL,
- "hreflang": sanitizationContextNone,
- "id": sanitizationContextIdentifier,
- "ismap": sanitizationContextNone,
- "itemid": sanitizationContextNone,
- "itemprop": sanitizationContextNone,
- "itemref": sanitizationContextNone,
- "itemscope": sanitizationContextNone,
- "itemtype": sanitizationContextNone,
- "label": sanitizationContextNone,
- "lang": sanitizationContextNone,
- "list": sanitizationContextIdentifier,
- "loading": sanitizationContextLoadingEnum,
- "loop": sanitizationContextNone,
- "max": sanitizationContextNone,
- "maxlength": sanitizationContextNone,
- "media": sanitizationContextNone,
- "min": sanitizationContextNone,
- "minlength": sanitizationContextNone,
- "multiple": sanitizationContextNone,
- "muted": sanitizationContextNone,
- "name": sanitizationContextIdentifier,
- "nonce": sanitizationContextNone,
- "open": sanitizationContextNone,
- "placeholder": sanitizationContextNone,
- "poster": sanitizationContextURL,
- "preload": sanitizationContextNone,
- "rel": sanitizationContextNone,
- "required": sanitizationContextNone,
- "reversed": sanitizationContextNone,
- "role": sanitizationContextNone,
- "rows": sanitizationContextNone,
- "rowspan": sanitizationContextNone,
- "selected": sanitizationContextNone,
- "shape": sanitizationContextNone,
- "size": sanitizationContextNone,
- "sizes": sanitizationContextNone,
- "slot": sanitizationContextNone,
- "span": sanitizationContextNone,
- "spellcheck": sanitizationContextNone,
- "src": sanitizationContextTrustedResourceURL,
- "srcset": sanitizationContextURLSet,
- "start": sanitizationContextNone,
- "step": sanitizationContextNone,
- "style": sanitizationContextStyle,
- "summary": sanitizationContextNone,
- "tabindex": sanitizationContextNone,
- "target": sanitizationContextTargetEnum,
- "title": sanitizationContextNone,
- "translate": sanitizationContextNone,
- "type": sanitizationContextNone,
- "valign": sanitizationContextNone,
- "value": sanitizationContextNone,
- "width": sanitizationContextNone,
- "wrap": sanitizationContextNone,
-}
-
-// elementContentSanitizationContext maps element names to element content sanitization contexts.
-var elementContentSanitizationContext = map[string]sanitizationContext{
- "a": sanitizationContextHTML,
- "abbr": sanitizationContextHTML,
- "address": sanitizationContextHTML,
- "article": sanitizationContextHTML,
- "aside": sanitizationContextHTML,
- "audio": sanitizationContextHTML,
- "b": sanitizationContextHTML,
- "bdi": sanitizationContextHTML,
- "bdo": sanitizationContextHTML,
- "blockquote": sanitizationContextHTML,
- "body": sanitizationContextHTML,
- "button": sanitizationContextHTML,
- "canvas": sanitizationContextHTML,
- "caption": sanitizationContextHTML,
- "center": sanitizationContextHTML,
- "cite": sanitizationContextHTML,
- "code": sanitizationContextHTML,
- "colgroup": sanitizationContextHTML,
- "command": sanitizationContextHTML,
- "data": sanitizationContextHTML,
- "datalist": sanitizationContextHTML,
- "dd": sanitizationContextHTML,
- "del": sanitizationContextHTML,
- "details": sanitizationContextHTML,
- "dfn": sanitizationContextHTML,
- "dialog": sanitizationContextHTML,
- "div": sanitizationContextHTML,
- "dl": sanitizationContextHTML,
- "dt": sanitizationContextHTML,
- "em": sanitizationContextHTML,
- "fieldset": sanitizationContextHTML,
- "figcaption": sanitizationContextHTML,
- "figure": sanitizationContextHTML,
- "font": sanitizationContextHTML,
- "footer": sanitizationContextHTML,
- "form": sanitizationContextHTML,
- "frame": sanitizationContextHTML,
- "frameset": sanitizationContextHTML,
- "h1": sanitizationContextHTML,
- "h2": sanitizationContextHTML,
- "h3": sanitizationContextHTML,
- "h4": sanitizationContextHTML,
- "h5": sanitizationContextHTML,
- "h6": sanitizationContextHTML,
- "head": sanitizationContextHTML,
- "header": sanitizationContextHTML,
- "html": sanitizationContextHTML,
- "i": sanitizationContextHTML,
- "iframe": sanitizationContextHTML,
- "ins": sanitizationContextHTML,
- "kbd": sanitizationContextHTML,
- "label": sanitizationContextHTML,
- "legend": sanitizationContextHTML,
- "lh": sanitizationContextHTML,
- "li": sanitizationContextHTML,
- "main": sanitizationContextHTML,
- "map": sanitizationContextHTML,
- "mark": sanitizationContextHTML,
- "menu": sanitizationContextHTML,
- "meter": sanitizationContextHTML,
- "nav": sanitizationContextHTML,
- "noscript": sanitizationContextHTML,
- "ol": sanitizationContextHTML,
- "optgroup": sanitizationContextHTML,
- "option": sanitizationContextHTML,
- "output": sanitizationContextHTML,
- "p": sanitizationContextHTML,
- "picture": sanitizationContextHTML,
- "pre": sanitizationContextHTML,
- "progress": sanitizationContextHTML,
- "q": sanitizationContextHTML,
- "rb": sanitizationContextHTML,
- "rp": sanitizationContextHTML,
- "rt": sanitizationContextHTML,
- "rtc": sanitizationContextHTML,
- "ruby": sanitizationContextHTML,
- "s": sanitizationContextHTML,
- "samp": sanitizationContextHTML,
- "script": sanitizationContextScript,
- "section": sanitizationContextHTML,
- "select": sanitizationContextHTML,
- "slot": sanitizationContextHTML,
- "small": sanitizationContextHTML,
- "span": sanitizationContextHTML,
- "strong": sanitizationContextHTML,
- "style": sanitizationContextStyleSheet,
- "sub": sanitizationContextHTML,
- "summary": sanitizationContextHTML,
- "sup": sanitizationContextHTML,
- "table": sanitizationContextHTML,
- "tbody": sanitizationContextHTML,
- "td": sanitizationContextHTML,
- "textarea": sanitizationContextRCDATA,
- "tfoot": sanitizationContextHTML,
- "th": sanitizationContextHTML,
- "thead": sanitizationContextHTML,
- "time": sanitizationContextHTML,
- "title": sanitizationContextRCDATA,
- "tr": sanitizationContextHTML,
- "u": sanitizationContextHTML,
- "ul": sanitizationContextHTML,
- "var": sanitizationContextHTML,
- "video": sanitizationContextHTML,
-}
-
-// allowedVoidElements is a set of names of void elements actions may appear in.
-var allowedVoidElements = map[string]bool{
- "area": true,
- "br": true,
- "col": true,
- "hr": true,
- "img": true,
- "input": true,
- "link": true,
- "param": true,
- "source": true,
- "track": true,
- "wbr": true,
-}
-
-var sanitizeAsyncEnumValues = map[string]bool{
- "async": true,
-}
-
-func sanitizeAsyncEnum(args ...interface{}) (string, error) {
- input := safehtmlutil.Stringify(args...)
- if sanitizeAsyncEnumValues[input] {
- return input, nil
- }
- return "", fmt.Errorf(`expected one of the following strings: ["async"]`)
-}
-
-var sanitizeDirEnumValues = map[string]bool{
- "auto": true,
- "ltr": true,
- "rtl": true,
-}
-
-func sanitizeDirEnum(args ...interface{}) (string, error) {
- input := safehtmlutil.Stringify(args...)
- if sanitizeDirEnumValues[input] {
- return input, nil
- }
- return "", fmt.Errorf(`expected one of the following strings: ["auto" "ltr" "rtl"]`)
-}
-
-func sanitizeHTML(args ...interface{}) (string, error) {
- if len(args) > 0 {
- if safeTypeValue, ok := safehtmlutil.Indirect(args[0]).(safehtml.HTML); ok {
- return safeTypeValue.String(), nil
- }
- }
- input := safehtmlutil.Stringify(args...)
- return safehtml.HTMLEscaped(input).String(), nil
-}
-
-func sanitizeHTMLValOnly(args ...interface{}) (string, error) {
- if len(args) > 0 {
- if safeTypeValue, ok := safehtmlutil.Indirect(args[0]).(safehtml.HTML); ok {
- return safeTypeValue.String(), nil
- }
- }
- return "", fmt.Errorf(`expected a safehtml.HTML value`)
-}
-
-func sanitizeIdentifier(args ...interface{}) (string, error) {
- if len(args) > 0 {
- if safeTypeValue, ok := safehtmlutil.Indirect(args[0]).(safehtml.Identifier); ok {
- return safeTypeValue.String(), nil
- }
- }
- return "", fmt.Errorf(`expected a safehtml.Identifier value`)
-}
-
-var sanitizeLoadingEnumValues = map[string]bool{
- "eager": true,
- "lazy": true,
-}
-
-func sanitizeLoadingEnum(args ...interface{}) (string, error) {
- input := safehtmlutil.Stringify(args...)
- if sanitizeLoadingEnumValues[input] {
- return input, nil
- }
- return "", fmt.Errorf(`expected one of the following strings: ["eager" "lazy"]`)
-}
-
-func sanitizeRCDATA(args ...interface{}) (string, error) {
- input := safehtmlutil.Stringify(args...)
- return safehtml.HTMLEscaped(input).String(), nil
-}
-
-func sanitizeScript(args ...interface{}) (string, error) {
- if len(args) > 0 {
- if safeTypeValue, ok := safehtmlutil.Indirect(args[0]).(safehtml.Script); ok {
- return safeTypeValue.String(), nil
- }
- }
- return "", fmt.Errorf(`expected a safehtml.Script value`)
-}
-
-func sanitizeStyle(args ...interface{}) (string, error) {
- if len(args) > 0 {
- if safeTypeValue, ok := safehtmlutil.Indirect(args[0]).(safehtml.Style); ok {
- return safeTypeValue.String(), nil
- }
- }
- return "", fmt.Errorf(`expected a safehtml.Style value`)
-}
-
-func sanitizeStyleSheet(args ...interface{}) (string, error) {
- if len(args) > 0 {
- if safeTypeValue, ok := safehtmlutil.Indirect(args[0]).(safehtml.StyleSheet); ok {
- return safeTypeValue.String(), nil
- }
- }
- return "", fmt.Errorf(`expected a safehtml.StyleSheet value`)
-}
-
-var sanitizeTargetEnumValues = map[string]bool{
- "_blank": true,
- "_self": true,
-}
-
-func sanitizeTargetEnum(args ...interface{}) (string, error) {
- input := safehtmlutil.Stringify(args...)
- if sanitizeTargetEnumValues[input] {
- return input, nil
- }
- return "", fmt.Errorf(`expected one of the following strings: ["_blank" "_self"]`)
-}
-
-func sanitizeTrustedResourceURL(args ...interface{}) (string, error) {
- if len(args) > 0 {
- if safeTypeValue, ok := safehtmlutil.Indirect(args[0]).(safehtml.TrustedResourceURL); ok {
- return safeTypeValue.String(), nil
- }
- }
- return "", fmt.Errorf(`expected a safehtml.TrustedResourceURL value`)
-}
-
-func sanitizeTrustedResourceURLOrURL(args ...interface{}) (string, error) {
- if len(args) > 0 {
- switch v := safehtmlutil.Indirect(args[0]).(type) {
- case safehtml.TrustedResourceURL, safehtml.URL:
- return safehtmlutil.Stringify(v), nil
- }
- }
- input := safehtmlutil.Stringify(args...)
- return safehtml.URLSanitized(input).String(), nil
-}
-
-func sanitizeURL(args ...interface{}) (string, error) {
- if len(args) > 0 {
- if safeTypeValue, ok := safehtmlutil.Indirect(args[0]).(safehtml.URL); ok {
- return safeTypeValue.String(), nil
- }
- }
- input := safehtmlutil.Stringify(args...)
- return safehtml.URLSanitized(input).String(), nil
-}
-
-func sanitizeURLSet(args ...interface{}) (string, error) {
- input := safehtmlutil.Stringify(args...)
- return safehtml.URLSetSanitized(input).String(), nil
-}
diff --git a/vendor/github.com/google/safehtml/template/state_string.go b/vendor/github.com/google/safehtml/template/state_string.go
deleted file mode 100644
index afbbf5a0d..000000000
--- a/vendor/github.com/google/safehtml/template/state_string.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Code generated by "stringer -type State"; DO NOT EDIT
-
-package template
-
-import "fmt"
-
-const _State_name = "StateTextStateSpecialElementBodyStateTagStateAttrNameStateAfterNameStateBeforeValueStateHTMLCmtStateAttrStateError"
-
-var _State_index = [...]uint16{0, 9, 32, 40, 53, 67, 83, 95, 104, 114}
-
-func (i state) String() string {
- if i >= state(len(_State_index)-1) {
- return fmt.Sprintf("state(%d)", i)
- }
- return _State_name[_State_index[i]:_State_index[i+1]]
-}
diff --git a/vendor/github.com/google/safehtml/template/template.go b/vendor/github.com/google/safehtml/template/template.go
deleted file mode 100644
index efd0ef610..000000000
--- a/vendor/github.com/google/safehtml/template/template.go
+++ /dev/null
@@ -1,651 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package template
-
-import (
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "path/filepath"
- "sync"
- "text/template"
- "text/template/parse"
-
- "log"
- "github.com/google/safehtml"
- "github.com/google/safehtml/uncheckedconversions"
-)
-
-// Template is a specialized Template from "text/template" that produces a safe
-// HTML document fragment.
-type Template struct {
- // Sticky error if escaping fails, or errEscapeOK if succeeded.
- escapeErr error
- // We could embed the text/template field, but it's safer not to because
- // we need to keep our version of the name space and the underlying
- // template's in sync.
- text *template.Template
- // The underlying template's parse tree, updated to be HTML-safe.
- Tree *parse.Tree
- *nameSpace // common to all associated templates
-}
-
-// errEscapeOK is a sentinel value used to indicate valid escaping.
-var errEscapeOK = fmt.Errorf("template escaped correctly")
-
-// nameSpace is the data structure shared by all templates in an association.
-type nameSpace struct {
- mu sync.Mutex
- set map[string]*Template
- escaped bool
- // cspCompatible indicates whether inline event handlers and
- // javascript: URIs are disallowed in templates in this namespace.
- cspCompatible bool
- esc escaper
-}
-
-// Templates returns a slice of the templates associated with t, including t
-// itself.
-func (t *Template) Templates() []*Template {
- ns := t.nameSpace
- ns.mu.Lock()
- defer ns.mu.Unlock()
- // Return a slice so we don't expose the map.
- m := make([]*Template, 0, len(ns.set))
- for _, v := range ns.set {
- m = append(m, v)
- }
- return m
-}
-
-// Option sets options for the template. Options are described by
-// strings, either a simple string or "key=value". There can be at
-// most one equals sign in an option string. If the option string
-// is unrecognized or otherwise invalid, Option panics.
-//
-// Known options:
-//
-// missingkey: Control the behavior during execution if a map is
-// indexed with a key that is not present in the map.
-// "missingkey=default" or "missingkey=invalid"
-// The default behavior: Do nothing and continue execution.
-// If printed, the result of the index operation is the string
-// "<no value>".
-// "missingkey=zero"
-// The operation returns the zero value for the map type's element.
-// "missingkey=error"
-// Execution stops immediately with an error.
-//
-func (t *Template) Option(opt ...string) *Template {
- t.text.Option(opt...)
- return t
-}
-
-// checkCanParse checks whether it is OK to parse templates.
-// If not, it returns an error.
-func (t *Template) checkCanParse() error {
- if t == nil {
- return nil
- }
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- if t.nameSpace.escaped {
- return fmt.Errorf("html/template: cannot Parse after Execute")
- }
- return nil
-}
-
-// escape escapes all associated templates.
-func (t *Template) escape() error {
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- t.nameSpace.escaped = true
- if t.escapeErr == nil {
- if t.Tree == nil {
- return fmt.Errorf("template: %q is an incomplete or empty template", t.Name())
- }
- if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
- return err
- }
- } else if t.escapeErr != errEscapeOK {
- return t.escapeErr
- }
- return nil
-}
-
-// Execute applies a parsed template to the specified data object,
-// writing the output to wr.
-// If an error occurs executing the template or writing its output,
-// execution stops, but partial results may already have been written to
-// the output writer.
-// A template may be executed safely in parallel, although if parallel
-// executions share a Writer the output may be interleaved.
-func (t *Template) Execute(wr io.Writer, data interface{}) error {
- if err := t.escape(); err != nil {
- return err
- }
- return t.text.Execute(wr, data)
-}
-
-// ExecuteToHTML applies a parsed template to the specified data object,
-// returning the output as a safehtml.HTML value.
-// A template may be executed safely in parallel.
-func (t *Template) ExecuteToHTML(data interface{}) (safehtml.HTML, error) {
- var buf bytes.Buffer
- if err := t.Execute(&buf, data); err != nil {
- return safehtml.HTML{}, err
- }
- return uncheckedconversions.HTMLFromStringKnownToSatisfyTypeContract(buf.String()), nil
-}
-
-// MustParseAndExecuteToHTML is a helper that returns the safehtml.HTML value produced
-// by parsing text as a template body and executing it with no data. Any errors
-// encountered parsing or executing the template are fatal. This function is intended
-// to produce safehtml.HTML values from static HTML snippets such as
-//
-// html := MustParseAndExecuteToHTML("<b>Important</b>")
-//
-// To guarantee that the template body is never controlled by an attacker, text
-// must be an untyped string constant, which is always under programmer control.
-func MustParseAndExecuteToHTML(text stringConstant) safehtml.HTML {
- t, err := New("").Parse(text)
- if err != nil {
- log.Fatal(err)
- }
- html, err := t.ExecuteToHTML(nil)
- if err != nil {
- log.Fatal(err)
- }
- return html
-}
-
-// ExecuteTemplate applies the template associated with t that has the given
-// name to the specified data object and writes the output to wr.
-// If an error occurs executing the template or writing its output,
-// execution stops, but partial results may already have been written to
-// the output writer.
-// A template may be executed safely in parallel, although if parallel
-// executions share a Writer the output may be interleaved.
-func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
- tmpl, err := t.lookupAndEscapeTemplate(name)
- if err != nil {
- return err
- }
- return tmpl.text.Execute(wr, data)
-}
-
-// ExecuteTemplateToHTML applies the template associated with t that has
-// the given name to the specified data object and returns the output as
-// a safehtml.HTML value.
-// A template may be executed safely in parallel.
-func (t *Template) ExecuteTemplateToHTML(name string, data interface{}) (safehtml.HTML, error) {
- var buf bytes.Buffer
- if err := t.ExecuteTemplate(&buf, name, data); err != nil {
- return safehtml.HTML{}, err
- }
- return uncheckedconversions.HTMLFromStringKnownToSatisfyTypeContract(buf.String()), nil
-}
-
-// lookupAndEscapeTemplate guarantees that the template with the given name
-// is escaped, or returns an error if it cannot be. It returns the named
-// template.
-func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) {
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- t.nameSpace.escaped = true
- tmpl = t.set[name]
- if tmpl == nil {
- return nil, fmt.Errorf("html/template: %q is undefined", name)
- }
- if tmpl.escapeErr != nil && tmpl.escapeErr != errEscapeOK {
- return nil, tmpl.escapeErr
- }
- if tmpl.text.Tree == nil || tmpl.text.Root == nil {
- return nil, fmt.Errorf("html/template: %q is an incomplete template", name)
- }
- if t.text.Lookup(name) == nil {
- panic("html/template internal error: template escaping out of sync")
- }
- if tmpl.escapeErr == nil {
- err = escapeTemplate(tmpl, tmpl.text.Root, name)
- }
- return tmpl, err
-}
-
-// DefinedTemplates returns a string listing the defined templates,
-// prefixed by the string "; defined templates are: ". If there are none,
-// it returns the empty string. Used to generate an error message.
-func (t *Template) DefinedTemplates() string {
- return t.text.DefinedTemplates()
-}
-
-// Parse parses text as a template body for t.
-// Named template definitions ({{define ...}} or {{block ...}} statements) in text
-// define additional templates associated with t and are removed from the
-// definition of t itself.
-//
-// Templates can be redefined in successive calls to Parse,
-// before the first use of Execute on t or any associated template.
-// A template definition with a body containing only white space and comments
-// is considered empty and will not replace an existing template's body.
-// This allows using Parse to add new named template definitions without
-// overwriting the main template body.
-//
-// To guarantee that the template body is never controlled by an attacker, text
-// must be an untyped string constant, which is always under programmer control.
-func (t *Template) Parse(text stringConstant) (*Template, error) {
- if err := t.checkCanParse(); err != nil {
- return nil, err
- }
-
- ret, err := t.text.Parse(string(text))
- if err != nil {
- return nil, err
- }
-
- // In general, all the named templates might have changed underfoot.
- // Regardless, some new ones may have been defined.
- // The template.Template set has been updated; update ours.
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- for _, v := range ret.Templates() {
- name := v.Name()
- tmpl := t.set[name]
- if tmpl == nil {
- tmpl = t.new(name)
- }
- tmpl.text = v
- tmpl.Tree = v.Tree
- }
- return t, nil
-}
-
-// ParseFromTrustedTemplate parses tmpl as a template body for t.
-// Named template definitions ({{define ...}} or {{block ...}} statements) in text
-// define additional templates associated with t and are removed from the
-// definition of t itself.
-//
-// Templates can be redefined in successive calls to ParseFromTrustedTemplate,
-// before the first use of Execute on t or any associated template.
-// A template definition with a body containing only white space and comments
-// is considered empty and will not replace an existing template's body.
-// This allows using ParseFromTrustedTemplate to add new named template definitions without
-// overwriting the main template body.
-//
-// To guarantee that the template body is never controlled by an attacker, tmpl
-// is a TrustedTemplate, which is always under programmer control.
-func (t *Template) ParseFromTrustedTemplate(tmpl TrustedTemplate) (*Template, error) {
- return t.Parse(stringConstant(tmpl.String()))
-}
-
-// Clone returns a duplicate of the template, including all associated
-// templates. The actual representation is not copied, but the name space of
-// associated templates is, so further calls to Parse in the copy will add
-// templates to the copy but not to the original. Clone can be used to prepare
-// common templates and use them with variant definitions for other templates
-// by adding the variants after the clone is made.
-//
-// It returns an error if t has already been executed.
-func (t *Template) Clone() (*Template, error) {
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- if t.escapeErr != nil {
- return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
- }
- textClone, err := t.text.Clone()
- if err != nil {
- return nil, err
- }
- ns := &nameSpace{set: make(map[string]*Template)}
- ns.esc = makeEscaper(ns)
- ret := &Template{
- nil,
- textClone,
- textClone.Tree,
- ns,
- }
- ret.set[ret.Name()] = ret
- for _, x := range textClone.Templates() {
- name := x.Name()
- src := t.set[name]
- if src == nil || src.escapeErr != nil {
- return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
- }
- x.Tree = x.Tree.Copy()
- ret.set[name] = &Template{
- nil,
- x,
- x.Tree,
- ret.nameSpace,
- }
- }
- // Return the template associated with the name of this template.
- return ret.set[ret.Name()], nil
-}
-
-// New allocates a new HTML template with the given name.
-func New(name string) *Template {
- ns := &nameSpace{set: make(map[string]*Template)}
- ns.esc = makeEscaper(ns)
- tmpl := &Template{
- nil,
- template.New(name),
- nil,
- ns,
- }
- tmpl.set[name] = tmpl
- return tmpl
-}
-
-// New allocates a new HTML template associated with the given one
-// and with the same delimiters. The association, which is transitive,
-// allows one template to invoke another with a {{template}} action.
-//
-// If a template with the given name already exists, the new HTML template
-// will replace it. The existing template will be reset and disassociated with
-// t.
-func (t *Template) New(name string) *Template {
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- return t.new(name)
-}
-
-// new is the implementation of New, without the lock.
-func (t *Template) new(name string) *Template {
- tmpl := &Template{
- nil,
- t.text.New(name),
- nil,
- t.nameSpace,
- }
- if existing, ok := tmpl.set[name]; ok {
- emptyTmpl := New(existing.Name())
- *existing = *emptyTmpl
- }
- tmpl.set[name] = tmpl
- return tmpl
-}
-
-// Name returns the name of the template.
-func (t *Template) Name() string {
- return t.text.Name()
-}
-
-// FuncMap is the type of the map defining the mapping from names to
-// functions. Each function must have either a single return value, or two
-// return values of which the second has type error. In that case, if the
-// second (error) argument evaluates to non-nil during execution, execution
-// terminates and Execute returns that error. FuncMap has the same base type
-// as FuncMap in "text/template", copied here so clients need not import
-// "text/template".
-type FuncMap map[string]interface{}
-
-// Funcs adds the elements of the argument map to the template's function map.
-// It must be called before the template is parsed.
-// It panics if a value in the map is not a function with appropriate return
-// type. However, it is legal to overwrite elements of the map. The return
-// value is the template, so calls can be chained.
-func (t *Template) Funcs(funcMap FuncMap) *Template {
- t.text.Funcs(template.FuncMap(funcMap))
- return t
-}
-
-// CSPCompatible causes this template to check template text for
-// Content Security Policy (CSP) compatibility. The template will return errors
-// at execution time if inline event handler attribute names or javascript:
-// URIs are found in template text.
-//
-// For example, the following templates will cause errors:
-// <span onclick="doThings();">A thing.</span> // inline event handler "onclick"
-// <a href="javascript:linkClicked()">foo</a> // javascript: URI present
-func (t *Template) CSPCompatible() *Template {
- t.nameSpace.mu.Lock()
- t.nameSpace.cspCompatible = true
- t.nameSpace.mu.Unlock()
- return t
-}
-
-// Delims sets the action delimiters to the specified strings, to be used in
-// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
-// definitions will inherit the settings. An empty delimiter stands for the
-// corresponding default: {{ or }}.
-// The return value is the template, so calls can be chained.
-func (t *Template) Delims(left, right string) *Template {
- t.text.Delims(left, right)
- return t
-}
-
-// Lookup returns the template with the given name that is associated with t,
-// or nil if there is no such template.
-func (t *Template) Lookup(name string) *Template {
- t.nameSpace.mu.Lock()
- defer t.nameSpace.mu.Unlock()
- return t.set[name]
-}
-
-// Must is a helper that wraps a call to a function returning (*Template, error)
-// and panics if the error is non-nil. It is intended for use in variable initializations
-// such as
-// var t = template.Must(template.New("name").Parse("html"))
-func Must(t *Template, err error) *Template {
- if err != nil {
- panic(err)
- }
- return t
-}
-
-// stringConstant is an unexported string type. Users of this package cannot
-// create values of this type except by passing an untyped string constant to
-// functions which expect a stringConstant. This type must be used only in
-// function and method parameters.
-type stringConstant string
-
-func stringConstantsToStrings(strs []stringConstant) []string {
- ret := make([]string, 0, len(strs))
- for _, s := range strs {
- ret = append(ret, string(s))
- }
- return ret
-}
-
-// ParseFiles creates a new Template and parses the template definitions from
-// the named files. The returned template's name will have the (base) name and
-// (parsed) contents of the first file. There must be at least one file.
-// If an error occurs, parsing stops and the returned *Template is nil.
-//
-// When parsing multiple files with the same name in different directories,
-// the last one mentioned will be the one that results.
-// For instance, ParseFiles("a/foo", "b/foo") stores "b/foo" as the template
-// named "foo", while "a/foo" is unavailable.
-//
-// To guarantee that filepaths, and thus template bodies, are never controlled by
-// an attacker, filenames must be untyped string constants, which are always under
-// programmer control.
-func ParseFiles(filenames ...stringConstant) (*Template, error) {
- return parseFiles(nil, readFileOS, stringConstantsToStrings(filenames)...)
-}
-
-// ParseFilesFromTrustedSources creates a new Template and parses the template definitions from
-// the named files. The returned template's name will have the (base) name and
-// (parsed) contents of the first file. There must be at least one file.
-// If an error occurs, parsing stops and the returned *Template is nil.
-//
-// When parsing multiple files with the same name in different directories,
-// the last one mentioned will be the one that results.
-// For instance, ParseFiles("a/foo", "b/foo") stores "b/foo" as the template
-// named "foo", while "a/foo" is unavailable.
-//
-// To guarantee that filepaths, and thus template bodies, are never controlled by
-// an attacker, filenames must be trusted sources, which are always under programmer
-// or application control.
-func ParseFilesFromTrustedSources(filenames ...TrustedSource) (*Template, error) {
- return parseFiles(nil, readFileOS, trustedSourcesToStrings(filenames)...)
-}
-
-// ParseFiles parses the named files and associates the resulting templates with
-// t. If an error occurs, parsing stops and the returned template is nil;
-// otherwise it is t. There must be at least one file.
-//
-// When parsing multiple files with the same name in different directories,
-// the last one mentioned will be the one that results.
-//
-// ParseFiles returns an error if t or any associated template has already been executed.
-//
-// To guarantee that filepaths, and thus template bodies, are never controlled by
-// an attacker, filenames must be untyped string constants, which are always under
-// programmer control.
-func (t *Template) ParseFiles(filenames ...stringConstant) (*Template, error) {
- return parseFiles(t, readFileOS, stringConstantsToStrings(filenames)...)
-}
-
-// ParseFilesFromTrustedSources parses the named files and associates the resulting templates with
-// t. If an error occurs, parsing stops and the returned template is nil;
-// otherwise it is t. There must be at least one file.
-//
-// When parsing multiple files with the same name in different directories,
-// the last one mentioned will be the one that results.
-//
-// ParseFilesFromTrustedSources returns an error if t or any associated template has already been executed.
-//
-// To guarantee that filepaths, and thus template bodies, are never controlled by
-// an attacker, filenames must be trusted sources, which are always under programmer
-// or application control.
-func (t *Template) ParseFilesFromTrustedSources(filenames ...TrustedSource) (*Template, error) {
- return parseFiles(t, readFileOS, trustedSourcesToStrings(filenames)...)
-}
-
-// parseFiles is the helper for the method and function. If the argument
-// template is nil, it is created from the first file.
-// readFile takes a filename and returns the file's basename and contents.
-func parseFiles(t *Template, readFile func(string) (string, []byte, error), filenames ...string) (*Template, error) {
- if err := t.checkCanParse(); err != nil {
- return nil, err
- }
-
- if len(filenames) == 0 {
- // Not really a problem, but be consistent.
- return nil, fmt.Errorf("html/template: no files named in call to ParseFiles")
- }
- for _, filename := range filenames {
- name, b, err := readFile(filename)
- if err != nil {
- return nil, err
- }
- s := stringConstant(b)
- // First template becomes return value if not already defined,
- // and we use that one for subsequent New calls to associate
- // all the templates together. Also, if this file has the same name
- // as t, this file becomes the contents of t, so
- // t, err := New(name).Funcs(xxx).ParseFiles(name)
- // works. Otherwise we create a new template associated with t.
- var tmpl *Template
- if t == nil {
- t = New(name)
- }
- if name == t.Name() {
- tmpl = t
- } else {
- tmpl = t.New(name)
- }
- _, err = tmpl.Parse(s)
- if err != nil {
- return nil, err
- }
- }
- return t, nil
-}
-
-// Copied with minor changes from
-// https://go.googlesource.com/go/+/refs/tags/go1.17.1/src/text/template/helper.go.
-func readFileOS(file string) (string, []byte, error) {
- name := filepath.Base(file)
- b, err := ioutil.ReadFile(file)
- return name, b, err
-}
-
-// ParseGlob creates a new Template and parses the template definitions from the
-// files identified by the pattern, which must match at least one file. The
-// returned template will have the (base) name and (parsed) contents of the
-// first file matched by the pattern. ParseGlob is equivalent to calling
-// ParseFiles with the list of files matched by the pattern.
-//
-// To guarantee that the pattern, and thus the template bodies, is never controlled by
-// an attacker, pattern must be an untyped string constant, which is always under
-// programmer control.
-func ParseGlob(pattern stringConstant) (*Template, error) {
- return parseGlob(nil, string(pattern))
-}
-
-// ParseGlobFromTrustedSource creates a new Template and parses the template definitions from the
-// files identified by the pattern, which must match at least one file. The
-// returned template will have the (base) name and (parsed) contents of the
-// first file matched by the pattern. ParseGlobFromTrustedSource is equivalent to calling
-// ParseFilesFromTrustedSources with the list of files matched by the pattern.
-//
-// To guarantee that the pattern, and thus the template bodies, is never controlled by
-// an attacker, pattern must be a trusted source, which is always under programmer or
-// application control.
-func ParseGlobFromTrustedSource(pattern TrustedSource) (*Template, error) {
- return parseGlob(nil, pattern.String())
-}
-
-// ParseGlob parses the template definitions in the files identified by the
-// pattern and associates the resulting templates with t. The pattern is
-// processed by filepath.Glob and must match at least one file. ParseGlob is
-// equivalent to calling t.ParseFiles with the list of files matched by the
-// pattern.
-//
-// When parsing multiple files with the same name in different directories,
-// the last one mentioned will be the one that results.
-//
-// ParseGlob returns an error if t or any associated template has already been executed.
-//
-// To guarantee that the pattern, and thus the template bodies, is never controlled by
-// an attacker, pattern must be an untyped string constant, which is always under
-// programmer control.
-func (t *Template) ParseGlob(pattern stringConstant) (*Template, error) {
- return parseGlob(t, string(pattern))
-}
-
-// ParseGlobFromTrustedSource parses the template definitions in the files identified by the
-// pattern and associates the resulting templates with t. The pattern is
-// processed by filepath.Glob and must match at least one file. ParseGlob is
-// equivalent to calling t.ParseFiles with the list of files matched by the
-// pattern.
-//
-// When parsing multiple files with the same name in different directories,
-// the last one mentioned will be the one that results.
-//
-// ParseGlobFromTrustedSource returns an error if t or any associated template has already been executed.
-//
-// To guarantee that the pattern, and thus the template bodies, is never controlled by
-// an attacker, pattern must be a trusted source, which is always under programmer or
-// application control.
-func (t *Template) ParseGlobFromTrustedSource(pattern TrustedSource) (*Template, error) {
- return parseGlob(t, pattern.String())
-}
-
-// parseGlob is the implementation of the function and method ParseGlob.
-func parseGlob(t *Template, pattern string) (*Template, error) {
- if err := t.checkCanParse(); err != nil {
- return nil, err
- }
- filenames, err := filepath.Glob(pattern)
- if err != nil {
- return nil, err
- }
- if len(filenames) == 0 {
- return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern)
- }
- return parseFiles(t, readFileOS, filenames...)
-}
-
-// IsTrue reports whether the value is 'true', in the sense of not the zero of its type,
-// and whether the value has a meaningful truth value. This is the definition of
-// truth used by if and other such actions.
-func IsTrue(val interface{}) (truth, ok bool) {
- return template.IsTrue(val)
-}
diff --git a/vendor/github.com/google/safehtml/template/transition.go b/vendor/github.com/google/safehtml/template/transition.go
deleted file mode 100644
index e0882e489..000000000
--- a/vendor/github.com/google/safehtml/template/transition.go
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package template
-
-import (
- "bytes"
- "strings"
-)
-
-// transitionFunc is the array of context transition functions for text nodes.
-// A transition function takes a context and template text input, and returns
-// the updated context and the number of bytes consumed from the front of the
-// input.
-var transitionFunc = [...]func(context, []byte) (context, int){
- stateText: tText,
- stateSpecialElementBody: tSpecialTagEnd,
- stateTag: tTag,
- stateAttrName: tAttrName,
- stateAfterName: tAfterName,
- stateBeforeValue: tBeforeValue,
- stateHTMLCmt: tHTMLCmt,
- stateAttr: tAttr,
- stateError: tError,
-}
-
-var commentStart = []byte("<!--")
-var commentEnd = []byte("-->")
-
-// tText is the context transition function for the text state.
-func tText(c context, s []byte) (context, int) {
- k := 0
- for {
- i := k + bytes.IndexByte(s[k:], '<')
- if i < k || i+1 == len(s) {
- return c, len(s)
- } else if i+4 <= len(s) && bytes.Equal(commentStart, s[i:i+4]) {
- return context{state: stateHTMLCmt}, i + 4
- }
- i++
- end := false
- if s[i] == '/' {
- if i+1 == len(s) {
- return c, len(s)
- }
- end, i = true, i+1
- }
- j, e := eatTagName(s, i)
- if j != i {
- // We've found an HTML tag.
- ret := context{state: stateTag}
- // Element name not needed if we are at the end of the element.
- if !end {
- ret.element = e
- }
- return ret, j
- }
- k = j
- }
-}
-
-// specialElements contains the names of elements whose bodies are treated
-// differently by the parser and escaper from stateText.
-var specialElements = map[string]bool{
- "script": true,
- "style": true,
- "textarea": true,
- "title": true,
-}
-
-// voidElements contains the names of all void elements.
-// https://www.w3.org/TR/html5/syntax.html#void-elements
-var voidElements = map[string]bool{
- "area": true,
- "base": true,
- "br": true,
- "col": true,
- "embed": true,
- "hr": true,
- "img": true,
- "input": true,
- "keygen": true,
- "link": true,
- "meta": true,
- "param": true,
- "source": true,
- "track": true,
- "wbr": true,
-}
-
-// tTag is the context transition function for the tag state.
-func tTag(c context, s []byte) (context, int) {
- // Find the attribute name.
- i := eatWhiteSpace(s, 0)
- if i == len(s) {
- return c, len(s)
- }
- if s[i] == '>' {
- ret := context{
- state: stateText,
- element: c.element,
- scriptType: c.scriptType,
- linkRel: c.linkRel,
- }
- if specialElements[c.element.name] {
- ret.state = stateSpecialElementBody
- }
- if c.element.name != "" && voidElements[c.element.name] {
- // Special case: end of start tag of a void element.
- // Discard unnecessary state, since this element have no content.
- ret.element = element{}
- ret.scriptType = ""
- ret.linkRel = ""
- }
- return ret, i + 1
- }
- j, err := eatAttrName(s, i)
- if err != nil {
- return context{state: stateError, err: err}, len(s)
- }
- state := stateTag
- if i == j {
- return context{
- state: stateError,
- err: errorf(ErrBadHTML, nil, 0, "expected space, attr name, or end of tag, but got %q", s[i:]),
- }, len(s)
- }
-
- if j == len(s) {
- state = stateAttrName
- } else {
- state = stateAfterName
- }
- return context{
- state: state,
- element: c.element,
- attr: attr{name: strings.ToLower(string(s[i:j]))},
- linkRel: c.linkRel,
- }, j
-}
-
-// tAttrName is the context transition function for stateAttrName.
-func tAttrName(c context, s []byte) (context, int) {
- i, err := eatAttrName(s, 0)
- if err != nil {
- return context{state: stateError, err: err}, len(s)
- } else if i != len(s) {
- c.state = stateAfterName
- }
- return c, i
-}
-
-// tAfterName is the context transition function for stateAfterName.
-func tAfterName(c context, s []byte) (context, int) {
- // Look for the start of the value.
- i := eatWhiteSpace(s, 0)
- if i == len(s) {
- return c, len(s)
- } else if s[i] != '=' {
- // Occurs due to tag ending '>', and valueless attribute.
- c.state = stateTag
- return c, i
- }
- c.state = stateBeforeValue
- // Consume the "=".
- return c, i + 1
-}
-
-// tBeforeValue is the context transition function for stateBeforeValue.
-func tBeforeValue(c context, s []byte) (context, int) {
- i := eatWhiteSpace(s, 0)
- if i == len(s) {
- return c, len(s)
- }
- // Find the attribute delimiter.
- // TODO: consider disallowing single-quoted or unquoted attribute values completely, even in hardcoded template text.
- delim := delimSpaceOrTagEnd
- switch s[i] {
- case '\'':
- delim, i = delimSingleQuote, i+1
- case '"':
- delim, i = delimDoubleQuote, i+1
- }
- c.state, c.delim = stateAttr, delim
- return c, i
-}
-
-// tHTMLCmt is the context transition function for stateHTMLCmt.
-func tHTMLCmt(c context, s []byte) (context, int) {
- if i := bytes.Index(s, commentEnd); i != -1 {
- return context{}, i + 3
- }
- return c, len(s)
-}
-
-var (
- specialTagEndPrefix = []byte("</")
- tagEndSeparators = []byte("> \t\n\f/")
-)
-
-// tSpecialTagEnd is the context transition function for raw text, RCDATA
-// script data, and stylesheet element states.
-func tSpecialTagEnd(c context, s []byte) (context, int) {
- if specialElements[c.element.name] {
- if i := indexTagEnd(s, []byte(c.element.name)); i != -1 {
- return context{}, i
- }
- }
- return c, len(s)
-}
-
-// indexTagEnd finds the index of a special tag end in a case insensitive way, or returns -1
-func indexTagEnd(s []byte, tag []byte) int {
- res := 0
- plen := len(specialTagEndPrefix)
- for len(s) > 0 {
- // Try to find the tag end prefix first
- i := bytes.Index(s, specialTagEndPrefix)
- if i == -1 {
- return i
- }
- s = s[i+plen:]
- // Try to match the actual tag if there is still space for it
- if len(tag) <= len(s) && bytes.EqualFold(tag, s[:len(tag)]) {
- s = s[len(tag):]
- // Check the tag is followed by a proper separator
- if len(s) > 0 && bytes.IndexByte(tagEndSeparators, s[0]) != -1 {
- return res + i
- }
- res += len(tag)
- }
- res += i + plen
- }
- return -1
-}
-
-// tAttr is the context transition function for the attribute state.
-func tAttr(c context, s []byte) (context, int) {
- return c, len(s)
-}
-
-// tError is the context transition function for the error state.
-func tError(c context, s []byte) (context, int) {
- return c, len(s)
-}
-
-// eatAttrName returns the largest j such that s[i:j] is an attribute name.
-// It returns an error if s[i:] does not look like it begins with an
-// attribute name, such as encountering a quote mark without a preceding
-// equals sign.
-func eatAttrName(s []byte, i int) (int, *Error) {
- for j := i; j < len(s); j++ {
- switch s[j] {
- case ' ', '\t', '\n', '\f', '\r', '=', '>':
- return j, nil
- case '\'', '"', '<':
- // These result in a parse warning in HTML5 and are
- // indicative of serious problems if seen in an attr
- // name in a template.
- return -1, errorf(ErrBadHTML, nil, 0, "%q in attribute name: %.32q", s[j:j+1], s)
- default:
- // No-op.
- }
- }
- return len(s), nil
-}
-
-// asciiAlpha reports whether c is an ASCII letter.
-func asciiAlpha(c byte) bool {
- return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
-}
-
-// asciiAlphaNum reports whether c is an ASCII letter or digit.
-func asciiAlphaNum(c byte) bool {
- return asciiAlpha(c) || '0' <= c && c <= '9'
-}
-
-// eatTagName returns the largest j such that s[i:j] is a tag name and the tag name.
-func eatTagName(s []byte, i int) (int, element) {
- if i == len(s) || !asciiAlpha(s[i]) {
- return i, element{}
- }
- j := i + 1
- for j < len(s) {
- x := s[j]
- if asciiAlphaNum(x) {
- j++
- continue
- }
- // Allow "x-y" or "x:y" but not "x-", "-y", or "x--y".
- if (x == ':' || x == '-') && j+1 < len(s) && asciiAlphaNum(s[j+1]) {
- j += 2
- continue
- }
- break
- }
- return j, element{name: strings.ToLower(string(s[i:j]))}
-}
-
-// eatWhiteSpace returns the largest j such that s[i:j] is white space.
-func eatWhiteSpace(s []byte, i int) int {
- for j := i; j < len(s); j++ {
- switch s[j] {
- case ' ', '\t', '\n', '\f', '\r':
- // No-op.
- default:
- return j
- }
- }
- return len(s)
-}
diff --git a/vendor/github.com/google/safehtml/template/trustedfs.go b/vendor/github.com/google/safehtml/template/trustedfs.go
deleted file mode 100644
index 80db11824..000000000
--- a/vendor/github.com/google/safehtml/template/trustedfs.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2021 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-//go:build go1.16
-// +build go1.16
-
-package template
-
-import (
- "embed"
- "fmt"
- "io/fs"
- "os"
- "path"
-)
-
-// A TrustedFS is an immutable type referencing a filesystem (fs.FS)
-// under application control.
-//
-// In order to ensure that an attacker cannot influence the TrustedFS value, a
-// TrustedFS can be instantiated in only two ways. One way is from an embed.FS
-// with TrustedFSFromEmbed. It is assumed that embedded filesystems are under
-// the programmer's control. The other way is from a TrustedSource using
-// TrustedFSFromTrustedSource, in which case the guarantees and caveats of
-// TrustedSource apply.
-type TrustedFS struct {
- fsys fs.FS
-}
-
-// TrustedFSFromEmbed constructs a TrustedFS from an embed.FS.
-func TrustedFSFromEmbed(fsys embed.FS) TrustedFS {
- return TrustedFS{fsys: fsys}
-}
-
-// TrustedFSFromTrustedSource constructs a TrustedFS from the string in the
-// TrustedSource, which should refer to a directory.
-func TrustedFSFromTrustedSource(ts TrustedSource) TrustedFS {
- return TrustedFS{fsys: os.DirFS(ts.src)}
-}
-
-// Sub returns a TrustedFS at a subdirectory of the receiver.
-// It works by calling fs.Sub on the receiver's fs.FS.
-func (tf TrustedFS) Sub(dir TrustedSource) (TrustedFS, error) {
- subfs, err := fs.Sub(tf.fsys, dir.String())
- return TrustedFS{fsys: subfs}, err
-}
-
-// ParseFS is like ParseFiles or ParseGlob but reads from the TrustedFS
-// instead of the host operating system's file system.
-// It accepts a list of glob patterns.
-// (Note that most file names serve as glob patterns matching only themselves.)
-//
-// The same behaviors listed for ParseFiles() apply to ParseFS too (e.g. using the base name
-// of the file as the template name).
-func ParseFS(tfs TrustedFS, patterns ...string) (*Template, error) {
- return parseFS(nil, tfs.fsys, patterns)
-}
-
-// ParseFS is like ParseFiles or ParseGlob but reads from the TrustedFS
-// instead of the host operating system's file system.
-// It accepts a list of glob patterns.
-// (Note that most file names serve as glob patterns matching only themselves.)
-//
-// The same behaviors listed for ParseFiles() apply to ParseFS too (e.g. using the base name
-// of the file as the template name).
-func (t *Template) ParseFS(tfs TrustedFS, patterns ...string) (*Template, error) {
- return parseFS(t, tfs.fsys, patterns)
-}
-
-// Copied from
-// https://go.googlesource.com/go/+/refs/tags/go1.17.1/src/text/template/helper.go.
-func parseFS(t *Template, fsys fs.FS, patterns []string) (*Template, error) {
- var filenames []string
- for _, pattern := range patterns {
- list, err := fs.Glob(fsys, pattern)
- if err != nil {
- return nil, err
- }
- if len(list) == 0 {
- return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
- }
- filenames = append(filenames, list...)
- }
- return parseFiles(t, readFileFS(fsys), filenames...)
-}
-
-// Copied with minor changes from
-// https://go.googlesource.com/go/+/refs/tags/go1.17.1/src/text/template/helper.go.
-func readFileFS(fsys fs.FS) func(string) (string, []byte, error) {
- return func(file string) (string, []byte, error) {
- name := path.Base(file)
- b, err := fs.ReadFile(fsys, file)
- return name, b, err
- }
-}
diff --git a/vendor/github.com/google/safehtml/template/trustedsource.go b/vendor/github.com/google/safehtml/template/trustedsource.go
deleted file mode 100644
index f64263948..000000000
--- a/vendor/github.com/google/safehtml/template/trustedsource.go
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package template
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
- "flag"
-)
-
-// A TrustedSource is an immutable string-like type referencing
-// trusted template files under application control. It can be passed to
-// template-parsing functions and methods to safely load templates
-// without the risk of untrusted template execution.
-//
-// In order to ensure that an attacker cannot influence the TrustedSource
-// value, a TrustedSource can be instantiated only from untyped string
-// constants, command-line flags, and other application-controlled strings, but
-// never from arbitrary string values potentially representing untrusted user input.
-//
-// Note that TrustedSource's constructors cannot truly guarantee that the
-// templates it references are not attacker-controlled; it can guarantee only that
-// the path to the template itself is under application control. Users of these
-// constructors must ensure themselves that TrustedSource never references
-// attacker-controlled files or directories that contain such files.
-type TrustedSource struct {
- // We declare a TrustedSource not as a string but as a struct wrapping a string
- // to prevent construction of TrustedSource values through string conversion.
- src string
-}
-
-// TrustedSourceFromConstant constructs a TrustedSource with its underlying
-// src set to the given src, which must be an untyped string constant.
-//
-// No runtime validation or sanitization is performed on src; being under
-// application control, it is simply assumed to comply with the TrustedSource type
-// contract.
-func TrustedSourceFromConstant(src stringConstant) TrustedSource {
- return TrustedSource{string(src)}
-}
-
-// TrustedSourceFromConstantDir constructs a TrustedSource calling path/filepath.Join on
-// an application-controlled directory path, which must be an untyped string constant,
-// a TrustedSource, and a dynamic filename. It returns an error if filename contains
-// filepath or list separators, since this might cause the resulting path to reference a
-// file outside of the given directory.
-//
-// dir or src may be empty if either of these path segments are not required.
-func TrustedSourceFromConstantDir(dir stringConstant, src TrustedSource, filename string) (TrustedSource, error) {
- if i := strings.IndexAny(filename, string([]rune{filepath.Separator, filepath.ListSeparator})); i != -1 {
- return TrustedSource{}, fmt.Errorf("filename %q must not contain the separator %q", filename, filename[i])
- }
- if filename == ".." {
- return TrustedSource{}, fmt.Errorf("filename must not be the special name %q", filename)
- }
- return TrustedSource{filepath.Join(string(dir), src.String(), filename)}, nil
-}
-
-// TrustedSourceJoin is a wrapper around path/filepath.Join that returns a
-// TrustedSource formed by joining the given path elements into a single path,
-// adding an OS-specific path separator if necessary.
-func TrustedSourceJoin(elem ...TrustedSource) TrustedSource {
- return TrustedSource{filepath.Join(trustedSourcesToStrings(elem)...)}
-}
-
-// TrustedSourceFromFlag returns a TrustedSource containing the string
-// representation of the retrieved value of the flag.
-//
-// In a server setting, flags are part of the application's deployment
-// configuration and are hence considered application-controlled.
-func TrustedSourceFromFlag(value flag.Value) TrustedSource {
- return TrustedSource{fmt.Sprint(value.String())}
-}
-
-// TrustedSourceFromEnvVar is a wrapper around os.Getenv that
-// returns a TrustedSource containing the value of the environment variable
-// named by the key. It returns the value, which will be empty if the variable
-// is not present. To distinguish between an empty value and an unset value,
-// use os.LookupEnv.
-//
-// In a server setting, environment variables are part of the application's
-// deployment configuration and are hence considered application-controlled.
-func TrustedSourceFromEnvVar(key stringConstant) TrustedSource {
- return TrustedSource{os.Getenv(string(key))}
-}
-
-// String returns the string form of the TrustedSource.
-func (t TrustedSource) String() string {
- return t.src
-}
-
-func trustedSourcesToStrings(paths []TrustedSource) []string {
- ret := make([]string, 0, len(paths))
- for _, p := range paths {
- ret = append(ret, p.String())
- }
- return ret
-}
diff --git a/vendor/github.com/google/safehtml/template/trustedtemplate.go b/vendor/github.com/google/safehtml/template/trustedtemplate.go
deleted file mode 100644
index bd3b1b46a..000000000
--- a/vendor/github.com/google/safehtml/template/trustedtemplate.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package template
-
-// A TrustedTemplate is an immutable string-like type containing a
-// safehtml/template template body. It can be safely loaded as template
-// text without the risk of untrusted template execution.
-//
-// In order to ensure that an attacker cannot influence the TrustedTemplate
-// value, a TrustedTemplate can be instantiated only from untyped string constants,
-// and never from arbitrary string values potentially representing untrusted user input.
-//
-type TrustedTemplate struct {
- // We declare a TrustedTemplate not as a string but as a struct wrapping a string
- // to prevent construction of TrustedTemplate values through string conversion.
- tmpl string
-}
-
-// MakeTrustedTemplate constructs a TrustedTemplate with its underlying
-// tmpl set to the given tmpl, which must be an untyped string constant.
-//
-// No runtime validation or sanitization is performed on tmpl; being under
-// application control, it is simply assumed to comply with the TrustedTemplate type
-// contract.
-func MakeTrustedTemplate(tmpl stringConstant) TrustedTemplate {
- return TrustedTemplate{string(tmpl)}
-}
-
-// String returns the string form of the TrustedTemplate.
-func (t TrustedTemplate) String() string {
- return t.tmpl
-}
diff --git a/vendor/github.com/google/safehtml/template/url.go b/vendor/github.com/google/safehtml/template/url.go
deleted file mode 100644
index f63475fcf..000000000
--- a/vendor/github.com/google/safehtml/template/url.go
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package template
-
-import (
- "fmt"
- "html"
- "regexp"
- "strings"
-
- "github.com/google/safehtml/internal/safehtmlutil"
- "github.com/google/safehtml"
-)
-
-// urlPrefixValidators maps URL and TrustedResourceURL sanitization contexts to functions return an error
-// if the given string is unsafe to use as a URL prefix in that sanitization context.
-var urlPrefixValidators = map[sanitizationContext]func(string) error{
- sanitizationContextURL: validateURLPrefix,
- sanitizationContextTrustedResourceURLOrURL: validateURLPrefix,
- sanitizationContextTrustedResourceURL: validateTrustedResourceURLPrefix,
-}
-
-// startsWithFullySpecifiedSchemePattern matches strings that have a fully-specified scheme component.
-// See RFC 3986 Section 3.
-var startsWithFullySpecifiedSchemePattern = regexp.MustCompile(
- `^[[:alpha:]](?:[[:alnum:]]|[+.-])*:`)
-
-// validateURLPrefix validates if the given non-empty prefix is a safe safehtml.URL prefix.
-//
-// Prefixes are considered unsafe if they end in an incomplete HTML character reference
-// or percent-encoding character triplet.
-//
-// If the prefix contains a fully-specified scheme component, it is considered safe only if
-// it starts with an allowed scheme. See safehtml.URLSanitized for more details.
-//
-// Otherwise, the prefix is safe only if it contains '/', '?', or '#', since the presence of any
-// of these runes ensures that this prefix, when combined with some arbitrary suffix, cannot be
-// interpreted as a part of a scheme.
-func validateURLPrefix(prefix string) error {
- decoded, err := decodeURLPrefix(prefix)
- if err != nil {
- return err
- }
- switch {
- case startsWithFullySpecifiedSchemePattern.MatchString(decoded):
- if safehtml.URLSanitized(decoded).String() != decoded {
- return fmt.Errorf("URL prefix %q contains an unsafe scheme", prefix)
- }
- case !strings.ContainsAny(decoded, "/?#"):
- // If the URL prefix does not already have a ':' scheme delimiter, and does not contain
- // '/', '?', or '#', any ':' following this prefix will be intepreted as a scheme
- // delimiter, causing this URL prefix to be interpreted as being part of a scheme.
- // e.g. `<a href="java{{ "script:" }}alert(1)>`
- return fmt.Errorf("URL prefix %q is unsafe; it might be interpreted as part of a scheme", prefix)
- }
- return nil
-}
-
-// validateTrustedResourceURLPrefix validates if the given non-empty prefix is a safe
-// safehtml.TrustedResourceURL prefix.
-//
-// Prefixes are considered unsafe if they end in an incomplete HTML character reference
-// or percent-encoding character triplet.
-//
-// See safehtmlutil.IsSafeTrustedResourceURLPrefix for details on how the prefix is validated.
-func validateTrustedResourceURLPrefix(prefix string) error {
- decoded, err := decodeURLPrefix(prefix)
- if err != nil {
- return err
- }
- if !safehtmlutil.IsSafeTrustedResourceURLPrefix(decoded) {
- return fmt.Errorf("%q is a disallowed TrustedResourceURL prefix", prefix)
- }
- return nil
-}
-
-// endsWithPercentEncodingPrefixPattern matches strings that end in an incomplete
-// URL percent encoding triplet.
-//
-// See https://tools.ietf.org/html/rfc3986#section-2.1.
-var endsWithPercentEncodingPrefixPattern = regexp.MustCompile(
- `%[[:xdigit:]]?$`)
-
-// containsWhitespaceOrControlPattern matches strings that contain ASCII whitespace
-// or control characters.
-var containsWhitespaceOrControlPattern = regexp.MustCompile(`[[:space:]]|[[:cntrl:]]`)
-
-// decodeURLPrefix returns the given prefix after it has been HTML-unescaped.
-// It returns an error if the prefix:
-// * ends in an incomplete HTML character reference before HTML-unescaping,
-// * ends in an incomplete percent-encoding character triplet after HTML-unescaping, or
-// * contains whitespace before or after HTML-unescaping.
-func decodeURLPrefix(prefix string) (string, error) {
- if containsWhitespaceOrControlPattern.MatchString(prefix) {
- return "", fmt.Errorf("URL prefix %q contains whitespace or control characters", prefix)
- }
- if err := validateDoesNotEndsWithCharRefPrefix(prefix); err != nil {
- return "", fmt.Errorf("URL %s", err)
- }
- decoded := html.UnescapeString(prefix)
- // Check again for whitespace that might have previously been masked by a HTML reference,
- // such as in "javascript&NewLine;".
- if containsWhitespaceOrControlPattern.MatchString(decoded) {
- return "", fmt.Errorf("URL prefix %q contains whitespace or control characters", prefix)
- }
- if endsWithPercentEncodingPrefixPattern.MatchString(decoded) {
- return "", fmt.Errorf("URL prefix %q ends with an incomplete percent-encoding character triplet", prefix)
- }
- return decoded, nil
-}
-
-func validateTrustedResourceURLSubstitution(args ...interface{}) (string, error) {
- input := safehtmlutil.Stringify(args...)
- if safehtmlutil.URLContainsDoubleDotSegment(input) {
- // Reject substitutions containing the ".." dot-segment to prevent the final TrustedResourceURL from referencing
- // a resource higher up in the path name hierarchy than the path specified in the prefix.
- return "", fmt.Errorf(`cannot substitute %q after TrustedResourceURL prefix: ".." is disallowed`, input)
- }
- return input, nil
-}
diff --git a/vendor/github.com/google/safehtml/trustedresourceurl.go b/vendor/github.com/google/safehtml/trustedresourceurl.go
deleted file mode 100644
index e31a2fd56..000000000
--- a/vendor/github.com/google/safehtml/trustedresourceurl.go
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package safehtml
-
-import (
- "fmt"
- "regexp"
- "sort"
- "strings"
-
- "flag"
- "github.com/google/safehtml/internal/safehtmlutil"
-)
-
-// A TrustedResourceURL is an immutable string-like type referencing the
-// application’s own, trusted resources. It can be used to safely load scripts,
-// CSS and other sensitive resources without the risk of untrusted code execution.
-// For example, it is unsafe to insert a plain string in a
-//
-// <script src=“...”></script>
-//
-// context since the URL may originate from untrusted user input and the
-// script it is pointing to may thus be controlled by an attacker. It is,
-// however, safe to use a TrustedResourceURL since its value is known to never
-// have left application control.
-//
-// In order to ensure that an attacker cannot influence the TrustedResourceURL
-// value, a TrustedResourceURL can only be instantiated from compile-time
-// constant string literals, command-line flags or a combination of the two,
-// but never from arbitrary string values potentially representing untrusted user input.
-//
-// Additionally, TrustedResourceURLs can be serialized and passed along within
-// the application via protocol buffers. It is the application’s responsibility
-// to ensure that the protocol buffers originate from within the application
-// itself and not from an external entity outside its trust domain.
-//
-// Note that TrustedResourceURLs can also use absolute paths (starting with '/')
-// and relative paths. This allows the same binary to be used for different
-// hosts without hard-coding the hostname in a string literal.
-type TrustedResourceURL struct {
- // We declare a TrustedResourceURL not as a string but as a struct wrapping a string
- // to prevent construction of TrustedResourceURL values through string conversion.
- str string
-}
-
-// TrustedResourceURLWithParams constructs a new TrustedResourceURL with the
-// given key-value pairs added as query parameters.
-//
-// Map entries with empty keys or values are ignored. The order of appended
-// keys is guaranteed to be stable but may differ from the order in input.
-func TrustedResourceURLWithParams(t TrustedResourceURL, params map[string]string) TrustedResourceURL {
- url := t.str
- var fragment string
- if i := strings.IndexByte(url, '#'); i != -1 {
- // The fragment identifier component will always appear at the end
- // of the URL after the query segment. It is therefore safe to
- // trim the fragment from the tail of the URL and re-append it after
- // all query parameters have been added.
- // See https://tools.ietf.org/html/rfc3986#appendix-A.
- fragment = url[i:]
- url = url[:i]
- }
- sep := "?"
- if i := strings.IndexRune(url, '?'); i != -1 {
- // The first "?" in a URL indicates the start of the query component.
- // See https://tools.ietf.org/html/rfc3986#section-3.4
- if i == len(url)-1 {
- sep = ""
- } else {
- sep = "&"
- }
- }
- stringParams := make([]string, 0, len(params))
- for k, v := range params {
- if k == "" || v == "" {
- continue
- }
- stringParam := safehtmlutil.QueryEscapeURL(k) + "=" + safehtmlutil.QueryEscapeURL(v)
- stringParams = append(stringParams, stringParam)
- }
- if len(stringParams) > 0 {
- sort.Strings(stringParams)
- url += sep + strings.Join(stringParams, "&")
- }
- return TrustedResourceURL{url + fragment}
-}
-
-// TrustedResourceURLFromConstant constructs a TrustedResourceURL with its underlying
-// URL set to the given url, which must be an untyped string constant.
-//
-// No runtime validation or sanitization is performed on url; being under
-// application control, it is simply assumed to comply with the TrustedResourceURL type
-// contract.
-func TrustedResourceURLFromConstant(url stringConstant) TrustedResourceURL {
- return TrustedResourceURL{string(url)}
-}
-
-// TrustedResourceURLFormatFromConstant constructs a TrustedResourceURL from a
-// format string, which must be an untyped string constant, and string arguments.
-//
-// Arguments are specified as a map of labels, which must contain only alphanumeric
-// and '_' runes, to string values. Each `%{<label>}` marker in the format string is
-// replaced by the string value identified by <label> after it has been URL-escaped.
-// Arguments that do not match any label in the format string are ignored.
-//
-// The format string must have a prefix of one of the following forms:
-// * `https://<origin>/`
-// * `//<origin>/`
-// * `/<pathStart>`
-// * `about:blank#`
-//
-// `<origin>` must contain only alphanumerics, '.', ':', '[', ']', or '-', and
-// `<pathStart>` is any character except `/` and `\`.
-func TrustedResourceURLFormatFromConstant(format stringConstant, args map[string]string) (TrustedResourceURL, error) {
- return trustedResourceURLFormat(string(format), args)
-}
-
-// TrustedResourceURLFormatFromFlag is a variant of TrustedResourceURLFormatFromConstant
-// that constructs a TrustedResourceURL from a format string, which is given as a flag.Value,
-// and string arguments.
-//
-// See TrustedResourceURLFormatFromConstant for more details about format
-// string markers and validation.
-func TrustedResourceURLFormatFromFlag(format flag.Value, args map[string]string) (TrustedResourceURL, error) {
- return trustedResourceURLFormat(fmt.Sprint(format.String()), args)
-}
-
-func trustedResourceURLFormat(format string, args map[string]string) (TrustedResourceURL, error) {
- if !safehtmlutil.IsSafeTrustedResourceURLPrefix(format) {
- return TrustedResourceURL{}, fmt.Errorf("%q is a disallowed TrustedResourceURL format string", format)
- }
- var err error
- ret := trustedResourceURLFormatMarkerPattern.ReplaceAllStringFunc(format, func(match string) string {
- argName := match[len("%{") : len(match)-len("}")]
- argVal, ok := args[argName]
- if !ok {
- if err == nil {
- // Report an error for the first missing argument.
- err = fmt.Errorf("expected argument named %q", argName)
- }
- return ""
- }
- if safehtmlutil.URLContainsDoubleDotSegment(argVal) {
- // Reject values containing the ".." dot-segment to prevent the final TrustedResourceURL from referencing
- // a resource higher up in the path name hierarchy than the path specified in the prefix.
- err = fmt.Errorf(`argument %q with value %q must not contain ".."`, argName, argVal)
- return ""
- }
- // QueryEscapeURL escapes some non-reserved characters in the path
- // segment (e.g. '/' and '?') in order to prevent the injection of any new path
- // segments or URL components.
- return safehtmlutil.QueryEscapeURL(argVal)
- })
- return TrustedResourceURL{ret}, err
-}
-
-// trustedResourceURLFormatMarkerPattern matches markers in TrustedResourceURLFormat
-// format strings.
-var trustedResourceURLFormatMarkerPattern = regexp.MustCompile(`%{[[:word:]]+}`)
-
-// TrustedResourceURLFromFlag returns a TrustedResourceURL containing the string
-// representation of the retrieved value of the flag.
-//
-// In a server setting, flags are part of the application's deployment
-// configuration and are hence considered application-controlled.
-func TrustedResourceURLFromFlag(value flag.Value) TrustedResourceURL {
- return TrustedResourceURL{fmt.Sprint(value.String())}
-}
-
-// String returns the string form of the TrustedResourceURL.
-func (t TrustedResourceURL) String() string {
- return t.str
-}
-
-// TrustedResourceURLAppend URL-escapes a string and appends it to the TrustedResourceURL.
-//
-// This function can only be used if the TrustedResourceURL has a prefix of one of the following
-// forms:
-// * `https://<origin>/`
-// * `//<origin>/`
-// * `/<pathStart>`
-// * `about:blank#`
-//
-// `<origin>` must contain only alphanumerics, '.', ':', '[', ']', or '-', and
-// `<pathStart>` is any character except `/` and `\`.
-func TrustedResourceURLAppend(t TrustedResourceURL, s string) (TrustedResourceURL, error) {
- if !safehtmlutil.IsSafeTrustedResourceURLPrefix(t.str) {
- return TrustedResourceURL{}, fmt.Errorf("cannot append to TrustedResourceURL %q because it has an unsafe prefix", t)
- }
- return TrustedResourceURL{t.str + safehtmlutil.QueryEscapeURL(s)}, nil
-}
diff --git a/vendor/github.com/google/safehtml/uncheckedconversions/uncheckedconversions.go b/vendor/github.com/google/safehtml/uncheckedconversions/uncheckedconversions.go
deleted file mode 100644
index 1b753a52d..000000000
--- a/vendor/github.com/google/safehtml/uncheckedconversions/uncheckedconversions.go
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-// Package uncheckedconversions provides functions to create values of package
-// safehtml types from plain strings. Use of these functions could potentially
-// result in instances of safe HTML types that violate their type contracts,
-// and hence result in security vulnerabilties.
-//
-// Avoid use of the functions in this file whenever possible; instead prefer to
-// create instances of package safehtml types using inherently safe builders or
-// template systems.
-//
-// Example appropriate uses include:
-// * Wrapping the result of general-purpose or application-specific content
-// sanitizer libraries.
-// * Wrapping the result of rendering strictly contextually autoescaping
-// templates (assuming the template's autoescaping implementation is indeed
-// strict enough to support the type contract).
-package uncheckedconversions
-
-import (
- "github.com/google/safehtml/internal/raw"
- "github.com/google/safehtml"
-)
-
-var html = raw.HTML.(func(string) safehtml.HTML)
-var script = raw.Script.(func(string) safehtml.Script)
-var style = raw.Style.(func(string) safehtml.Style)
-var styleSheet = raw.StyleSheet.(func(string) safehtml.StyleSheet)
-var url = raw.URL.(func(string) safehtml.URL)
-var trustedResourceURL = raw.TrustedResourceURL.(func(string) safehtml.TrustedResourceURL)
-var identifier = raw.Identifier.(func(string) safehtml.Identifier)
-
-// HTMLFromStringKnownToSatisfyTypeContract converts a string into a HTML.
-//
-func HTMLFromStringKnownToSatisfyTypeContract(s string) safehtml.HTML {
- return html(s)
-}
-
-// ScriptFromStringKnownToSatisfyTypeContract converts a string into a Script.
-//
-// Users of this function must ensure themselves that the string does not
-// contain unsafe script. Note in particular that '<' is dangerous, even when
-// inside JavaScript strings, and so should always be forbidden or JavaScript
-// escaped in user controlled input. For example, if
-// "</script><script>evil</script>" were interpolated inside a JavaScript
-// string,it would break out of the context of the original script element and
-// "evil" would execute. Also note that within an HTML script (raw text)
-// element, HTML character references, such as "&lt;" are not allowed. See
-// http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements.
-func ScriptFromStringKnownToSatisfyTypeContract(s string) safehtml.Script {
- return script(s)
-}
-
-// StyleFromStringKnownToSatisfyTypeContract converts a string into a Style.
-//
-// Users of thie function must ensure themselves that the string:
-// * Does not contain unsafe CSS.
-// * Does not contain literal angle brackets. Otherwise, it could be unsafe to
-// place a Style into the contents of a <style> element where it can't be
-// HTML escaped (see http://www.w3.org/International/questions/qa-escapes).
-// For example, if the Style containing
-// "font: 'foo <style/><script>evil</script>'" was interpolated within a
-// <style> tag, it would then break out of the style context into HTML.
-// * Does not end in a property value or property name context.
-// For example, a value of "background:url(\"" or "font-" does not satisfy
-// the Style type contract. This rule is enforced to ensure composability:
-// concatenating two incomplete strings that themselves do not contain unsafe
-// CSS can result in an overall string that does. For example, if
-// "javascript:evil())\"" is appended to "background:url(\"", the resulting
-// string may result in the execution of a malicious script.
-//
-// The string may, however, contain literal single or double quotes (for example,
-// in the "content" property). Therefore, the entire style string must be
-// escaped when used in a style attribute.
-//
-// The following example values comply with Style's type contract:
-// width: 1em;
-// height:1em;
-// width: 1em;height: 1em;
-// background:url('http://url');
-//
-// In addition, the empty string is safe for use in a style attribute.
-//
-// The following example values do NOT comply with this type's contract:
-// background: red --- missing a trailing semi-colon
-// background: --- missing a value and a trailing semi-colon
-// 1em --- missing an attribute name, which provides context
-// for the value
-//
-// See also http://www.w3.org/TR/css3-syntax/.
-func StyleFromStringKnownToSatisfyTypeContract(s string) safehtml.Style {
- return style(s)
-}
-
-// StyleSheetFromStringKnownToSatisfyTypeContract converts a string into a StyleSheet.
-//
-// Users of this function must ensure themselves that the string does not
-// contain unsafe script. Note in particular that '<' is dangerous, even when
-// inside CSS strings, and so should always be forbidden or CSS-escaped in
-// user controlled input. For example, if
-// "</style><script>evil</script>" were interpolated inside a CSS string, it
-// would break out of the context of the original style element and "evil" would
-// execute. Also note that within an HTML style (raw text) element, HTML
-// character references, such as "&lt;", are not allowed.See
-// http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements
-// (Similar considerations apply to the style element.)
-func StyleSheetFromStringKnownToSatisfyTypeContract(s string) safehtml.StyleSheet {
- return styleSheet(s)
-}
-
-// URLFromStringKnownToSatisfyTypeContract converts a string into a URL.
-//
-func URLFromStringKnownToSatisfyTypeContract(s string) safehtml.URL {
- return url(s)
-}
-
-// TrustedResourceURLFromStringKnownToSatisfyTypeContract converts a string into a TrustedResourceURL.
-//
-func TrustedResourceURLFromStringKnownToSatisfyTypeContract(s string) safehtml.TrustedResourceURL {
- return trustedResourceURL(s)
-}
-
-// IdentifierFromStringKnownToSatisfyTypeContract converts a string into a Identifier.
-//
-func IdentifierFromStringKnownToSatisfyTypeContract(s string) safehtml.Identifier {
- return identifier(s)
-}
diff --git a/vendor/github.com/google/safehtml/url.go b/vendor/github.com/google/safehtml/url.go
deleted file mode 100644
index 6e772219c..000000000
--- a/vendor/github.com/google/safehtml/url.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package safehtml
-
-import (
- "regexp"
- "strings"
-)
-
-// A URL is an immutable string-like type that is safe to use in URL contexts in
-// DOM APIs and HTML documents.
-//
-// URL guarantees that its value as a string will not cause untrusted script execution
-// when evaluated as a hyperlink URL in a browser.
-//
-// Values of this type are guaranteed to be safe to use in URL/hyperlink contexts,
-// such as assignment to URL-valued DOM properties, in the sense that the use
-// will not result in a Cross-site Scripting (XSS) vulnerability. Similarly, URLs can
-// be interpolated into the URL context of an HTML template (e.g. inside a href attribute).
-// However, appropriate HTML-escaping must still be applied.
-//
-// Note that this type's contract does not imply any guarantees regarding the resource
-// the URL refers to. In particular, URLs are not safe to use in a context
-// where the referred-to resource is interpreted as trusted code, e.g., as the src of
-// a script tag. For safely loading trusted resources, use the TrustedResourceURL type.
-type URL struct {
- // We declare a URL not as a string but as a struct wrapping a string
- // to prevent construction of URL values through string conversion.
- str string
-}
-
-// InnocuousURL is an innocuous URL generated by URLSanitized when passed an unsafe URL.
-//
-// about:invalid is registered in http://www.w3.org/TR/css3-values/#about-invalid,
-// and "references a non-existent document with a generic error condition. It can be
-// used when a URI is necessary, but the default value shouldn't be resolveable as any
-// type of document."
-//
-// http://tools.ietf.org/html/rfc6694#section-2.1 permits about URLs to contain
-// a fragment, which is not to be considered when determining if an about URL is
-// well-known.
-const InnocuousURL = "about:invalid#zGoSafez"
-
-// URLSanitized returns a URL whose value is url, validating that the input string matches
-// a pattern of commonly used safe URLs. If url fails validation, this method returns a
-// URL containing InnocuousURL.
-//
-// url may be a URL with the http, https, ftp or mailto scheme, or a relative URL,
-// i.e. a URL without a scheme. Specifically, a relative URL may be scheme-relative,
-// absolute-path-relative, or path-relative. See
-// http://url.spec.whatwg.org/#concept-relative-url.
-//
-// url may also be a base64 data URL with an allowed audio, image or video MIME type.
-//
-// No attempt is made at validating that the URL percent-decodes to structurally valid or
-// interchange-valid UTF-8 since the percent-decoded representation is unsafe to use in an
-// HTML context regardless of UTF-8 validity.
-func URLSanitized(url string) URL {
- if !isSafeURL(url) {
- return URL{InnocuousURL}
- }
- return URL{url}
-}
-
-// safeURLPattern matches URLs that
-// (a) Start with a scheme in an allowlist (http, https, mailto, ftp); or
-// (b) Contain no scheme. To ensure that the URL cannot be interpreted as a
-// disallowed scheme URL, ':' may only appear after one of the runes [/?#].
-//
-// The origin (RFC 6454) in which a URL is loaded depends on
-// its scheme. We assume that the scheme used by the current document is HTTPS, HTTP, or
-// something equivalent. We allow relative URLs unless in a particularly sensitive context
-// called a "TrustedResourceUrl" context. In a non-TrustedResourceURL context we allow absolute
-// URLs whose scheme is on a white-list.
-//
-// The position of the first colon (':') character determines whether a URL is absolute or relative.
-// Looking at the prefix leading up to the first colon allows us to identify relative and absolute URLs,
-// extract the scheme, and minimize the risk of a user-agent concluding a URL specifies a scheme not in
-// our allowlist.
-//
-// According to RFC 3986 Section 3, the normative interpretation of the canonicial WHATWG specification
-// (https://url.spec.whatwg.org/#url-scheme-string), colons can appear in a URL in these locations:
-// * A colon after a non-empty run of (ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )) ends a scheme.
-// If the colon after the scheme is not followed by "//" then any subsequent colons are part
-// of an opaque URI body.
-// * Otherwise, a colon after a hash (#) must be in the fragment.
-// * Otherwise, a colon after a (?) must be in the query.
-// * Otherwise, a colon after a single solidus ("/") must be in the path.
-// * Otherwise, a colon after a double solidus ("//") must be in the authority (before port).
-// * Otherwise, a colon after a valid protocol must be in the opaque part of the URL.
-var safeURLPattern = regexp.MustCompile(`^(?:(?:https?|mailto|ftp):|[^:/?#]*(?:[/?#]|$))`)
-
-// dataURLPattern matches base-64 data URLs (RFC 2397), with the first capture group being the media type
-// specification given as a MIME type.
-//
-// Note: this pattern does not match data URLs containig media type specifications with optional parameters,
-// such as `data:text/javascript;charset=UTF-8;base64,...`. This is ok since this pattern only needs to
-// match audio, image and video MIME types in its capture group.
-var dataURLPattern = regexp.MustCompile(`^data:([^;,]*);base64,[a-z0-9+/]+=*$`)
-
-// safeMIMETypePattern matches MIME types that are safe to include in a data URL.
-var safeMIMETypePattern = regexp.MustCompile(`^(?:audio/(?:3gpp2|3gpp|aac|midi|mp3|mp4|mpeg|oga|ogg|opus|x-m4a|x-matroska|x-wav|wav|webm)|image/(?:bmp|gif|jpeg|jpg|png|tiff|webp|x-icon)|video/(?:mpeg|mp4|ogg|webm|x-matroska))$`)
-
-// isSafeURL matches url to a subset of URLs that will not cause script execution if used in
-// a URL context within a HTML document. Specifically, this method returns true if url:
-// (a) Starts with a scheme in the default allowlist (http, https, mailto, ftp); or
-// (b) Contains no scheme. To ensure that the URL cannot be interpreted as a
-// disallowed scheme URL, the runes ':', and '&' may only appear
-// after one of the runes [/?#].
-func isSafeURL(url string) bool {
- // Ignore case.
- url = strings.ToLower(url)
- if safeURLPattern.MatchString(url) {
- return true
- }
- submatches := dataURLPattern.FindStringSubmatch(url)
- return len(submatches) == 2 && safeMIMETypePattern.MatchString(submatches[1])
-}
-
-// String returns the string form of the URL.
-func (u URL) String() string {
- return u.str
-}
diff --git a/vendor/github.com/google/safehtml/urlset.go b/vendor/github.com/google/safehtml/urlset.go
deleted file mode 100644
index 8d74a7732..000000000
--- a/vendor/github.com/google/safehtml/urlset.go
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) 2017 The Go Authors. All rights reserved.
-//
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file or at
-// https://developers.google.com/open-source/licenses/bsd
-
-package safehtml
-
-import (
- "bytes"
- "strconv"
-)
-
-// https://infra.spec.whatwg.org/#ascii-whitespace
-// ASCII whitespace is U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020 SPACE.
-var asciiWhitespace [256]bool
-
-// Metacharacters that affect parsing of srcset values.
-var srcsetMetachars [256]bool
-
-func init() {
- asciiWhitespace['\t'] = true
- asciiWhitespace[' '] = true
- asciiWhitespace['\n'] = true
- asciiWhitespace['\f'] = true
- asciiWhitespace['\r'] = true
-
- srcsetMetachars['\t'] = true
- srcsetMetachars[' '] = true
- srcsetMetachars['\n'] = true
- srcsetMetachars['\f'] = true
- srcsetMetachars['\r'] = true
- srcsetMetachars[','] = true
-}
-
-// URLSetSanitized returns a safe srcset by individually vetting each
-// substring that specifies a URL.
-//
-// https://html.spec.whatwg.org/multipage/images.html#srcset-attributes
-func URLSetSanitized(str string) URLSet {
- var buffer bytes.Buffer
-
- for len(str) != 0 {
- // Consume one image candidate
- var url, metadata string
- _, str = consumeIn(str, asciiWhitespace)
- url, str = consumeNotIn(str, asciiWhitespace)
- _, str = consumeIn(str, asciiWhitespace)
- metadata, str = consumeNotIn(str, srcsetMetachars)
- _, str = consumeIn(str, asciiWhitespace)
-
- // Append sanitized content onto buffer.
- if len(url) != 0 && isSafeURL(url) && isOptionalSrcMetadataWellFormed(metadata) {
- if buffer.Len() != 0 {
- // The space before the comma is necessary because
- // a comma adjacent to a URL will attach to it.
- buffer.WriteString(" , ")
- }
- // URL may contain commas. Disambiguate.
- appendURLToSet(url, &buffer)
- if len(metadata) != 0 {
- buffer.WriteByte(' ')
- buffer.WriteString(metadata)
- }
- }
-
- // Consume any trailing comma
- if len(str) == 0 || str[0] != ',' {
- break
- }
- str = str[1:]
- }
-
- if buffer.Len() == 0 {
- return URLSet{InnocuousURL}
- }
-
- return URLSet{buffer.String()}
-}
-
-// appendURLToSet appends a URL so that it does not start or end with a comma
-//
-// https://html.spec.whatwg.org/multipage/images.html#srcset-attributes
-// parsing step 2 which says:
-// """
-// A valid non-empty URL that does not start or end with a U+002C COMMA character (,),
-// referencing a non-interactive, optionally animated, image resource that is neither
-// paged nor scripted
-// """
-//
-// Simply replacing all commas would break data:image/png;base64,IMAGECONTENT
-// Note: This breaks data URLs with empty content since they end with a comma.
-// We could handle that case by appending a '#'.
-func appendURLToSet(url string, buffer *bytes.Buffer) {
- n := len(url)
- left, right := 0, n
- if url[left] == ',' {
- buffer.WriteString("%2c")
- left++
- }
- commaAtEnd := false
- if left < right && url[right-1] == ',' {
- commaAtEnd = true
- right--
- }
- buffer.WriteString(url[left:right])
- if commaAtEnd {
- buffer.WriteString("%2c")
- }
-}
-
-// consumeNotIn uses bytes in str as bit indices in mask to find
-// the least index >= left whose byte corresponds to a zero bit.
-func consumeNotIn(str string, mask [256]bool) (consumed, rest string) {
- i, n := 0, len(str)
- for ; i < n; i++ {
- if mask[str[i]] {
- return str[0:i], str[i:n]
- }
- }
- return str, ""
-}
-
-// consumeIn is like consumeNotIn but treats mask as inverted.
-func consumeIn(str string, mask [256]bool) (consumed, rest string) {
- for i, n := 0, len(str); i < n; i++ {
- if !mask[str[i]] {
- return str[0:i], str[i:n]
- }
- }
- return str, ""
-}
-
-// isOptionalSrcMetadataWellFormed is true when its input is empty and
-// when it is a floating point number optionally followed by an ASCII letter.
-func isOptionalSrcMetadataWellFormed(metadata string) bool {
- // srcset for both image candidates (<img srcset>) and
- // the proposal for script allow a number and an optional letter
- // afterwards.
- n := len(metadata)
- if n == 0 {
- // Metadata is optional
- return true
- }
- metadataPrefix := metadata
- if last := metadata[n-1] | 32; 'a' <= last && last <= 'z' {
- metadataPrefix = metadata[0 : n-1]
- }
- // This overmatches
- // html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-floating-point-number
- // but is sufficient.
- _, err := strconv.ParseFloat(metadataPrefix, 64)
- return err == nil
-}
-
-// URLSet corresponds to the value of a srcset attribute outside a
-// TrustedResourceURL context.
-type URLSet struct {
- // We declare a URLSet not as a string but as a struct wrapping a string
- // to prevent construction of URL values through string conversion.
- str string
-}
-
-// String returns the string content of a URLSet
-func (s URLSet) String() string {
- return s.str
-}