Ready to use x's webdav components.

This commit is contained in:
zicla 2020-03-25 01:55:03 +08:00
parent 83cf140fa1
commit ff81448611
4 changed files with 32 additions and 31 deletions

View File

@ -155,6 +155,7 @@ func (this *DavService) HandlePropfind(writer http.ResponseWriter, request *http
fmt.Printf("PROPFIND %s\n", subPath) fmt.Printf("PROPFIND %s\n", subPath)
// read depth
depth := this.ParseDepth(request) depth := this.ParseDepth(request)
propfind := dav.ReadPropfind(request.Body) propfind := dav.ReadPropfind(request.Body)

View File

@ -526,7 +526,7 @@ func (h *Handler) handlePropfind(w http.ResponseWriter, r *http.Request) (status
return http.StatusBadRequest, errInvalidDepth return http.StatusBadRequest, errInvalidDepth
} }
} }
pf, status, err := readPropfind(r.Body) pf, status, err := ReadPropfind(r.Body)
if err != nil { if err != nil {
return status, err return status, err
} }

View File

@ -134,13 +134,13 @@ func next(d *ixml.Decoder) (ixml.Token, error) {
} }
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for propfind) // http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for propfind)
type propfindProps []xml.Name type PropfindProps []xml.Name
// UnmarshalXML appends the property names enclosed within start to pn. // UnmarshalXML appends the property names enclosed within start to pn.
// //
// It returns an error if start does not contain any properties or if // It returns an error if start does not contain any properties or if
// properties contain values. Character data between properties is ignored. // properties contain values. Character data between properties is ignored.
func (pn *propfindProps) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement) error { func (pn *PropfindProps) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement) error {
for { for {
t, err := next(d) t, err := next(d)
if err != nil { if err != nil {
@ -167,39 +167,39 @@ func (pn *propfindProps) UnmarshalXML(d *ixml.Decoder, start ixml.StartElement)
} }
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_propfind // http://www.webdav.org/specs/rfc4918.html#ELEMENT_propfind
type propfind struct { type Propfind struct {
XMLName ixml.Name `xml:"DAV: propfind"` XMLName ixml.Name `xml:"DAV: propfind"`
Allprop *struct{} `xml:"DAV: allprop"` Allprop *struct{} `xml:"DAV: allprop"`
Propname *struct{} `xml:"DAV: propname"` Propname *struct{} `xml:"DAV: propname"`
Prop propfindProps `xml:"DAV: prop"` Prop PropfindProps `xml:"DAV: prop"`
Include propfindProps `xml:"DAV: include"` Include PropfindProps `xml:"DAV: include"`
} }
func readPropfind(r io.Reader) (pf propfind, status int, err error) { func ReadPropfind(r io.Reader) (pf Propfind, status int, err error) {
c := countingReader{r: r} c := countingReader{r: r}
if err = ixml.NewDecoder(&c).Decode(&pf); err != nil { if err = ixml.NewDecoder(&c).Decode(&pf); err != nil {
if err == io.EOF { if err == io.EOF {
if c.n == 0 { if c.n == 0 {
// An empty body means to propfind allprop. // An empty body means to propfind allprop.
// http://www.webdav.org/specs/rfc4918.html#METHOD_PROPFIND // http://www.webdav.org/specs/rfc4918.html#METHOD_PROPFIND
return propfind{Allprop: new(struct{})}, 0, nil return Propfind{Allprop: new(struct{})}, 0, nil
} }
err = errInvalidPropfind err = errInvalidPropfind
} }
return propfind{}, http.StatusBadRequest, err return Propfind{}, http.StatusBadRequest, err
} }
if pf.Allprop == nil && pf.Include != nil { if pf.Allprop == nil && pf.Include != nil {
return propfind{}, http.StatusBadRequest, errInvalidPropfind return Propfind{}, http.StatusBadRequest, errInvalidPropfind
} }
if pf.Allprop != nil && (pf.Prop != nil || pf.Propname != nil) { if pf.Allprop != nil && (pf.Prop != nil || pf.Propname != nil) {
return propfind{}, http.StatusBadRequest, errInvalidPropfind return Propfind{}, http.StatusBadRequest, errInvalidPropfind
} }
if pf.Prop != nil && pf.Propname != nil { if pf.Prop != nil && pf.Propname != nil {
return propfind{}, http.StatusBadRequest, errInvalidPropfind return Propfind{}, http.StatusBadRequest, errInvalidPropfind
} }
if pf.Propname == nil && pf.Allprop == nil && pf.Prop == nil { if pf.Propname == nil && pf.Allprop == nil && pf.Prop == nil {
return propfind{}, http.StatusBadRequest, errInvalidPropfind return Propfind{}, http.StatusBadRequest, errInvalidPropfind
} }
return pf, 0, nil return pf, 0, nil
} }

View File

@ -139,7 +139,7 @@ func TestReadPropfind(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
input string input string
wantPF propfind wantPF Propfind
wantStatus int wantStatus int
}{{ }{{
desc: "propfind: propname", desc: "propfind: propname",
@ -147,14 +147,14 @@ func TestReadPropfind(t *testing.T) {
"<A:propfind xmlns:A='DAV:'>\n" + "<A:propfind xmlns:A='DAV:'>\n" +
" <A:propname/>\n" + " <A:propname/>\n" +
"</A:propfind>", "</A:propfind>",
wantPF: propfind{ wantPF: Propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
Propname: new(struct{}), Propname: new(struct{}),
}, },
}, { }, {
desc: "propfind: empty body means allprop", desc: "propfind: empty body means allprop",
input: "", input: "",
wantPF: propfind{ wantPF: Propfind{
Allprop: new(struct{}), Allprop: new(struct{}),
}, },
}, { }, {
@ -163,7 +163,7 @@ func TestReadPropfind(t *testing.T) {
"<A:propfind xmlns:A='DAV:'>\n" + "<A:propfind xmlns:A='DAV:'>\n" +
" <A:allprop/>\n" + " <A:allprop/>\n" +
"</A:propfind>", "</A:propfind>",
wantPF: propfind{ wantPF: Propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
Allprop: new(struct{}), Allprop: new(struct{}),
}, },
@ -174,10 +174,10 @@ func TestReadPropfind(t *testing.T) {
" <A:allprop/>\n" + " <A:allprop/>\n" +
" <A:include><A:displayname/></A:include>\n" + " <A:include><A:displayname/></A:include>\n" +
"</A:propfind>", "</A:propfind>",
wantPF: propfind{ wantPF: Propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
Allprop: new(struct{}), Allprop: new(struct{}),
Include: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, Include: PropfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
}, },
}, { }, {
desc: "propfind: include followed by allprop", desc: "propfind: include followed by allprop",
@ -186,10 +186,10 @@ func TestReadPropfind(t *testing.T) {
" <A:include><A:displayname/></A:include>\n" + " <A:include><A:displayname/></A:include>\n" +
" <A:allprop/>\n" + " <A:allprop/>\n" +
"</A:propfind>", "</A:propfind>",
wantPF: propfind{ wantPF: Propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
Allprop: new(struct{}), Allprop: new(struct{}),
Include: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, Include: PropfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
}, },
}, { }, {
desc: "propfind: propfind", desc: "propfind: propfind",
@ -197,9 +197,9 @@ func TestReadPropfind(t *testing.T) {
"<A:propfind xmlns:A='DAV:'>\n" + "<A:propfind xmlns:A='DAV:'>\n" +
" <A:prop><A:displayname/></A:prop>\n" + " <A:prop><A:displayname/></A:prop>\n" +
"</A:propfind>", "</A:propfind>",
wantPF: propfind{ wantPF: Propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, Prop: PropfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
}, },
}, { }, {
desc: "propfind: prop with ignored comments", desc: "propfind: prop with ignored comments",
@ -210,9 +210,9 @@ func TestReadPropfind(t *testing.T) {
" <A:displayname><!-- ignore --></A:displayname>\n" + " <A:displayname><!-- ignore --></A:displayname>\n" +
" </A:prop>\n" + " </A:prop>\n" +
"</A:propfind>", "</A:propfind>",
wantPF: propfind{ wantPF: Propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, Prop: PropfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
}, },
}, { }, {
desc: "propfind: propfind with ignored whitespace", desc: "propfind: propfind with ignored whitespace",
@ -220,9 +220,9 @@ func TestReadPropfind(t *testing.T) {
"<A:propfind xmlns:A='DAV:'>\n" + "<A:propfind xmlns:A='DAV:'>\n" +
" <A:prop> <A:displayname/></A:prop>\n" + " <A:prop> <A:displayname/></A:prop>\n" +
"</A:propfind>", "</A:propfind>",
wantPF: propfind{ wantPF: Propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, Prop: PropfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
}, },
}, { }, {
desc: "propfind: propfind with ignored mixed-content", desc: "propfind: propfind with ignored mixed-content",
@ -230,9 +230,9 @@ func TestReadPropfind(t *testing.T) {
"<A:propfind xmlns:A='DAV:'>\n" + "<A:propfind xmlns:A='DAV:'>\n" +
" <A:prop>foo<A:displayname/>bar</A:prop>\n" + " <A:prop>foo<A:displayname/>bar</A:prop>\n" +
"</A:propfind>", "</A:propfind>",
wantPF: propfind{ wantPF: Propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
Prop: propfindProps{xml.Name{Space: "DAV:", Local: "displayname"}}, Prop: PropfindProps{xml.Name{Space: "DAV:", Local: "displayname"}},
}, },
}, { }, {
desc: "propfind: propname with ignored element (section A.4)", desc: "propfind: propname with ignored element (section A.4)",
@ -241,7 +241,7 @@ func TestReadPropfind(t *testing.T) {
" <A:propname/>\n" + " <A:propname/>\n" +
" <E:leave-out xmlns:E='E:'>*boss*</E:leave-out>\n" + " <E:leave-out xmlns:E='E:'>*boss*</E:leave-out>\n" +
"</A:propfind>", "</A:propfind>",
wantPF: propfind{ wantPF: Propfind{
XMLName: ixml.Name{Space: "DAV:", Local: "propfind"}, XMLName: ixml.Name{Space: "DAV:", Local: "propfind"},
Propname: new(struct{}), Propname: new(struct{}),
}, },
@ -330,7 +330,7 @@ func TestReadPropfind(t *testing.T) {
}} }}
for _, tc := range testCases { for _, tc := range testCases {
pf, status, err := readPropfind(strings.NewReader(tc.input)) pf, status, err := ReadPropfind(strings.NewReader(tc.input))
if tc.wantStatus != 0 { if tc.wantStatus != 0 {
if err == nil { if err == nil {
t.Errorf("%s: got nil error, want non-nil", tc.desc) t.Errorf("%s: got nil error, want non-nil", tc.desc)