Initial commit: docker compose config
Release Docker multi arch / docker (push) Has been cancelled
Test Install Script / Test Script Syntax (push) Has been cancelled
Test Install Script / Test on almalinux-10 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-10 (root) (push) Has been cancelled
Test Install Script / Test on almalinux-8 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-8 (root) (push) Has been cancelled
Test Install Script / Test on almalinux-9 (default) (push) Has been cancelled
Test Install Script / Test on almalinux-9 (root) (push) Has been cancelled
Test Install Script / Test on amazonlinux-2 (default) (push) Has been cancelled
Test Install Script / Test on amazonlinux-2 (root) (push) Has been cancelled
Test Install Script / Test on debian-11 (default) (push) Has been cancelled
Test Install Script / Test on debian-11 (root) (push) Has been cancelled
Test Install Script / Test on debian-12 (default) (push) Has been cancelled
Test Install Script / Test on debian-12 (root) (push) Has been cancelled
Test Install Script / Test on debian-13 (default) (push) Has been cancelled
Test Install Script / Test on debian-13 (root) (push) Has been cancelled
Test Install Script / Test on fedora-latest (default) (push) Has been cancelled
Test Install Script / Test on fedora-latest (root) (push) Has been cancelled
Test Install Script / Test on rocky-10 (default) (push) Has been cancelled
Test Install Script / Test on rocky-10 (root) (push) Has been cancelled
Test Install Script / Test on rocky-8 (default) (push) Has been cancelled
Test Install Script / Test on rocky-8 (root) (push) Has been cancelled
Test Install Script / Test on rocky-9 (default) (push) Has been cancelled
Test Install Script / Test on rocky-9 (root) (push) Has been cancelled
Test Install Script / Test on ubuntu-22.04 (default) (push) Has been cancelled
Test Install Script / Test on ubuntu-22.04 (root) (push) Has been cancelled
Test Install Script / Test on ubuntu-24.04 (default) (push) Has been cancelled
Test Install Script / Test on ubuntu-24.04 (root) (push) Has been cancelled

This commit is contained in:
2026-05-30 12:07:11 +00:00
commit 616c6b1c62
381 changed files with 55145 additions and 0 deletions
+232
View File
@@ -0,0 +1,232 @@
package webdav
import (
"context"
"errors"
"io"
"io/fs"
"os"
"path"
"sync"
"time"
"server/log"
"server/torrfs"
"github.com/gin-gonic/gin"
"golang.org/x/net/webdav"
)
var missingMethods = []string{
"PROPFIND", "PROPPATCH", "MKCOL", "COPY", "MOVE", "LOCK", "UNLOCK",
}
func MountWebDAV(r *gin.Engine) {
log.TLogln("Starting WebDAV")
tfs := torrfs.AsFS(torrfs.New())
h := &webdav.Handler{
Prefix: "/dav",
FileSystem: &ReadOnlyFS{FS: tfs},
LockSystem: webdav.NewMemLS(),
}
grp := r.Group("/dav")
handler := func(c *gin.Context) {
h.ServeHTTP(c.Writer, c.Request)
}
grp.Any("/*webdav", handler)
for _, m := range missingMethods {
grp.Handle(m, "/*webdav", handler)
}
grp.Any("", handler)
for _, m := range missingMethods {
grp.Handle(m, "", handler)
}
}
type ReadOnlyFS struct {
FS fs.FS
}
var _ webdav.FileSystem = (*ReadOnlyFS)(nil)
func (ro *ReadOnlyFS) Mkdir(ctx context.Context, name string, perm os.FileMode) error {
return os.ErrPermission
}
func (ro *ReadOnlyFS) RemoveAll(ctx context.Context, name string) error {
return os.ErrPermission
}
func (ro *ReadOnlyFS) Rename(ctx context.Context, oldName, newName string) error {
return os.ErrPermission
}
func (ro *ReadOnlyFS) Stat(ctx context.Context, name string) (os.FileInfo, error) {
name = cleanWebDAVPath(name)
return fs.Stat(ro.FS, name)
}
func (ro *ReadOnlyFS) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
if flag&(os.O_WRONLY|os.O_RDWR|os.O_APPEND|os.O_CREATE|os.O_TRUNC) != 0 {
return nil, os.ErrPermission
}
name = cleanWebDAVPath(name)
f, err := ro.FS.Open(name)
if err != nil {
return nil, err
}
return newROFile(ro.FS, name, f), nil
}
// --- file wrapper ---
type roFile struct {
fsys fs.FS
name string
mu sync.Mutex
f fs.File
dirPos int
dirList []fs.DirEntry
}
func newROFile(fsys fs.FS, name string, f fs.File) *roFile {
return &roFile{fsys: fsys, name: name, f: f}
}
var _ webdav.File = (*roFile)(nil)
func (f *roFile) Write(p []byte) (n int, err error) {
return 0, fs.ErrPermission
}
func (f *roFile) Close() error {
f.mu.Lock()
defer f.mu.Unlock()
if f.f == nil {
return nil
}
err := f.f.Close()
f.f = nil
f.dirList = nil
f.dirPos = 0
return err
}
func (f *roFile) Read(p []byte) (int, error) {
f.mu.Lock()
defer f.mu.Unlock()
if f.f == nil {
return 0, fs.ErrClosed
}
r, ok := f.f.(io.Reader)
if !ok {
return 0, fs.ErrInvalid
}
return r.Read(p)
}
func (f *roFile) Seek(offset int64, whence int) (int64, error) {
f.mu.Lock()
defer f.mu.Unlock()
if f.f == nil {
return 0, fs.ErrClosed
}
rs, ok := f.f.(io.Seeker)
if !ok {
return 0, errors.New("seek not supported")
}
return rs.Seek(offset, whence)
}
func (f *roFile) Stat() (os.FileInfo, error) {
return fs.Stat(f.fsys, f.name)
}
func (f *roFile) Readdir(count int) ([]os.FileInfo, error) {
f.mu.Lock()
defer f.mu.Unlock()
if f.f == nil {
return nil, fs.ErrClosed
}
fi, err := fs.Stat(f.fsys, f.name)
if err != nil {
return nil, err
}
if !fi.IsDir() {
return nil, fs.ErrInvalid
}
if f.dirList == nil {
des, err := fs.ReadDir(f.fsys, f.name)
if err != nil {
return nil, err
}
f.dirList = des
f.dirPos = 0
}
if count <= 0 {
out := make([]os.FileInfo, 0, len(f.dirList)-f.dirPos)
for f.dirPos < len(f.dirList) {
de := f.dirList[f.dirPos]
f.dirPos++
info, err := de.Info()
if err != nil {
continue
}
out = append(out, info)
}
return out, nil
}
out := make([]os.FileInfo, 0, count)
for f.dirPos < len(f.dirList) && len(out) < count {
de := f.dirList[f.dirPos]
f.dirPos++
info, err := de.Info()
if err != nil {
continue
}
out = append(out, info)
}
if len(out) == 0 {
return nil, io.EOF
}
return out, nil
}
// --- path helpers ---
func cleanWebDAVPath(name string) string {
if name == "" || name == "/" {
return "."
}
name = path.Clean("/" + name)
name = name[1:]
if name == "" {
return "."
}
return name
}
func nonZeroTime(t time.Time) time.Time {
if t.IsZero() {
return time.Unix(0, 0)
}
return t
}