diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2020-12-29 00:28:27 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-29 00:28:27 +0800 |
commit | 11555d850b0b5977d49b458db2be6305fe4f645d (patch) | |
tree | d75468bf043878f67298f91e2b5376c2315e9538 /vendor/github.com | |
parent | 3175d08626232e85df64bec95fa62aac227e252a (diff) | |
download | gitea-11555d850b0b5977d49b458db2be6305fe4f645d.tar.gz gitea-11555d850b0b5977d49b458db2be6305fe4f645d.zip |
Fix bug of link query order on markdown render (#14156)
* Fix bug of link query order on markdown render
* Fix bluemonday bug and fix one wrong test
Co-authored-by: 6543 <6543@obermui.de>
Diffstat (limited to 'vendor/github.com')
-rw-r--r-- | vendor/github.com/microcosm-cc/bluemonday/sanitize.go | 79 |
1 files changed, 68 insertions, 11 deletions
diff --git a/vendor/github.com/microcosm-cc/bluemonday/sanitize.go b/vendor/github.com/microcosm-cc/bluemonday/sanitize.go index 103f39f6e5..a58333aa65 100644 --- a/vendor/github.com/microcosm-cc/bluemonday/sanitize.go +++ b/vendor/github.com/microcosm-cc/bluemonday/sanitize.go @@ -122,22 +122,79 @@ func escapeUrlComponent(val string) string { return w.String() } -func sanitizedUrl(val string) (string, error) { +// Query represents a query +type Query struct { + Key string + Value string +} + +func parseQuery(query string) (values []Query, err error) { + for query != "" { + key := query + if i := strings.IndexAny(key, "&;"); i >= 0 { + key, query = key[:i], key[i+1:] + } else { + query = "" + } + if key == "" { + continue + } + value := "" + if i := strings.Index(key, "="); i >= 0 { + key, value = key[:i], key[i+1:] + } + key, err1 := url.QueryUnescape(key) + if err1 != nil { + if err == nil { + err = err1 + } + continue + } + value, err1 = url.QueryUnescape(value) + if err1 != nil { + if err == nil { + err = err1 + } + continue + } + values = append(values, Query{ + Key: key, + Value: value, + }) + } + return values, err +} + +func encodeQueries(queries []Query) string { + var b strings.Builder + for i, query := range queries { + b.WriteString(url.QueryEscape(query.Key)) + b.WriteString("=") + b.WriteString(url.QueryEscape(query.Value)) + if i < len(queries)-1 { + b.WriteString("&") + } + } + return b.String() +} + +func sanitizedURL(val string) (string, error) { u, err := url.Parse(val) if err != nil { return "", err } + + // we use parseQuery but not u.Query to keep the order not change because + // url.Values is a map which has a random order. + queryValues, err := parseQuery(u.RawQuery) + if err != nil { + return "", err + } // sanitize the url query params - sanitizedQueryValues := make(url.Values, 0) - queryValues := u.Query() - for k, vals := range queryValues { - sk := html.EscapeString(k) - for _, v := range vals { - sv := v - sanitizedQueryValues.Add(sk, sv) - } + for i, query := range queryValues { + queryValues[i].Key = html.EscapeString(query.Key) } - u.RawQuery = sanitizedQueryValues.Encode() + u.RawQuery = encodeQueries(queryValues) // u.String() will also sanitize host/scheme/user/pass return u.String(), nil } @@ -158,7 +215,7 @@ func (p *Policy) writeLinkableBuf(buff *bytes.Buffer, token *html.Token) { tokenBuff.WriteString(html.EscapeString(attr.Val)) continue } - u, err := sanitizedUrl(u) + u, err := sanitizedURL(u) if err == nil { tokenBuff.WriteString(u) } else { |