author | Nigel Tao
<nigeltao@golang.org> 2016-04-07 01:50:39 UTC |
committer | Nigel Tao
<nigeltao@golang.org> 2016-04-07 02:10:48 UTC |
parent | bcb71dd18ffab660eaf1580c7cef547aaad6dc87 |
webdav/xml.go | +48 | -48 |
webdav/xml_test.go | +39 | -39 |
diff --git a/webdav/xml.go b/webdav/xml.go index 8705cda..7fb1147 100644 --- a/webdav/xml.go +++ b/webdav/xml.go @@ -14,12 +14,12 @@ import ( "net/http" "time" - "golang.org/x/net/webdav/internal/xml" + ixml "golang.org/x/net/webdav/internal/xml" ) // http://www.webdav.org/specs/rfc4918.html#ELEMENT_lockinfo type lockInfo struct { - XMLName xml.Name `xml:"lockinfo"` + XMLName ixml.Name `xml:"lockinfo"` Exclusive *struct{} `xml:"lockscope>exclusive"` Shared *struct{} `xml:"lockscope>shared"` Write *struct{} `xml:"locktype>write"` @@ -33,7 +33,7 @@ type owner struct { func readLockInfo(r io.Reader) (li lockInfo, status int, err error) { c := &countingReader{r: r} - if err = xml.NewDecoder(c).Decode(&li); err != nil { + if err = ixml.NewDecoder(c).Decode(&li); err != nil { if err == io.EOF { if c.n == 0 { // An empty body means to refresh the lock. @@ -88,7 +88,7 @@ func escape(s string) string { switch s[i] { case '"', '&', '\'', '<', '>': b := bytes.NewBuffer(nil) - xml.EscapeText(b, []byte(s)) + ixml.EscapeText(b, []byte(s)) return b.String() } } @@ -100,14 +100,14 @@ func escape(s string) string { // and directives. // http://www.webdav.org/specs/rfc4918.html#property_values // http://www.webdav.org/specs/rfc4918.html#xml-extensibility -func next(d *xml.Decoder) (xml.Token, error) { +func next(d *ixml.Decoder) (ixml.Token, error) { for { t, err := d.Token() if err != nil { return t, err } switch t.(type) { - case xml.Comment, xml.Directive, xml.ProcInst: + case ixml.Comment, ixml.Directive, ixml.ProcInst: continue default: return t, nil @@ -116,31 +116,31 @@ func next(d *xml.Decoder) (xml.Token, error) { } // http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for propfind) -type propfindProps []xml.Name +type propfindProps []ixml.Name // UnmarshalXML appends the property names enclosed within start to pn. // // It returns an error if start does not contain any properties or if // properties contain values. Character data between properties is ignored. -func (pn *propfindProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { +func (pn *propfindProps) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement) error { for { t, err := next(d) if err != nil { return err } switch t.(type) { - case xml.EndElement: + case ixml.EndElement: if len(*pn) == 0 { return fmt.Errorf("%s must not be empty", start.Name.Local) } return nil - case xml.StartElement: - name := t.(xml.StartElement).Name + case ixml.StartElement: + name := t.(ixml.StartElement).Name t, err = next(d) if err != nil { return err } - if _, ok := t.(xml.EndElement); !ok { + if _, ok := t.(ixml.EndElement); !ok { return fmt.Errorf("unexpected token %T", t) } *pn = append(*pn, name) @@ -150,7 +150,7 @@ func (pn *propfindProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) er // http://www.webdav.org/specs/rfc4918.html#ELEMENT_propfind type propfind struct { - XMLName xml.Name `xml:"DAV: propfind"` + XMLName ixml.Name `xml:"DAV: propfind"` Allprop *struct{} `xml:"DAV: allprop"` Propname *struct{} `xml:"DAV: propname"` Prop propfindProps `xml:"DAV: prop"` @@ -159,7 +159,7 @@ type propfind struct { func readPropfind(r io.Reader) (pf propfind, status int, err error) { c := countingReader{r: r} - if err = xml.NewDecoder(&c).Decode(&pf); err != nil { + if err = ixml.NewDecoder(&c).Decode(&pf); err != nil { if err == io.EOF { if c.n == 0 { // An empty body means to propfind allprop. @@ -190,7 +190,7 @@ func readPropfind(r io.Reader) (pf propfind, status int, err error) { // See http://www.webdav.org/specs/rfc4918.html#data.model.for.resource.properties type Property struct { // XMLName is the fully qualified name that identifies this property. - XMLName xml.Name + XMLName ixml.Name // Lang is an optional xml:lang attribute. Lang string `xml:"xml:lang,attr,omitempty"` @@ -209,8 +209,8 @@ type Property struct { // http://www.webdav.org/specs/rfc4918.html#ELEMENT_error // See multistatusWriter for the "D:" namespace prefix. type xmlError struct { - XMLName xml.Name `xml:"D:error"` - InnerXML []byte `xml:",innerxml"` + XMLName ixml.Name `xml:"D:error"` + InnerXML []byte `xml:",innerxml"` } // http://www.webdav.org/specs/rfc4918.html#ELEMENT_propstat @@ -224,10 +224,10 @@ type propstat struct { // MarshalXML prepends the "D:" namespace prefix on properties in the DAV: namespace // before encoding. See multistatusWriter. -func (ps propstat) MarshalXML(e *xml.Encoder, start xml.StartElement) error { +func (ps propstat) MarshalXML(e *ixml.Encoder, start ixml.StartElement) error { for k, prop := range ps.Prop { if prop.XMLName.Space == "DAV:" { - prop.XMLName = xml.Name{Space: "", Local: "D:" + prop.XMLName.Local} + prop.XMLName = ixml.Name{Space: "", Local: "D:" + prop.XMLName.Local} ps.Prop[k] = prop } } @@ -239,7 +239,7 @@ func (ps propstat) MarshalXML(e *xml.Encoder, start xml.StartElement) error { // http://www.webdav.org/specs/rfc4918.html#ELEMENT_response // See multistatusWriter for the "D:" namespace prefix. type response struct { - XMLName xml.Name `xml:"D:response"` + XMLName ixml.Name `xml:"D:response"` Href []string `xml:"D:href"` Propstat []propstat `xml:"D:propstat"` Status string `xml:"D:status,omitempty"` @@ -264,7 +264,7 @@ type multistatusWriter struct { responseDescription string w http.ResponseWriter - enc *xml.Encoder + enc *ixml.Encoder } // Write validates and emits a DAV response as part of a multistatus response @@ -308,14 +308,14 @@ func (w *multistatusWriter) writeHeader() error { if err != nil { return err } - w.enc = xml.NewEncoder(w.w) - return w.enc.EncodeToken(xml.StartElement{ - Name: xml.Name{ + w.enc = ixml.NewEncoder(w.w) + return w.enc.EncodeToken(ixml.StartElement{ + Name: ixml.Name{ Space: "DAV:", Local: "multistatus", }, - Attr: []xml.Attr{{ - Name: xml.Name{Space: "xmlns", Local: "D"}, + Attr: []ixml.Attr{{ + Name: ixml.Name{Space: "xmlns", Local: "D"}, Value: "DAV:", }}, }) @@ -329,17 +329,17 @@ func (w *multistatusWriter) close() error { if w.enc == nil { return nil } - var end []xml.Token + var end []ixml.Token if w.responseDescription != "" { - name := xml.Name{Space: "DAV:", Local: "responsedescription"} + name := ixml.Name{Space: "DAV:", Local: "responsedescription"} end = append(end, - xml.StartElement{Name: name}, - xml.CharData(w.responseDescription), - xml.EndElement{Name: name}, + ixml.StartElement{Name: name}, + ixml.CharData(w.responseDescription), + ixml.EndElement{Name: name}, ) } - end = append(end, xml.EndElement{ - Name: xml.Name{Space: "DAV:", Local: "multistatus"}, + end = append(end, ixml.EndElement{ + Name: ixml.Name{Space: "DAV:", Local: "multistatus"}, }) for _, t := range end { err := w.enc.EncodeToken(t) @@ -353,9 +353,9 @@ func (w *multistatusWriter) close() error { // http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for proppatch) type proppatchProps []Property -var xmlLangName = xml.Name{Space: "http://www.w3.org/XML/1998/namespace", Local: "lang"} +var xmlLangName = ixml.Name{Space: "http://www.w3.org/XML/1998/namespace", Local: "lang"} -func xmlLang(s xml.StartElement, d string) string { +func xmlLang(s ixml.StartElement, d string) string { for _, attr := range s.Attr { if attr.Name == xmlLangName { return attr.Value @@ -366,19 +366,19 @@ func xmlLang(s xml.StartElement, d string) string { type xmlValue []byte -func (v *xmlValue) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { +func (v *xmlValue) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement) error { // The XML value of a property can be arbitrary, mixed-content XML. // To make sure that the unmarshalled value contains all required // namespaces, we encode all the property value XML tokens into a // buffer. This forces the encoder to redeclare any used namespaces. var b bytes.Buffer - e := xml.NewEncoder(&b) + e := ixml.NewEncoder(&b) for { t, err := next(d) if err != nil { return err } - if e, ok := t.(xml.EndElement); ok && e.Name == start.Name { + if e, ok := t.(ixml.EndElement); ok && e.Name == start.Name { break } if err = e.EncodeToken(t); err != nil { @@ -401,7 +401,7 @@ func (v *xmlValue) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { // // UnmarshalXML returns an error if start does not contain any properties or if // property values contain syntactically incorrect XML. -func (ps *proppatchProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { +func (ps *proppatchProps) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement) error { lang := xmlLang(start, "") for { t, err := next(d) @@ -409,15 +409,15 @@ func (ps *proppatchProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) e return err } switch elem := t.(type) { - case xml.EndElement: + case ixml.EndElement: if len(*ps) == 0 { return fmt.Errorf("%s must not be empty", start.Name.Local) } return nil - case xml.StartElement: + case ixml.StartElement: p := Property{ - XMLName: t.(xml.StartElement).Name, - Lang: xmlLang(t.(xml.StartElement), lang), + XMLName: t.(ixml.StartElement).Name, + Lang: xmlLang(t.(ixml.StartElement), lang), } err = d.DecodeElement(((*xmlValue)(&p.InnerXML)), &elem) if err != nil { @@ -431,29 +431,29 @@ func (ps *proppatchProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) e // http://www.webdav.org/specs/rfc4918.html#ELEMENT_set // http://www.webdav.org/specs/rfc4918.html#ELEMENT_remove type setRemove struct { - XMLName xml.Name + XMLName ixml.Name Lang string `xml:"xml:lang,attr,omitempty"` Prop proppatchProps `xml:"DAV: prop"` } // http://www.webdav.org/specs/rfc4918.html#ELEMENT_propertyupdate type propertyupdate struct { - XMLName xml.Name `xml:"DAV: propertyupdate"` + XMLName ixml.Name `xml:"DAV: propertyupdate"` Lang string `xml:"xml:lang,attr,omitempty"` SetRemove []setRemove `xml:",any"` } func readProppatch(r io.Reader) (patches []Proppatch, status int, err error) { var pu propertyupdate - if err = xml.NewDecoder(r).Decode(&pu); err != nil { + if err = ixml.NewDecoder(r).Decode(&pu); err != nil { return nil, http.StatusBadRequest, err } for _, op := range pu.SetRemove { remove := false switch op.XMLName { - case xml.Name{Space: "DAV:", Local: "set"}: + case ixml.Name{Space: "DAV:", Local: "set"}: // No-op. - case xml.Name{Space: "DAV:", Local: "remove"}: + case ixml.Name{Space: "DAV:", Local: "remove"}: for _, p := range op.Prop { if len(p.InnerXML) > 0 { return nil, http.StatusBadRequest, errInvalidProppatch diff --git a/webdav/xml_test.go b/webdav/xml_test.go index f38504e..7cd14b6 100644 --- a/webdav/xml_test.go +++ b/webdav/xml_test.go @@ -15,7 +15,7 @@ import ( "strings" "testing" - "golang.org/x/net/webdav/internal/xml" + ixml "golang.org/x/net/webdav/internal/xml" ) func TestReadLockInfo(t *testing.T) { @@ -86,7 +86,7 @@ func TestReadLockInfo(t *testing.T) { " <D:owner>gopher</D:owner>\n" + "</D:lockinfo>", lockInfo{ - XMLName: xml.Name{Space: "DAV:", Local: "lockinfo"}, + XMLName: ixml.Name{Space: "DAV:", Local: "lockinfo"}, Exclusive: new(struct{}), Write: new(struct{}), Owner: owner{ @@ -105,7 +105,7 @@ func TestReadLockInfo(t *testing.T) { " </D:owner>\n" + "</D:lockinfo>", lockInfo{ - XMLName: xml.Name{Space: "DAV:", Local: "lockinfo"}, + XMLName: ixml.Name{Space: "DAV:", Local: "lockinfo"}, Exclusive: new(struct{}), Write: new(struct{}), Owner: owner{ @@ -147,7 +147,7 @@ func TestReadPropfind(t *testing.T) { " <A:propname/>\n" + "</A:propfind>", wantPF: propfind{ - XMLName: xml.Name{Space: "DAV:", Local: "propfind"}, + XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, Propname: new(struct{}), }, }, { @@ -163,7 +163,7 @@ func TestReadPropfind(t *testing.T) { " <A:allprop/>\n" + "</A:propfind>", wantPF: propfind{ - XMLName: xml.Name{Space: "DAV:", Local: "propfind"}, + XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, Allprop: new(struct{}), }, }, { @@ -174,9 +174,9 @@ func TestReadPropfind(t *testing.T) { " <A:include><A:displayname/></A:include>\n" + "</A:propfind>", wantPF: propfind{ - XMLName: xml.Name{Space: "DAV:", Local: "propfind"}, + XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, Allprop: new(struct{}), - Include: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, + Include: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}}, }, }, { desc: "propfind: include followed by allprop", @@ -186,9 +186,9 @@ func TestReadPropfind(t *testing.T) { " <A:allprop/>\n" + "</A:propfind>", wantPF: propfind{ - XMLName: xml.Name{Space: "DAV:", Local: "propfind"}, + XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, Allprop: new(struct{}), - Include: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, + Include: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}}, }, }, { desc: "propfind: propfind", @@ -197,8 +197,8 @@ func TestReadPropfind(t *testing.T) { " <A:prop><A:displayname/></A:prop>\n" + "</A:propfind>", wantPF: propfind{ - XMLName: xml.Name{Space: "DAV:", Local: "propfind"}, - Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, + XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, + Prop: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}}, }, }, { desc: "propfind: prop with ignored comments", @@ -210,8 +210,8 @@ func TestReadPropfind(t *testing.T) { " </A:prop>\n" + "</A:propfind>", wantPF: propfind{ - XMLName: xml.Name{Space: "DAV:", Local: "propfind"}, - Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, + XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, + Prop: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}}, }, }, { desc: "propfind: propfind with ignored whitespace", @@ -220,8 +220,8 @@ func TestReadPropfind(t *testing.T) { " <A:prop> <A:displayname/></A:prop>\n" + "</A:propfind>", wantPF: propfind{ - XMLName: xml.Name{Space: "DAV:", Local: "propfind"}, - Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, + XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, + Prop: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}}, }, }, { desc: "propfind: propfind with ignored mixed-content", @@ -230,8 +230,8 @@ func TestReadPropfind(t *testing.T) { " <A:prop>foo<A:displayname/>bar</A:prop>\n" + "</A:propfind>", wantPF: propfind{ - XMLName: xml.Name{Space: "DAV:", Local: "propfind"}, - Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, + XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, + Prop: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}}, }, }, { desc: "propfind: propname with ignored element (section A.4)", @@ -241,7 +241,7 @@ func TestReadPropfind(t *testing.T) { " <E:leave-out xmlns:E='E:'>*boss*</E:leave-out>\n" + "</A:propfind>", wantPF: propfind{ - XMLName: xml.Name{Space: "DAV:", Local: "propfind"}, + XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, Propname: new(struct{}), }, }, { @@ -364,7 +364,7 @@ func TestMultistatusWriter(t *testing.T) { Href: []string{"http://example.com/foo"}, Propstat: []propstat{{ Prop: []Property{{ - XMLName: xml.Name{ + XMLName: ixml.Name{ Space: "http://ns.example.com/", Local: "Authors", }, @@ -372,7 +372,7 @@ func TestMultistatusWriter(t *testing.T) { Status: "HTTP/1.1 424 Failed Dependency", }, { Prop: []Property{{ - XMLName: xml.Name{ + XMLName: ixml.Name{ Space: "http://ns.example.com/", Local: "Copyright-Owner", }, @@ -427,13 +427,13 @@ func TestMultistatusWriter(t *testing.T) { Href: []string{"http://example.com/foo"}, Propstat: []propstat{{ Prop: []Property{{ - XMLName: xml.Name{Space: "http://ns.example.com/boxschema/", Local: "bigbox"}, + XMLName: ixml.Name{Space: "http://ns.example.com/boxschema/", Local: "bigbox"}, InnerXML: []byte(`` + `<BoxType xmlns="http://ns.example.com/boxschema/">` + `Box type A` + `</BoxType>`), }, { - XMLName: xml.Name{Space: "http://ns.example.com/boxschema/", Local: "author"}, + XMLName: ixml.Name{Space: "http://ns.example.com/boxschema/", Local: "author"}, InnerXML: []byte(`` + `<Name xmlns="http://ns.example.com/boxschema/">` + `J.J. Johnson` + @@ -442,9 +442,9 @@ func TestMultistatusWriter(t *testing.T) { Status: "HTTP/1.1 200 OK", }, { Prop: []Property{{ - XMLName: xml.Name{Space: "http://ns.example.com/boxschema/", Local: "DingALing"}, + XMLName: ixml.Name{Space: "http://ns.example.com/boxschema/", Local: "DingALing"}, }, { - XMLName: xml.Name{Space: "http://ns.example.com/boxschema/", Local: "Random"}, + XMLName: ixml.Name{Space: "http://ns.example.com/boxschema/", Local: "Random"}, }}, Status: "HTTP/1.1 403 Forbidden", ResponseDescription: "The user does not have access to the DingALing property.", @@ -494,7 +494,7 @@ func TestMultistatusWriter(t *testing.T) { responses: []response{{ Propstat: []propstat{{ Prop: []Property{{ - XMLName: xml.Name{ + XMLName: ixml.Name{ Space: "http://example.com/", Local: "foo", }, @@ -527,7 +527,7 @@ func TestMultistatusWriter(t *testing.T) { Href: []string{"http://example.com/foo"}, Propstat: []propstat{{ Prop: []Property{{ - XMLName: xml.Name{ + XMLName: ixml.Name{ Space: "http://example.com/", Local: "foo", }, @@ -548,7 +548,7 @@ func TestMultistatusWriter(t *testing.T) { }, Propstat: []propstat{{ Prop: []Property{{ - XMLName: xml.Name{ + XMLName: ixml.Name{ Space: "http://example.com/", Local: "foo", }, @@ -638,14 +638,14 @@ func TestReadProppatch(t *testing.T) { `</D:propertyupdate>`, wantPP: []Proppatch{{ Props: []Property{{ - xml.Name{Space: "http://ns.example.com/z/", Local: "Authors"}, + ixml.Name{Space: "http://ns.example.com/z/", Local: "Authors"}, "", []byte(`somevalue`), }}, }, { Remove: true, Props: []Property{{ - xml.Name{Space: "http://ns.example.com/z/", Local: "Copyright-Owner"}, + ixml.Name{Space: "http://ns.example.com/z/", Local: "Copyright-Owner"}, "", nil, }}, @@ -663,7 +663,7 @@ func TestReadProppatch(t *testing.T) { `</D:propertyupdate>`, wantPP: []Proppatch{{ Props: []Property{{ - xml.Name{Space: "http://example.com/ns", Local: "foo"}, + ixml.Name{Space: "http://example.com/ns", Local: "foo"}, "en", nil, }}, @@ -798,7 +798,7 @@ func TestUnmarshalXMLValue(t *testing.T) { var n xmlNormalizer for _, tc := range testCases { - d := xml.NewDecoder(strings.NewReader(tc.input)) + d := ixml.NewDecoder(strings.NewReader(tc.input)) var v xmlValue if err := d.Decode(&v); err != nil { t.Errorf("%s: got error %v, want nil", tc.desc, err) @@ -836,8 +836,8 @@ type xmlNormalizer struct { // * Remove comments, if instructed to do so. // func (n *xmlNormalizer) normalize(w io.Writer, r io.Reader) error { - d := xml.NewDecoder(r) - e := xml.NewEncoder(w) + d := ixml.NewDecoder(r) + e := ixml.NewEncoder(w) for { t, err := d.Token() if err != nil { @@ -847,18 +847,18 @@ func (n *xmlNormalizer) normalize(w io.Writer, r io.Reader) error { return err } switch val := t.(type) { - case xml.Directive, xml.ProcInst: + case ixml.Directive, ixml.ProcInst: continue - case xml.Comment: + case ixml.Comment: if n.omitComments { continue } - case xml.CharData: + case ixml.CharData: if n.omitWhitespace && len(bytes.TrimSpace(val)) == 0 { continue } - case xml.StartElement: - start, _ := xml.CopyToken(val).(xml.StartElement) + case ixml.StartElement: + start, _ := ixml.CopyToken(val).(ixml.StartElement) attr := start.Attr[:0] for _, a := range start.Attr { if a.Name.Space == "xmlns" || a.Name.Local == "xmlns" { @@ -893,7 +893,7 @@ func (n *xmlNormalizer) equalXML(a, b io.Reader) (bool, error) { return normA == normB, nil } -type byName []xml.Attr +type byName []ixml.Attr func (a byName) Len() int { return len(a) } func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }