2019-01-05 22:44:33 +00:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
2020-12-28 16:35:29 +00:00
|
|
|
"path"
|
|
|
|
"path/filepath"
|
2019-05-13 14:30:18 +00:00
|
|
|
"strings"
|
2019-01-05 22:44:33 +00:00
|
|
|
|
2020-12-28 16:35:29 +00:00
|
|
|
"github.com/spf13/afero"
|
|
|
|
|
2019-01-05 22:44:33 +00:00
|
|
|
"github.com/filebrowser/filebrowser/v2/files"
|
|
|
|
)
|
|
|
|
|
|
|
|
var withHashFile = func(fn handleFunc) handleFunc {
|
|
|
|
return func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
2020-12-28 16:35:29 +00:00
|
|
|
id, path := ifPathWithName(r)
|
|
|
|
link, err := d.store.Share.GetByHash(id)
|
2019-01-05 22:44:33 +00:00
|
|
|
if err != nil {
|
2020-12-28 16:35:29 +00:00
|
|
|
return errToStatus(err), err
|
2019-01-05 22:44:33 +00:00
|
|
|
}
|
|
|
|
|
2019-01-08 10:29:09 +00:00
|
|
|
user, err := d.store.Users.Get(d.server.Root, link.UserID)
|
2019-01-05 22:44:33 +00:00
|
|
|
if err != nil {
|
|
|
|
return errToStatus(err), err
|
|
|
|
}
|
|
|
|
|
|
|
|
d.user = user
|
|
|
|
|
|
|
|
file, err := files.NewFileInfo(files.FileOptions{
|
|
|
|
Fs: d.user.Fs,
|
|
|
|
Path: link.Path,
|
|
|
|
Modify: d.user.Perm.Modify,
|
2020-11-03 19:17:22 +00:00
|
|
|
Expand: true,
|
2019-01-05 22:44:33 +00:00
|
|
|
Checker: d,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return errToStatus(err), err
|
|
|
|
}
|
|
|
|
|
2020-12-28 16:35:29 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-05 22:44:33 +00:00
|
|
|
d.raw = file
|
|
|
|
return fn(w, r, d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-05 11:15:57 +00:00
|
|
|
// 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
|
2020-12-28 16:35:29 +00:00
|
|
|
func ifPathWithName(r *http.Request) (id, filePath string) {
|
2019-05-13 14:30:18 +00:00
|
|
|
pathElements := strings.Split(r.URL.Path, "/")
|
2019-07-05 11:15:57 +00:00
|
|
|
// 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`
|
2020-12-28 16:35:29 +00:00
|
|
|
|
|
|
|
switch len(pathElements) {
|
|
|
|
case 1:
|
|
|
|
return r.URL.Path, "/"
|
|
|
|
default:
|
|
|
|
return pathElements[0], path.Join("/", path.Join(pathElements[1:]...))
|
2019-07-05 11:15:57 +00:00
|
|
|
}
|
2019-05-13 14:30:18 +00:00
|
|
|
}
|
|
|
|
|
2019-01-05 22:44:33 +00:00
|
|
|
var publicShareHandler = withHashFile(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
2020-11-03 19:17:22 +00:00
|
|
|
file := d.raw.(*files.FileInfo)
|
|
|
|
|
|
|
|
if file.IsDir {
|
|
|
|
file.Listing.Sorting = files.Sorting{By: "name", Asc: false}
|
|
|
|
file.Listing.ApplySort()
|
|
|
|
return renderJSON(w, r, file)
|
|
|
|
}
|
|
|
|
|
|
|
|
return renderJSON(w, r, file)
|
2019-01-05 22:44:33 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
var publicDlHandler = withHashFile(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
|
|
|
|
file := d.raw.(*files.FileInfo)
|
|
|
|
if !file.IsDir {
|
|
|
|
return rawFileHandler(w, r, file)
|
|
|
|
}
|
|
|
|
|
|
|
|
return rawDirHandler(w, r, d, file)
|
|
|
|
})
|