From 17f9ed2cbd511ab7f99ac28601d1d9ee2d6a0d4f Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Sat, 3 Aug 2019 18:51:26 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Use=20a=20dedicated=20path=20for=20?= =?UTF-8?q?the=20shares?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- filesystem.go | 17 ++++++++++++++--- main.go | 15 +++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/filesystem.go b/filesystem.go index 4ffdbaf..eec90eb 100644 --- a/filesystem.go +++ b/filesystem.go @@ -42,6 +42,11 @@ import ( "strings" ) +type DirectoryMapping struct { + VirtualName string + RealName string +} + // slashClean is equivalent to but slightly more efficient than // path.Clean("/" + name). func slashClean(name string) string { @@ -54,18 +59,24 @@ func slashClean(name string) string { type BaseDir string func (d BaseDir) resolve(ctx context.Context, name string) string { - subDir := ctx.Value("dir").(string) + directoryMapping := ctx.Value("mapping").(*DirectoryMapping) + prefix := directoryMapping.VirtualName + "/" + if !strings.HasPrefix(name, prefix) { + // something does not add up + return "" + } + nameWithoutPrefix := strings.TrimPrefix(name, prefix) // This implementation is based on Dir.Open's code in the standard net/http package. if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 || - strings.Contains(name, "\x00") { + strings.Contains(nameWithoutPrefix, "\x00") { return "" } dir := string(d) if dir == "" { dir = "." } - return filepath.Join(dir, subDir, filepath.FromSlash(slashClean(name))) + return filepath.Join(dir, directoryMapping.RealName, filepath.FromSlash(slashClean(nameWithoutPrefix))) } func (d BaseDir) Mkdir(ctx context.Context, name string, perm os.FileMode) error { diff --git a/main.go b/main.go index 37718b2..a8768b1 100644 --- a/main.go +++ b/main.go @@ -29,6 +29,7 @@ import ( "context" "flag" "fmt" + "github.com/go-chi/chi" pwgen "github.com/sethvargo/go-password/password" "golang.org/x/crypto/bcrypt" "golang.org/x/net/webdav" @@ -73,6 +74,7 @@ func main() { c := LoadConfig(*configFile) h := &webdav.Handler{} + h.Prefix = "/share/" h.LockSystem = webdav.NewMemLS() h.FileSystem = BaseDir(c.BaseDirectory) @@ -88,11 +90,20 @@ func main() { return } + shareName := chi.URLParam(r, "share") + directoryMapping := DirectoryMapping{ + VirtualName: shareName, + RealName: directory, + } + // Use the WebDAV handler to actually serve the request. Also enhance the context // to contain the subdirectory (of the base directory) which contains the data for // the authenticated user. - h.ServeHTTP(w, r.WithContext(context.WithValue(r.Context(), "dir", directory))) + h.ServeHTTP(w, r.WithContext(context.WithValue(r.Context(), "mapping", &directoryMapping))) }) - http.ListenAndServe(c.ListenAddress, authenticatedWebdavHandler) + r := chi.NewRouter() + r.Handle("/share/{share}/*", authenticatedWebdavHandler) + + http.ListenAndServe(c.ListenAddress, r) }