소스 검색

webdav: fix props for directory

Fixes golang/go#13126

- GET/HEAD/POST method should not allowed for directory
- Ignore EOFs while detecting the file.

Change-Id: I5ce345408a5ea4ec0dc993631122e6c79fc64398
Reviewed-on: https://go-review.googlesource.com/16799
Reviewed-by: Robert Stepanek <robert.stepanek@gmail.com>
Reviewed-by: Nigel Tao <nigeltao@golang.org>
Yasuhiro Matsumoto 10 년 전
부모
커밋
d75b190240
3개의 변경된 파일24개의 추가작업 그리고 31개의 파일을 삭제
  1. 16 12
      webdav/prop.go
  2. 0 12
      webdav/prop_test.go
  3. 8 7
      webdav/webdav.go

+ 16 - 12
webdav/prop.go

@@ -115,23 +115,23 @@ var liveProps = map[xml.Name]struct {
 	},
 	xml.Name{Space: "DAV:", Local: "getcontentlength"}: {
 		findFn: findContentLength,
-		dir:    true,
+		dir:    false,
 	},
 	xml.Name{Space: "DAV:", Local: "getlastmodified"}: {
 		findFn: findLastModified,
-		dir:    true,
+		dir:    false,
 	},
 	xml.Name{Space: "DAV:", Local: "creationdate"}: {
 		findFn: nil,
-		dir:    true,
+		dir:    false,
 	},
 	xml.Name{Space: "DAV:", Local: "getcontentlanguage"}: {
 		findFn: nil,
-		dir:    true,
+		dir:    false,
 	},
 	xml.Name{Space: "DAV:", Local: "getcontenttype"}: {
 		findFn: findContentType,
-		dir:    true,
+		dir:    false,
 	},
 	xml.Name{Space: "DAV:", Local: "getetag"}: {
 		findFn: findETag,
@@ -358,14 +358,18 @@ func findContentType(fs FileSystem, ls LockSystem, name string, fi os.FileInfo)
 	defer f.Close()
 	// This implementation is based on serveContent's code in the standard net/http package.
 	ctype := mime.TypeByExtension(filepath.Ext(name))
-	if ctype == "" {
-		// Read a chunk to decide between utf-8 text and binary.
-		var buf [512]byte
-		n, _ := io.ReadFull(f, buf[:])
-		ctype = http.DetectContentType(buf[:n])
-		// Rewind file.
-		_, err = f.Seek(0, os.SEEK_SET)
+	if ctype != "" {
+		return ctype, nil
+	}
+	// Read a chunk to decide between utf-8 text and binary.
+	var buf [512]byte
+	n, err := io.ReadFull(f, buf[:])
+	if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF {
+		return "", err
 	}
+	ctype = http.DetectContentType(buf[:n])
+	// Rewind file.
+	_, err = f.Seek(0, os.SEEK_SET)
 	return ctype, err
 }
 

+ 0 - 12
webdav/prop_test.go

@@ -77,9 +77,6 @@ func TestMemPS(t *testing.T) {
 			wantPnames: []xml.Name{
 				xml.Name{Space: "DAV:", Local: "resourcetype"},
 				xml.Name{Space: "DAV:", Local: "displayname"},
-				xml.Name{Space: "DAV:", Local: "getcontentlength"},
-				xml.Name{Space: "DAV:", Local: "getlastmodified"},
-				xml.Name{Space: "DAV:", Local: "getcontenttype"},
 				xml.Name{Space: "DAV:", Local: "supportedlock"},
 			},
 		}, {
@@ -109,15 +106,6 @@ func TestMemPS(t *testing.T) {
 				}, {
 					XMLName:  xml.Name{Space: "DAV:", Local: "displayname"},
 					InnerXML: []byte("dir"),
-				}, {
-					XMLName:  xml.Name{Space: "DAV:", Local: "getcontentlength"},
-					InnerXML: []byte("0"),
-				}, {
-					XMLName:  xml.Name{Space: "DAV:", Local: "getlastmodified"},
-					InnerXML: nil, // Calculated during test.
-				}, {
-					XMLName:  xml.Name{Space: "DAV:", Local: "getcontenttype"},
-					InnerXML: []byte("text/plain; charset=utf-8"),
 				}, {
 					XMLName:  xml.Name{Space: "DAV:", Local: "supportedlock"},
 					InnerXML: []byte(lockEntry),

+ 8 - 7
webdav/webdav.go

@@ -195,7 +195,7 @@ func (h *Handler) handleOptions(w http.ResponseWriter, r *http.Request) (status
 	allow := "OPTIONS, LOCK, PUT, MKCOL"
 	if fi, err := h.FileSystem.Stat(reqPath); err == nil {
 		if fi.IsDir() {
-			allow = "OPTIONS, LOCK, GET, HEAD, POST, DELETE, PROPPATCH, COPY, MOVE, UNLOCK, PROPFIND"
+			allow = "OPTIONS, LOCK, DELETE, PROPPATCH, COPY, MOVE, UNLOCK, PROPFIND"
 		} else {
 			allow = "OPTIONS, LOCK, GET, HEAD, POST, DELETE, PROPPATCH, COPY, MOVE, UNLOCK, PROPFIND, PUT"
 		}
@@ -223,13 +223,14 @@ func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request) (sta
 	if err != nil {
 		return http.StatusNotFound, err
 	}
-	if !fi.IsDir() {
-		etag, err := findETag(h.FileSystem, h.LockSystem, reqPath, fi)
-		if err != nil {
-			return http.StatusInternalServerError, err
-		}
-		w.Header().Set("ETag", etag)
+	if fi.IsDir() {
+		return http.StatusMethodNotAllowed, nil
+	}
+	etag, err := findETag(h.FileSystem, h.LockSystem, reqPath, fi)
+	if err != nil {
+		return http.StatusInternalServerError, err
 	}
+	w.Header().Set("ETag", etag)
 	// Let ServeContent determine the Content-Type header.
 	http.ServeContent(w, r, reqPath, fi.ModTime(), f)
 	return 0, nil