Source File
url.go
Belonging Package
html/template
// 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 templateimport ()// urlFilter returns its input unless it contains an unsafe scheme in which// case it defangs the entire URL.//// Schemes that cause unintended side effects that are irreversible without user// interaction are considered unsafe. For example, clicking on a "javascript:"// link can immediately trigger JavaScript code execution.//// This filter conservatively assumes that all schemes other than the following// are unsafe:// - http: Navigates to a new website, and may open a new window or tab.// These side effects can be reversed by navigating back to the// previous website, or closing the window or tab. No irreversible// changes will take place without further user interaction with// the new website.// - https: Same as http.// - mailto: Opens an email program and starts a new draft. This side effect// is not irreversible until the user explicitly clicks send; it// can be undone by closing the email program.//// To allow URLs containing other schemes to bypass this filter, developers must// explicitly indicate that such a URL is expected and safe by encapsulating it// in a template.URL value.func urlFilter( ...any) string {, := stringify(...)if == contentTypeURL {return}if !isSafeURL() {return "#" + filterFailsafe}return}// isSafeURL is true if s is a relative URL or if URL has a protocol in// (http, https, mailto).func isSafeURL( string) bool {if , , := strings.Cut(, ":"); && !strings.Contains(, "/") {if !strings.EqualFold(, "http") && !strings.EqualFold(, "https") && !strings.EqualFold(, "mailto") {return false}}return true}// urlEscaper produces an output that can be embedded in a URL query.// The output can be embedded in an HTML attribute without further escaping.func urlEscaper( ...any) string {return urlProcessor(false, ...)}// urlNormalizer 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 '&'.func urlNormalizer( ...any) string {return urlProcessor(true, ...)}// urlProcessor normalizes (when norm is true) or escapes its input to produce// a valid hierarchical or opaque URL part.func urlProcessor( bool, ...any) string {, := stringify(...)if == contentTypeURL {= true}var strings.Builderif processURLOnto(, , &) {return .String()}return}// processURLOnto appends a normalized URL corresponding to its input to b// and reports whether the appended content differs from s.func processURLOnto( string, bool, *strings.Builder) bool {.Grow(len() + 16):= 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 , := 0, len(); < ; ++ {:= []switch {// 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 {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 producerscase '-', '.', '_', '~':continuecase '%':// When normalizing do not re-encode valid escapes.if && +2 < len() && isHex([+1]) && isHex([+2]) {continue}default:// Unreserved according to RFC 3986 sec 2.3if 'a' <= && <= 'z' {continue}if 'A' <= && <= 'Z' {continue}if '0' <= && <= '9' {continue}}.WriteString([:])fmt.Fprintf(, "%%%02x", )= + 1}.WriteString([:])return != 0}// Filters and normalizes srcset values which are comma separated// URLs followed by metadata.func srcsetFilterAndEscaper( ...any) string {, := stringify(...)switch {case contentTypeSrcset:returncase contentTypeURL:// Normalizing gets rid of all HTML whitespace// which separate the image URL from its metadata.var strings.Builderif processURLOnto(, true, &) {= .String()}// Additionally, commas separate one source from another.return strings.ReplaceAll(, ",", "%2c")}var strings.Builder:= 0for := 0; < len(); ++ {if [] == ',' {filterSrcsetElement(, , , &).WriteString(",")= + 1}}filterSrcsetElement(, , len(), &)return .String()}// Derived from https://play.golang.org/p/Dhmj7FORT5const htmlSpaceAndASCIIAlnumBytes = "\x00\x36\x00\x00\x01\x00\xff\x03\xfe\xff\xff\x07\xfe\xff\xff\x07"// isHTMLSpace is true iff c is a whitespace character per// https://infra.spec.whatwg.org/#ascii-whitespacefunc isHTMLSpace( byte) bool {return ( <= 0x20) && 0 != (htmlSpaceAndASCIIAlnumBytes[>>3]&(1<<uint(&0x7)))}func isHTMLSpaceOrASCIIAlnum( byte) bool {return ( < 0x80) && 0 != (htmlSpaceAndASCIIAlnumBytes[>>3]&(1<<uint(&0x7)))}func filterSrcsetElement( string, int, int, *strings.Builder) {:=for < && isHTMLSpace([]) {++}:=for := ; < ; ++ {if isHTMLSpace([]) {=break}}if := [:]; isSafeURL() {// If image metadata is only spaces or alnums then// we don't need to URL normalize it.:= truefor := ; < ; ++ {if !isHTMLSpaceOrASCIIAlnum([]) {= falsebreak}}if {.WriteString([:])processURLOnto(, true, ).WriteString([:])return}}.WriteString("#").WriteString(filterFailsafe)}
![]() |
The pages are generated with Golds v0.7.9-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |