fix: match CHFS preview and listing behavior
This commit is contained in:
@@ -89,7 +89,7 @@ func main() {
|
|||||||
if len(cfg.Path) == 1 {
|
if len(cfg.Path) == 1 {
|
||||||
store = storage.Local{Root: root}
|
store = storage.Local{Root: root}
|
||||||
}
|
}
|
||||||
srv := &api.Server{Store: store, Auth: mgr, Sessions: map[string]*auth.Account{}, SessionExpiry: map[string]time.Time{}, SessionTimeout: cfg.SessionTimeout, WebDAVRoot: root, Allow: cfg.Allow, MultiRoot: len(cfg.Path) > 1, RemoveMode: cfg.FileRemove, Log: opslog.New(cfg.Log)}
|
srv := &api.Server{Store: store, Auth: mgr, Sessions: map[string]*auth.Account{}, SessionExpiry: map[string]time.Time{}, SessionTimeout: cfg.SessionTimeout, WebDAVRoot: root, Allow: cfg.Allow, MultiRoot: len(cfg.Path) > 1, RemoveMode: cfg.FileRemove, ImagePreview: cfg.ImagePreview, Log: opslog.New(cfg.Log)}
|
||||||
addr := ":" + itoa(cfg.Port)
|
addr := ":" + itoa(cfg.Port)
|
||||||
log.Printf("chfs-ng listening on %s root=%s removeMode=%d", addr, filepath.Clean(root), cfg.FileRemove)
|
log.Printf("chfs-ng listening on %s root=%s removeMode=%d", addr, filepath.Clean(root), cfg.FileRemove)
|
||||||
if cfg.SSLCert != "" && cfg.SSLKey != "" {
|
if cfg.SSLCert != "" && cfg.SSLKey != "" {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ go 1.22
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Bios-Marcel/wastebasket v0.0.3
|
github.com/Bios-Marcel/wastebasket v0.0.3
|
||||||
|
github.com/anthonynsimon/bild v0.14.0
|
||||||
github.com/emersion/go-webdav v0.7.0
|
github.com/emersion/go-webdav v0.7.0
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.2
|
github.com/golang-jwt/jwt/v4 v4.5.2
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
github.com/Bios-Marcel/wastebasket v0.0.3 h1:gyuMcoDav6n+sdynn9TDl1NN7GOAnoy227JErVSW3RM=
|
github.com/Bios-Marcel/wastebasket v0.0.3 h1:gyuMcoDav6n+sdynn9TDl1NN7GOAnoy227JErVSW3RM=
|
||||||
github.com/Bios-Marcel/wastebasket v0.0.3/go.mod h1:FChzXi1izqzdPb6BiNZmcZLGyTYiT61iGx9Rxx9GNeI=
|
github.com/Bios-Marcel/wastebasket v0.0.3/go.mod h1:FChzXi1izqzdPb6BiNZmcZLGyTYiT61iGx9Rxx9GNeI=
|
||||||
|
github.com/anthonynsimon/bild v0.14.0 h1:IFRkmKdNdqmexXHfEU7rPlAmdUZ8BDZEGtGHDnGWync=
|
||||||
|
github.com/anthonynsimon/bild v0.14.0/go.mod h1:hcvEAyBjTW69qkKJTfpcDQ83sSZHxwOunsseDfeQhUs=
|
||||||
github.com/emersion/go-ical v0.0.0-20240127095438-fc1c9d8fb2b6/go.mod h1:BEksegNspIkjCQfmzWgsgbu6KdeJ/4LwUZs7DMBzjzw=
|
github.com/emersion/go-ical v0.0.0-20240127095438-fc1c9d8fb2b6/go.mod h1:BEksegNspIkjCQfmzWgsgbu6KdeJ/4LwUZs7DMBzjzw=
|
||||||
github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
||||||
github.com/emersion/go-webdav v0.7.0 h1:cp6aBWXBf8Sjzguka9VJarr4XTkGc2IHxXI1Gq3TKpA=
|
github.com/emersion/go-webdav v0.7.0 h1:cp6aBWXBf8Sjzguka9VJarr4XTkGc2IHxXI1Gq3TKpA=
|
||||||
|
|||||||
@@ -2,9 +2,14 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image"
|
||||||
|
_ "image/gif"
|
||||||
|
_ "image/jpeg"
|
||||||
|
"image/png"
|
||||||
"io"
|
"io"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net"
|
"net"
|
||||||
@@ -19,6 +24,7 @@ import (
|
|||||||
"chfs-ng/internal/auth"
|
"chfs-ng/internal/auth"
|
||||||
"chfs-ng/internal/opslog"
|
"chfs-ng/internal/opslog"
|
||||||
"chfs-ng/internal/storage"
|
"chfs-ng/internal/storage"
|
||||||
|
"github.com/anthonynsimon/bild/transform"
|
||||||
"github.com/emersion/go-webdav"
|
"github.com/emersion/go-webdav"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -34,6 +40,7 @@ type Server struct {
|
|||||||
Allow string
|
Allow string
|
||||||
MultiRoot bool
|
MultiRoot bool
|
||||||
RemoveMode int
|
RemoveMode int
|
||||||
|
ImagePreview bool
|
||||||
Log *opslog.Logger
|
Log *opslog.Logger
|
||||||
}
|
}
|
||||||
type fileInfo struct {
|
type fileInfo struct {
|
||||||
@@ -463,7 +470,7 @@ func (s *Server) search(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
needle := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("str")))
|
needle := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("str")))
|
||||||
var out []fileInfo
|
out := make([]fileInfo, 0)
|
||||||
var walk func(string) error
|
var walk func(string) error
|
||||||
walk = func(dir string) error {
|
walk = func(dir string) error {
|
||||||
items, err := s.Store.List(dir)
|
items, err := s.Store.List(dir)
|
||||||
@@ -502,16 +509,39 @@ func (s *Server) shared(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) preview(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) preview(w http.ResponseWriter, r *http.Request) {
|
||||||
if !account(r, s).MaskFor(strings.Trim(r.URL.Query().Get("file"), "/")).HasRead() {
|
file := strings.Trim(strings.ReplaceAll(r.URL.Query().Get("file"), "\\", "/"), "/")
|
||||||
http.Error(w, "forbidden", 403)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
file := strings.Trim(r.URL.Query().Get("file"), "/")
|
|
||||||
if file == "" {
|
if file == "" {
|
||||||
http.Error(w, "file required", 400)
|
http.Error(w, "file required", 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.serveFile(w, r, file, false)
|
if !account(r, s).MaskFor(file).HasRead() {
|
||||||
|
http.Error(w, "forbidden", 403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !s.ImagePreview {
|
||||||
|
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f, err := s.Store.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
src, _, err := image.Decode(f)
|
||||||
|
if err != nil {
|
||||||
|
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
thumb := transform.Resize(src, 64, 64, transform.Linear)
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := png.Encode(&buf, thumb); err != nil {
|
||||||
|
writeJSONError(w, http.StatusInternalServerError, "Open image file fail!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Set("Cache-Control", "max-age=2592000")
|
||||||
|
w.Header().Set("Content-Type", "image/png")
|
||||||
|
_, _ = w.Write(buf.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) fileHandler(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) fileHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
@@ -258,7 +259,12 @@ func (s Local) List(path string) ([]os.FileInfo, error) {
|
|||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
return f.Readdir(-1)
|
items, err := f.Readdir(-1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sort.Slice(items, func(i, j int) bool { return items[i].Name() < items[j].Name() })
|
||||||
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ fs.FS
|
var _ fs.FS
|
||||||
|
|||||||
Reference in New Issue
Block a user