Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webdav: ignore path and perm errors in PROPFIND #91

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions webdav/webdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"net/url"
"os"
"path"
"path/filepath"
"strings"
"time"
)
Expand Down Expand Up @@ -535,13 +536,14 @@ func (h *Handler) handlePropfind(w http.ResponseWriter, r *http.Request) (status

walkFn := func(reqPath string, info os.FileInfo, err error) error {
if err != nil {
return err
return handlePropfindError(err, info)
}

var pstats []Propstat
if pf.Propname != nil {
pnames, err := propnames(ctx, h.FileSystem, h.LockSystem, reqPath)
if err != nil {
return err
return handlePropfindError(err, info)
}
pstat := Propstat{Status: http.StatusOK}
for _, xmlname := range pnames {
Expand All @@ -554,7 +556,7 @@ func (h *Handler) handlePropfind(w http.ResponseWriter, r *http.Request) (status
pstats, err = props(ctx, h.FileSystem, h.LockSystem, reqPath, pf.Prop)
}
if err != nil {
return err
return handlePropfindError(err, info)
}
href := path.Join(h.Prefix, reqPath)
if href != "/" && info.IsDir() {
Expand Down Expand Up @@ -633,6 +635,33 @@ func makePropstatResponse(href string, pstats []Propstat) *response {
return &resp
}

func handlePropfindError(err error, info os.FileInfo) error {
var skipResp error = nil
if info != nil && info.IsDir() {
skipResp = filepath.SkipDir
}

if errors.Is(err, os.ErrPermission) {
// If the server cannot recurse into a directory because it is not allowed,
// then there is nothing more to say about it. Just skip sending anything.
return skipResp
}

if _, ok := err.(*os.PathError); ok {
// If the file is just bad, it couldn't be a proper WebDAV resource. Skip it.
return skipResp
}

// We need to be careful with other errors: there is no way to abort the xml stream
// part way through while returning a valid PROPFIND response. Returning only half
// the data would be misleading, but so would be returning results tainted by errors.
// The curent behaviour by returning an error here leads to the stream being aborted,
// and the parent http server complaining about writing a spurious header. We should
// consider further enhancing this error handling to more gracefully fail, or perhaps
// buffer the entire response until we've walked the tree.
return err
}

const (
infiniteDepth = -1
invalidDepth = -2
Expand Down