webdav: have the exported API use the standard library's xml.Name type.
In particular, the Property and DeadPropsHolder types need to refer to
the standard xml package, not the internal fork, to be usable by other
packages.
Inside the package, the XML marshaling and unmarshaling is still done by
the etc/internal/xml package, and will remain that way until
https://github.com/golang/go/issues/13400 is resolved.
Fixes golang/go#15128.
Change-Id: Ie7e7927d8b30d97d10b1a4a654d774fdf3e7a1e3
Reviewed-on: https://go-review.googlesource.com/21635
Reviewed-by: Andrew Gerrand <adg@golang.org>
diff --git a/webdav/file.go b/webdav/file.go
index 9ba1ca1..3d95c6c 100644
--- a/webdav/file.go
+++ b/webdav/file.go
@@ -5,6 +5,7 @@
package webdav
import (
+ "encoding/xml"
"io"
"net/http"
"os"
@@ -13,8 +14,6 @@
"strings"
"sync"
"time"
-
- "golang.org/x/net/webdav/internal/xml"
)
// slashClean is equivalent to but slightly more efficient than
diff --git a/webdav/file_test.go b/webdav/file_test.go
index 99547e1..7ce6c12 100644
--- a/webdav/file_test.go
+++ b/webdav/file_test.go
@@ -5,6 +5,7 @@
package webdav
import (
+ "encoding/xml"
"fmt"
"io"
"io/ioutil"
@@ -17,8 +18,6 @@
"strconv"
"strings"
"testing"
-
- "golang.org/x/net/webdav/internal/xml"
)
func TestSlashClean(t *testing.T) {
diff --git a/webdav/prop.go b/webdav/prop.go
index 88b9a3a..ac6c65a 100644
--- a/webdav/prop.go
+++ b/webdav/prop.go
@@ -5,6 +5,7 @@
package webdav
import (
+ "encoding/xml"
"fmt"
"io"
"mime"
@@ -12,8 +13,6 @@
"os"
"path/filepath"
"strconv"
-
- "golang.org/x/net/webdav/internal/xml"
)
// Proppatch describes a property update instruction as defined in RFC 4918.
diff --git a/webdav/prop_test.go b/webdav/prop_test.go
index c55a7ba..ee188ac 100644
--- a/webdav/prop_test.go
+++ b/webdav/prop_test.go
@@ -5,14 +5,13 @@
package webdav
import (
+ "encoding/xml"
"fmt"
"net/http"
"os"
"reflect"
"sort"
"testing"
-
- "golang.org/x/net/webdav/internal/xml"
)
func TestMemPS(t *testing.T) {
diff --git a/webdav/xml.go b/webdav/xml.go
index 7fb1147..790dc81 100644
--- a/webdav/xml.go
+++ b/webdav/xml.go
@@ -9,11 +9,29 @@
import (
"bytes"
+ "encoding/xml"
"fmt"
"io"
"net/http"
"time"
+ // As of https://go-review.googlesource.com/#/c/12772/ which was submitted
+ // in July 2015, this package uses an internal fork of the standard
+ // library's encoding/xml package, due to changes in the way namespaces
+ // were encoded. Such changes were introduced in the Go 1.5 cycle, but were
+ // rolled back in response to https://github.com/golang/go/issues/11841
+ //
+ // However, this package's exported API, specifically the Property and
+ // DeadPropsHolder types, need to refer to the standard library's version
+ // of the xml.Name type, as code that imports this package cannot refer to
+ // the internal version.
+ //
+ // This file therefore imports both the internal and external versions, as
+ // ixml and xml, and converts between them.
+ //
+ // In the long term, this package should use the standard library's version
+ // only, and the internal fork deleted, once
+ // https://github.com/golang/go/issues/13400 is resolved.
ixml "golang.org/x/net/webdav/internal/xml"
)
@@ -116,7 +134,7 @@
}
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for propfind)
-type propfindProps []ixml.Name
+type propfindProps []xml.Name
// UnmarshalXML appends the property names enclosed within start to pn.
//
@@ -143,7 +161,7 @@
if _, ok := t.(ixml.EndElement); !ok {
return fmt.Errorf("unexpected token %T", t)
}
- *pn = append(*pn, name)
+ *pn = append(*pn, xml.Name(name))
}
}
}
@@ -190,7 +208,7 @@
// 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 ixml.Name
+ XMLName xml.Name
// Lang is an optional xml:lang attribute.
Lang string `xml:"xml:lang,attr,omitempty"`
@@ -206,6 +224,14 @@
InnerXML []byte `xml:",innerxml"`
}
+// ixmlProperty is the same as the Property type except it holds an ixml.Name
+// instead of an xml.Name.
+type ixmlProperty struct {
+ XMLName ixml.Name
+ Lang string `xml:"xml:lang,attr,omitempty"`
+ InnerXML []byte `xml:",innerxml"`
+}
+
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_error
// See multistatusWriter for the "D:" namespace prefix.
type xmlError struct {
@@ -222,18 +248,42 @@
ResponseDescription string `xml:"D:responsedescription,omitempty"`
}
+// ixmlPropstat is the same as the propstat type except it holds an ixml.Name
+// instead of an xml.Name.
+type ixmlPropstat struct {
+ Prop []ixmlProperty `xml:"D:prop>_ignored_"`
+ Status string `xml:"D:status"`
+ Error *xmlError `xml:"D:error"`
+ ResponseDescription string `xml:"D:responsedescription,omitempty"`
+}
+
// MarshalXML prepends the "D:" namespace prefix on properties in the DAV: namespace
// before encoding. See multistatusWriter.
func (ps propstat) MarshalXML(e *ixml.Encoder, start ixml.StartElement) error {
+ // Convert from a propstat to an ixmlPropstat.
+ ixmlPs := ixmlPropstat{
+ Prop: make([]ixmlProperty, len(ps.Prop)),
+ Status: ps.Status,
+ Error: ps.Error,
+ ResponseDescription: ps.ResponseDescription,
+ }
for k, prop := range ps.Prop {
+ ixmlPs.Prop[k] = ixmlProperty{
+ XMLName: ixml.Name(prop.XMLName),
+ Lang: prop.Lang,
+ InnerXML: prop.InnerXML,
+ }
+ }
+
+ for k, prop := range ixmlPs.Prop {
if prop.XMLName.Space == "DAV:" {
prop.XMLName = ixml.Name{Space: "", Local: "D:" + prop.XMLName.Local}
- ps.Prop[k] = prop
+ ixmlPs.Prop[k] = prop
}
}
// Distinct type to avoid infinite recursion of MarshalXML.
- type newpropstat propstat
- return e.EncodeElement(newpropstat(ps), start)
+ type newpropstat ixmlPropstat
+ return e.EncodeElement(newpropstat(ixmlPs), start)
}
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_response
@@ -350,9 +400,6 @@
return w.enc.Flush()
}
-// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for proppatch)
-type proppatchProps []Property
-
var xmlLangName = ixml.Name{Space: "http://www.w3.org/XML/1998/namespace", Local: "lang"}
func xmlLang(s ixml.StartElement, d string) string {
@@ -393,6 +440,9 @@
return nil
}
+// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for proppatch)
+type proppatchProps []Property
+
// UnmarshalXML appends the property names and values enclosed within start
// to ps.
//
@@ -416,7 +466,7 @@
return nil
case ixml.StartElement:
p := Property{
- XMLName: t.(ixml.StartElement).Name,
+ XMLName: xml.Name(t.(ixml.StartElement).Name),
Lang: xmlLang(t.(ixml.StartElement), lang),
}
err = d.DecodeElement(((*xmlValue)(&p.InnerXML)), &elem)
diff --git a/webdav/xml_test.go b/webdav/xml_test.go
index 7cd14b6..a3d9e1e 100644
--- a/webdav/xml_test.go
+++ b/webdav/xml_test.go
@@ -6,6 +6,7 @@
import (
"bytes"
+ "encoding/xml"
"fmt"
"io"
"net/http"
@@ -176,7 +177,7 @@
wantPF: propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
Allprop: new(struct{}),
- Include: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}},
+ Include: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
},
}, {
desc: "propfind: include followed by allprop",
@@ -188,7 +189,7 @@
wantPF: propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
Allprop: new(struct{}),
- Include: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}},
+ Include: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
},
}, {
desc: "propfind: propfind",
@@ -198,7 +199,7 @@
"</A:propfind>",
wantPF: propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
- Prop: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}},
+ Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
},
}, {
desc: "propfind: prop with ignored comments",
@@ -211,7 +212,7 @@
"</A:propfind>",
wantPF: propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
- Prop: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}},
+ Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
},
}, {
desc: "propfind: propfind with ignored whitespace",
@@ -221,7 +222,7 @@
"</A:propfind>",
wantPF: propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
- Prop: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}},
+ Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
},
}, {
desc: "propfind: propfind with ignored mixed-content",
@@ -231,7 +232,7 @@
"</A:propfind>",
wantPF: propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
- Prop: propfindProps{ixml.Name{Space: "DAV:", Local: "displayname"}},
+ Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
},
}, {
desc: "propfind: propname with ignored element (section A.4)",
@@ -364,7 +365,7 @@
Href: []string{"http://example.com/foo"},
Propstat: []propstat{{
Prop: []Property{{
- XMLName: ixml.Name{
+ XMLName: xml.Name{
Space: "http://ns.example.com/",
Local: "Authors",
},
@@ -372,7 +373,7 @@
Status: "HTTP/1.1 424 Failed Dependency",
}, {
Prop: []Property{{
- XMLName: ixml.Name{
+ XMLName: xml.Name{
Space: "http://ns.example.com/",
Local: "Copyright-Owner",
},
@@ -427,13 +428,13 @@
Href: []string{"http://example.com/foo"},
Propstat: []propstat{{
Prop: []Property{{
- XMLName: ixml.Name{Space: "http://ns.example.com/boxschema/", Local: "bigbox"},
+ XMLName: xml.Name{Space: "http://ns.example.com/boxschema/", Local: "bigbox"},
InnerXML: []byte(`` +
`<BoxType xmlns="http://ns.example.com/boxschema/">` +
`Box type A` +
`</BoxType>`),
}, {
- XMLName: ixml.Name{Space: "http://ns.example.com/boxschema/", Local: "author"},
+ XMLName: xml.Name{Space: "http://ns.example.com/boxschema/", Local: "author"},
InnerXML: []byte(`` +
`<Name xmlns="http://ns.example.com/boxschema/">` +
`J.J. Johnson` +
@@ -442,9 +443,9 @@
Status: "HTTP/1.1 200 OK",
}, {
Prop: []Property{{
- XMLName: ixml.Name{Space: "http://ns.example.com/boxschema/", Local: "DingALing"},
+ XMLName: xml.Name{Space: "http://ns.example.com/boxschema/", Local: "DingALing"},
}, {
- XMLName: ixml.Name{Space: "http://ns.example.com/boxschema/", Local: "Random"},
+ XMLName: xml.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 +495,7 @@
responses: []response{{
Propstat: []propstat{{
Prop: []Property{{
- XMLName: ixml.Name{
+ XMLName: xml.Name{
Space: "http://example.com/",
Local: "foo",
},
@@ -527,7 +528,7 @@
Href: []string{"http://example.com/foo"},
Propstat: []propstat{{
Prop: []Property{{
- XMLName: ixml.Name{
+ XMLName: xml.Name{
Space: "http://example.com/",
Local: "foo",
},
@@ -548,7 +549,7 @@
},
Propstat: []propstat{{
Prop: []Property{{
- XMLName: ixml.Name{
+ XMLName: xml.Name{
Space: "http://example.com/",
Local: "foo",
},
@@ -638,14 +639,14 @@
`</D:propertyupdate>`,
wantPP: []Proppatch{{
Props: []Property{{
- ixml.Name{Space: "http://ns.example.com/z/", Local: "Authors"},
+ xml.Name{Space: "http://ns.example.com/z/", Local: "Authors"},
"",
[]byte(`somevalue`),
}},
}, {
Remove: true,
Props: []Property{{
- ixml.Name{Space: "http://ns.example.com/z/", Local: "Copyright-Owner"},
+ xml.Name{Space: "http://ns.example.com/z/", Local: "Copyright-Owner"},
"",
nil,
}},
@@ -663,7 +664,7 @@
`</D:propertyupdate>`,
wantPP: []Proppatch{{
Props: []Property{{
- ixml.Name{Space: "http://example.com/ns", Local: "foo"},
+ xml.Name{Space: "http://example.com/ns", Local: "foo"},
"en",
nil,
}},