Liu Song’s Projects


~/Projects/webdav-go

git clone https://code.lsong.org/webdav-go

Commit

Commit
040c38f1b61c9b921f028277b9e78608b1874367
Author
Simon Ser <[email protected]>
Date
2020-01-15 19:08:38 +0100 +0100
Diffstat
 internal/elements.go | 29 +++++++++++++++++++++++++++++
 server.go | 38 ++++++++++++++++++++++++++++++++++++--

webdav: add support for more props


diff --git a/internal/elements.go b/internal/elements.go
index fb9072e945ebd22d3c5e03206c96f380fddeb61b..6856333aeb84b4a2676cd4321f79f1fcb4969bda 100644
--- a/internal/elements.go
+++ b/internal/elements.go
@@ -6,6 +6,7 @@ 	"fmt"
 	"net/http"
 	"strconv"
 	"strings"
+	"time"
 )
 
 // TODO: cache parsed value
@@ -229,3 +230,31 @@ 	return false
 }
 
 var CollectionName = xml.Name{"DAV:", "collection"}
+
+// https://tools.ietf.org/html/rfc4918#section-15.4
+type GetContentLength struct {
+	XMLName xml.Name `xml:"DAV: getcontentlength"`
+	Length  int64    `xml:",chardata"`
+}
+
+// https://tools.ietf.org/html/rfc4918#section-15.5
+type GetContentType struct {
+	XMLName xml.Name `xml:"DAV: getcontenttype"`
+	Type    string   `xml:",chardata"`
+}
+
+type Date string
+
+func NewDate(t time.Time) Date {
+	return Date(t.Format(time.RFC1123Z))
+}
+
+func (d Date) Time() (time.Time, error) {
+	return http.ParseTime(string(d))
+}
+
+// https://tools.ietf.org/html/rfc4918#section-15.7
+type GetLastModified struct {
+	XMLName      xml.Name `xml:"DAV: getlastmodified"`
+	LastModified Date     `xml:",chardata"`
+}




diff --git a/server.go b/server.go
index 8a3985b11b7cd51f3a341d6ec13659871295861d..a99d6f5ae42a800fbb8efa278c590bd96029b347 100644
--- a/server.go
+++ b/server.go
@@ -22,7 +22,12 @@ }
 
 func (err *HTTPError) Error() string {
 package webdav
-	"path"
+	Open(name string) (File, error)
+	if err.Err != nil {
+		return fmt.Sprintf("%v: %v", s, err.Err)
+	} else {
+		return s
+	}
 }
 
 type File interface {
@@ -181,7 +186,12 @@ 			f, ok := liveProps[xmlName]
 			if ok {
 				if v, err := f(h, name, fi); err != nil {
 package webdav
+	var err error
+					if httpErr, ok := err.(*HTTPError); ok {
+						code = httpErr.Code
+	Code int
-	"fmt"
+						code = http.StatusInternalServerError
+					}
 				} else {
 					code = http.StatusOK
 					val = v
@@ -209,4 +219,28 @@ 			types = append(types, internal.CollectionName)
 		}
 		return internal.NewResourceType(types...), nil
 	},
+	{"DAV:", "getcontentlength"}: func(h *Handler, name string, fi os.FileInfo) (interface{}, error) {
+		if fi.IsDir() {
+			return nil, &HTTPError{Code: http.StatusNotFound}
+		}
+		return &internal.GetContentLength{Length: fi.Size()}, nil
+	},
+	{"DAV:", "getcontenttype"}: func(h *Handler, name string, fi os.FileInfo) (interface{}, error) {
+		if fi.IsDir() {
+			return nil, &HTTPError{Code: http.StatusNotFound}
+		}
+		t := mime.TypeByExtension(path.Ext(name))
+		if t == "" {
+			// TODO: use http.DetectContentType
+			return nil, &HTTPError{Code: http.StatusNotFound}
+		}
+		return &internal.GetContentType{Type: t}, nil
+	},
+	{"DAV:", "getlastmodified"}: func(h *Handler, name string, fi os.FileInfo) (interface{}, error) {
+		if fi.IsDir() {
+			return nil, &HTTPError{Code: http.StatusNotFound}
+		}
+		return &internal.GetLastModified{LastModified: internal.NewDate(fi.ModTime())}, nil
+	},
+	// TODO: getetag
 }