mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-08 15:41:15 +02:00
* webdav: name the entry, not its path, in a listing DAV:displayname carried the full path of every entry. A client that takes displayname for the child's name - Windows Explorer does - then looks for /dir/name under /dir and finds nothing, so a folder shows up empty while the root, where the two spellings differ only by a leading slash, still lists. Readdir now builds its entries with toFileInfo like stat does, so a listing and a lookup describe a child the same way, and the wrapper that was trimming the sub-folder back off a name goes away with it. Claude-Session: https://claude.ai/code/session_01XCeuCWpF9xo9CfyHvCQE9c * webdav: derive an ETag when nothing hashed the entry Uploads through this gateway carry no content MD5, so filer.ETag comes back empty and every file in a PROPFIND answered with an empty DAV:getetag, which is not a valid entity-tag. Report it as unimplemented instead, the way the sub-folder wrapper already did, and webdav falls back to modification time and size. The wrapper's copy went with it - it swallowed the stat error a caller was meant to see. Claude-Session: https://claude.ai/code/session_01XCeuCWpF9xo9CfyHvCQE9c
58 lines
1.6 KiB
Go
58 lines
1.6 KiB
Go
package weed_server
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path"
|
|
|
|
"golang.org/x/net/webdav"
|
|
)
|
|
|
|
type wrappedFs struct {
|
|
subFolder string
|
|
webdav.FileSystem
|
|
}
|
|
|
|
// confine joins a client-supplied name under subFolder. The name is cleaned as
|
|
// a rooted path first so `..` segments cannot climb above subFolder; cleaning
|
|
// after the concat (as the underlying FileSystem does) would resolve them across
|
|
// the confinement boundary.
|
|
func (w wrappedFs) confine(name string) string {
|
|
return w.subFolder + path.Clean("/"+name)
|
|
}
|
|
|
|
// NewWrappedFs returns a webdav.FileSystem identical to fs, except that it
|
|
// serves only the subFolder sub-tree of fs.
|
|
func NewWrappedFs(fs webdav.FileSystem, subFolder string) webdav.FileSystem {
|
|
return wrappedFs{
|
|
subFolder: subFolder,
|
|
FileSystem: fs,
|
|
}
|
|
}
|
|
|
|
func (w wrappedFs) Mkdir(ctx context.Context, name string, perm os.FileMode) error {
|
|
name = w.confine(name)
|
|
return w.FileSystem.Mkdir(ctx, name, perm)
|
|
}
|
|
|
|
func (w wrappedFs) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
|
|
name = w.confine(name)
|
|
return w.FileSystem.OpenFile(ctx, name, flag, perm)
|
|
}
|
|
|
|
func (w wrappedFs) RemoveAll(ctx context.Context, name string) error {
|
|
name = w.confine(name)
|
|
return w.FileSystem.RemoveAll(ctx, name)
|
|
}
|
|
|
|
func (w wrappedFs) Rename(ctx context.Context, oldName, newName string) error {
|
|
oldName = w.confine(oldName)
|
|
newName = w.confine(newName)
|
|
return w.FileSystem.Rename(ctx, oldName, newName)
|
|
}
|
|
|
|
func (w wrappedFs) Stat(ctx context.Context, name string) (os.FileInfo, error) {
|
|
name = w.confine(name)
|
|
return w.FileSystem.Stat(ctx, name)
|
|
}
|