| // Copyright 2012 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 vendor | 
 |  | 
 | import ( | 
 | 	"encoding/xml" | 
 | 	"fmt" | 
 | 	"io" | 
 | 	"strings" | 
 | ) | 
 |  | 
 | // charsetReader returns a reader for the given charset. Currently | 
 | // it only supports UTF-8 and ASCII. Otherwise, it returns a meaningful | 
 | // error which is printed by go get, so the user can find why the package | 
 | // wasn't downloaded if the encoding is not supported. Note that, in | 
 | // order to reduce potential errors, ASCII is treated as UTF-8 (i.e. characters | 
 | // greater than 0x7f are not rejected). | 
 | func charsetReader(charset string, input io.Reader) (io.Reader, error) { | 
 | 	switch strings.ToLower(charset) { | 
 | 	case "ascii": | 
 | 		return input, nil | 
 | 	default: | 
 | 		return nil, fmt.Errorf("can't decode XML document using charset %q", charset) | 
 | 	} | 
 | } | 
 |  | 
 | type metaImport struct { | 
 | 	Prefix, VCS, RepoRoot string | 
 | } | 
 |  | 
 | // parseMetaGoImports returns meta imports from the HTML in r. | 
 | // Parsing ends at the end of the <head> section or the beginning of the <body>. | 
 | func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) { | 
 | 	d := xml.NewDecoder(r) | 
 | 	d.CharsetReader = charsetReader | 
 | 	d.Strict = false | 
 | 	var t xml.Token | 
 | 	for { | 
 | 		t, err = d.RawToken() | 
 | 		if err != nil { | 
 | 			if err == io.EOF || len(imports) > 0 { | 
 | 				err = nil | 
 | 			} | 
 | 			return | 
 | 		} | 
 | 		if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") { | 
 | 			return | 
 | 		} | 
 | 		if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") { | 
 | 			return | 
 | 		} | 
 | 		e, ok := t.(xml.StartElement) | 
 | 		if !ok || !strings.EqualFold(e.Name.Local, "meta") { | 
 | 			continue | 
 | 		} | 
 | 		if attrValue(e.Attr, "name") != "go-import" { | 
 | 			continue | 
 | 		} | 
 | 		if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 { | 
 | 			imports = append(imports, metaImport{ | 
 | 				Prefix:   f[0], | 
 | 				VCS:      f[1], | 
 | 				RepoRoot: f[2], | 
 | 			}) | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | // attrValue returns the attribute value for the case-insensitive key | 
 | // `name', or the empty string if nothing is found. | 
 | func attrValue(attrs []xml.Attr, name string) string { | 
 | 	for _, a := range attrs { | 
 | 		if strings.EqualFold(a.Name.Local, name) { | 
 | 			return a.Value | 
 | 		} | 
 | 	} | 
 | 	return "" | 
 | } |