diff options
Diffstat (limited to 'libgo/go/net/url/url.go')
-rw-r--r-- | libgo/go/net/url/url.go | 90 |
1 files changed, 55 insertions, 35 deletions
diff --git a/libgo/go/net/url/url.go b/libgo/go/net/url/url.go index d90f5f0..20de0f6 100644 --- a/libgo/go/net/url/url.go +++ b/libgo/go/net/url/url.go @@ -425,31 +425,31 @@ func (u *Userinfo) String() string { return s } -// Maybe rawurl is of the form scheme:path. +// Maybe rawURL is of the form scheme:path. // (Scheme must be [a-zA-Z][a-zA-Z0-9+-.]*) -// If so, return scheme, path; else return "", rawurl. -func getscheme(rawurl string) (scheme, path string, err error) { - for i := 0; i < len(rawurl); i++ { - c := rawurl[i] +// If so, return scheme, path; else return "", rawURL. +func getScheme(rawURL string) (scheme, path string, err error) { + for i := 0; i < len(rawURL); i++ { + c := rawURL[i] switch { case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z': // do nothing case '0' <= c && c <= '9' || c == '+' || c == '-' || c == '.': if i == 0 { - return "", rawurl, nil + return "", rawURL, nil } case c == ':': if i == 0 { return "", "", errors.New("missing protocol scheme") } - return rawurl[:i], rawurl[i+1:], nil + return rawURL[:i], rawURL[i+1:], nil default: // we have encountered an invalid character, // so there is no valid scheme - return "", rawurl, nil + return "", rawURL, nil } } - return "", rawurl, nil + return "", rawURL, nil } // split slices s into two substrings separated by the first occurrence of @@ -466,15 +466,15 @@ func split(s string, sep byte, cutc bool) (string, string) { return s[:i], s[i:] } -// Parse parses rawurl into a URL structure. +// Parse parses a raw url into a URL structure. // -// The rawurl may be relative (a path, without a host) or absolute +// The url may be relative (a path, without a host) or absolute // (starting with a scheme). Trying to parse a hostname and path // without a scheme is invalid but may not necessarily return an // error, due to parsing ambiguities. -func Parse(rawurl string) (*URL, error) { +func Parse(rawURL string) (*URL, error) { // Cut off #frag - u, frag := split(rawurl, '#', true) + u, frag := split(rawURL, '#', true) url, err := parse(u, false) if err != nil { return nil, &Error{"parse", u, err} @@ -483,20 +483,20 @@ func Parse(rawurl string) (*URL, error) { return url, nil } if err = url.setFragment(frag); err != nil { - return nil, &Error{"parse", rawurl, err} + return nil, &Error{"parse", rawURL, err} } return url, nil } -// ParseRequestURI parses rawurl into a URL structure. It assumes that -// rawurl was received in an HTTP request, so the rawurl is interpreted +// ParseRequestURI parses a raw url into a URL structure. It assumes that +// url was received in an HTTP request, so the url is interpreted // only as an absolute URI or an absolute path. -// The string rawurl is assumed not to have a #fragment suffix. +// The string url is assumed not to have a #fragment suffix. // (Web browsers strip #fragment before sending the URL to a web server.) -func ParseRequestURI(rawurl string) (*URL, error) { - url, err := parse(rawurl, true) +func ParseRequestURI(rawURL string) (*URL, error) { + url, err := parse(rawURL, true) if err != nil { - return nil, &Error{"parse", rawurl, err} + return nil, &Error{"parse", rawURL, err} } return url, nil } @@ -505,27 +505,27 @@ func ParseRequestURI(rawurl string) (*URL, error) { // viaRequest is true, the URL is assumed to have arrived via an HTTP request, // in which case only absolute URLs or path-absolute relative URLs are allowed. // If viaRequest is false, all forms of relative URLs are allowed. -func parse(rawurl string, viaRequest bool) (*URL, error) { +func parse(rawURL string, viaRequest bool) (*URL, error) { var rest string var err error - if stringContainsCTLByte(rawurl) { + if stringContainsCTLByte(rawURL) { return nil, errors.New("net/url: invalid control character in URL") } - if rawurl == "" && viaRequest { + if rawURL == "" && viaRequest { return nil, errors.New("empty url") } url := new(URL) - if rawurl == "*" { + if rawURL == "*" { url.Path = "*" return url, nil } // Split off possible leading "http:", "mailto:", etc. // Cannot contain escaped characters. - if url.Scheme, rest, err = getscheme(rawurl); err != nil { + if url.Scheme, rest, err = getScheme(rawURL); err != nil { return nil, err } url.Scheme = strings.ToLower(url.Scheme) @@ -909,15 +909,22 @@ func (v Values) Del(key string) { delete(v, key) } +// Has checks whether a given key is set. +func (v Values) Has(key string) bool { + _, ok := v[key] + return ok +} + // 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 or semicolons. A setting without an equals sign is -// interpreted as a key set to an empty value. +// 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) @@ -927,11 +934,15 @@ func ParseQuery(query string) (Values, error) { func parseQuery(m Values, query string) (err error) { for query != "" { key := query - if i := strings.IndexAny(key, "&;"); i >= 0 { + 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 } @@ -1009,6 +1020,8 @@ func resolvePath(base, ref string) string { ) first := true remaining := full + // We want to return a leading '/', so write it now. + dst.WriteByte('/') for i >= 0 { i = strings.IndexByte(remaining, '/') if i < 0 { @@ -1023,10 +1036,12 @@ func resolvePath(base, ref string) string { } if elem == ".." { - str := dst.String() + // Ignore the leading '/' we already wrote. + str := dst.String()[1:] index := strings.LastIndexByte(str, '/') dst.Reset() + dst.WriteByte('/') if index == -1 { first = true } else { @@ -1045,7 +1060,12 @@ func resolvePath(base, ref string) string { dst.WriteByte('/') } - return "/" + strings.TrimPrefix(dst.String(), "/") + // We wrote an initial '/', but we don't want two. + r := dst.String() + if len(r) > 1 && r[1] == '/' { + r = r[1:] + } + return r } // IsAbs reports whether the URL is absolute. @@ -1058,11 +1078,11 @@ func (u *URL) IsAbs() bool { // may be relative or absolute. Parse returns nil, err on parse // failure, otherwise its return value is the same as ResolveReference. func (u *URL) Parse(ref string) (*URL, error) { - refurl, err := Parse(ref) + refURL, err := Parse(ref) if err != nil { return nil, err } - return u.ResolveReference(refurl), nil + return u.ResolveReference(refURL), nil } // ResolveReference resolves a URI reference to an absolute URI from @@ -1151,8 +1171,8 @@ func (u *URL) Port() string { // splitHostPort separates host and port. If the port is not valid, it returns // the entire input as host, and it doesn't check the validity of the host. // Unlike net.SplitHostPort, but per RFC 3986, it requires ports to be numeric. -func splitHostPort(hostport string) (host, port string) { - host = hostport +func splitHostPort(hostPort string) (host, port string) { + host = hostPort colon := strings.LastIndexByte(host, ':') if colon != -1 && validOptionalPort(host[colon:]) { |