feat: download shared subdirectory (#1184)

Co-authored-by: Oleg Lobanov <oleg@lobanov.me>
This commit is contained in:
WeidiDeng 2020-12-29 00:35:29 +08:00 committed by GitHub
parent 677bce376b
commit fb5b28d9cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 240 additions and 88 deletions

View file

@ -2,19 +2,21 @@ package http
import (
"net/http"
"path"
"path/filepath"
"strings"
"github.com/spf13/afero"
"github.com/filebrowser/filebrowser/v2/files"
)
var withHashFile = func(fn handleFunc) handleFunc {
return func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
link, err := d.store.Share.GetByHash(r.URL.Path)
id, path := ifPathWithName(r)
link, err := d.store.Share.GetByHash(id)
if err != nil {
link, err = d.store.Share.GetByHash(ifPathWithName(r))
if err != nil {
return errToStatus(err), err
}
return errToStatus(err), err
}
user, err := d.store.Users.Get(d.server.Root, link.UserID)
@ -35,6 +37,22 @@ var withHashFile = func(fn handleFunc) handleFunc {
return errToStatus(err), err
}
if file.IsDir {
// set fs root to the shared folder
d.user.Fs = afero.NewBasePathFs(d.user.Fs, filepath.Dir(link.Path))
file, err = files.NewFileInfo(files.FileOptions{
Fs: d.user.Fs,
Path: path,
Modify: d.user.Perm.Modify,
Expand: true,
Checker: d,
})
if err != nil {
return errToStatus(err), err
}
}
d.raw = file
return fn(w, r, d)
}
@ -42,15 +60,17 @@ var withHashFile = func(fn handleFunc) handleFunc {
// ref to https://github.com/filebrowser/filebrowser/pull/727
// `/api/public/dl/MEEuZK-v/file-name.txt` for old browsers to save file with correct name
func ifPathWithName(r *http.Request) string {
func ifPathWithName(r *http.Request) (id, filePath string) {
pathElements := strings.Split(r.URL.Path, "/")
// prevent maliciously constructed parameters like `/api/public/dl/XZzCDnK2_not_exists_hash_name`
// len(pathElements) will be 1, and golang will panic `runtime error: index out of range`
if len(pathElements) < 2 { //nolint: mnd
return r.URL.Path
switch len(pathElements) {
case 1:
return r.URL.Path, "/"
default:
return pathElements[0], path.Join("/", path.Join(pathElements[1:]...))
}
id := pathElements[len(pathElements)-2]
return id
}
var publicShareHandler = withHashFile(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {