mirror of
https://github.com/muraenateam/muraena.git
synced 2026-01-23 02:24:05 +00:00
95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
package core
|
|
|
|
import (
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
// Values maps a string key to a list of values.
|
|
// It is typically used for query parameters and form values.
|
|
// Unlike in the http.Header map, the keys in a Values map
|
|
// are case-sensitive.
|
|
type Values map[string][]string
|
|
|
|
// ParseQuery parses the URL-encoded query string and returns
|
|
// a map listing the values specified for each key.
|
|
// ParseQuery always returns a non-nil map containing all the
|
|
// valid query parameters found; err describes the first decoding error
|
|
// encountered, if any.
|
|
//
|
|
// Query is expected to be a list of key=value settings separated by ampersands.
|
|
// A setting without an equals sign is interpreted as a key set to an empty
|
|
// value.
|
|
// Settings containing a non-URL-encoded semicolon are considered invalid.
|
|
func ParseQuery(query string) (Values, error) {
|
|
m := make(Values)
|
|
err := parseQuery(m, query)
|
|
return m, err
|
|
}
|
|
|
|
func parseQuery(m Values, query string) (err error) {
|
|
for query != "" {
|
|
key := query
|
|
if i := strings.IndexAny(key, "&"); i >= 0 {
|
|
key, query = key[:i], key[i+1:]
|
|
} else {
|
|
query = ""
|
|
}
|
|
//if strings.Contains(key, ";") {
|
|
// err = fmt.Errorf("invalid semicolon separator in query")
|
|
// continue
|
|
//}
|
|
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
|
|
}
|
|
m[key] = append(m[key], value)
|
|
}
|
|
return err
|
|
}
|
|
|
|
// Encode encodes the values into "URL encoded" form
|
|
// ("bar=baz&foo=quux") NOT sorted by key.
|
|
func (v Values) Encode() string {
|
|
if v == nil {
|
|
return ""
|
|
}
|
|
var buf strings.Builder
|
|
keys := make([]string, 0, len(v))
|
|
for k := range v {
|
|
keys = append(keys, k)
|
|
}
|
|
|
|
// We don't want to be sorted
|
|
// sort.Strings(keys)
|
|
for _, k := range keys {
|
|
vs := v[k]
|
|
keyEscaped := url.QueryEscape(k)
|
|
for _, v := range vs {
|
|
if buf.Len() > 0 {
|
|
buf.WriteByte('&')
|
|
}
|
|
buf.WriteString(keyEscaped)
|
|
buf.WriteByte('=')
|
|
buf.WriteString(url.QueryEscape(v))
|
|
}
|
|
}
|
|
return buf.String()
|
|
}
|