2020-02-21 04:23:16 +01:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
2021-04-30 16:52:54 +02:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
2020-02-21 04:23:16 +01:00
|
|
|
|
2021-05-01 10:25:34 +02:00
|
|
|
"github.com/photoprism/photoprism/pkg/fs"
|
|
|
|
|
2021-01-04 10:32:43 +01:00
|
|
|
"github.com/photoprism/photoprism/pkg/txt"
|
|
|
|
|
2020-02-21 04:23:16 +01:00
|
|
|
"github.com/gin-gonic/gin"
|
2021-01-02 18:56:15 +01:00
|
|
|
"github.com/photoprism/photoprism/internal/auto"
|
2020-02-21 04:23:16 +01:00
|
|
|
"github.com/photoprism/photoprism/internal/config"
|
|
|
|
"golang.org/x/net/webdav"
|
|
|
|
)
|
|
|
|
|
2021-01-02 18:56:15 +01:00
|
|
|
const WebDAVOriginals = "/originals"
|
|
|
|
const WebDAVImport = "/import"
|
|
|
|
|
2021-04-30 16:52:54 +02:00
|
|
|
// MarkUploadAsFavorite sets the favorite flag for newly uploaded files.
|
|
|
|
func MarkUploadAsFavorite(fileName string) {
|
|
|
|
yamlName := fs.AbsPrefix(fileName, false) + fs.YamlExt
|
|
|
|
|
|
|
|
// Abort if YAML file already exists to avoid overwriting metadata.
|
|
|
|
if fs.FileExists(yamlName) {
|
|
|
|
log.Warnf("webdav: %s already exists", txt.Quote(filepath.Base(yamlName)))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure directory exists.
|
|
|
|
if err := os.MkdirAll(filepath.Dir(yamlName), os.ModePerm); err != nil {
|
|
|
|
log.Errorf("webdav: %s", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write YAML data to file.
|
2021-10-06 07:10:50 +02:00
|
|
|
if err := os.WriteFile(yamlName, []byte("Favorite: true\n"), os.ModePerm); err != nil {
|
2021-04-30 16:52:54 +02:00
|
|
|
log.Errorf("webdav: %s", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Log success.
|
|
|
|
log.Infof("webdav: marked %s as favorite", txt.Quote(filepath.Base(fileName)))
|
|
|
|
}
|
|
|
|
|
2021-08-19 12:49:07 +02:00
|
|
|
// WebDAV handles any requests to /originals|import/*
|
2020-02-21 04:23:16 +01:00
|
|
|
func WebDAV(path string, router *gin.RouterGroup, conf *config.Config) {
|
|
|
|
if router == nil {
|
|
|
|
log.Error("webdav: router is nil")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if conf == nil {
|
|
|
|
log.Error("webdav: conf is nil")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
f := webdav.Dir(path)
|
|
|
|
|
|
|
|
srv := &webdav.Handler{
|
2020-03-09 01:13:32 +01:00
|
|
|
Prefix: router.BasePath(),
|
2020-02-21 04:23:16 +01:00
|
|
|
FileSystem: f,
|
|
|
|
LockSystem: webdav.NewMemLS(),
|
|
|
|
Logger: func(r *http.Request, err error) {
|
|
|
|
if err != nil {
|
2021-01-02 18:56:15 +01:00
|
|
|
switch r.Method {
|
2021-01-04 10:32:43 +01:00
|
|
|
case MethodPut, MethodPost, MethodPatch, MethodDelete, MethodCopy, MethodMove:
|
|
|
|
log.Errorf("webdav: %s in %s %s", txt.Quote(err.Error()), r.Method, r.URL)
|
|
|
|
case MethodPropfind:
|
|
|
|
log.Tracef("webdav: %s in %s %s", txt.Quote(err.Error()), r.Method, r.URL)
|
2021-01-02 18:56:15 +01:00
|
|
|
default:
|
2021-01-04 10:32:43 +01:00
|
|
|
log.Debugf("webdav: %s in %s %s", txt.Quote(err.Error()), r.Method, r.URL)
|
2021-01-02 18:56:15 +01:00
|
|
|
}
|
|
|
|
|
2020-02-21 04:23:16 +01:00
|
|
|
} else {
|
2021-04-30 16:52:54 +02:00
|
|
|
// Mark uploaded files as favorite if X-Favorite HTTP header is "1".
|
|
|
|
if r.Method == MethodPut && r.Header.Get("X-Favorite") == "1" {
|
|
|
|
if router.BasePath() == WebDAVOriginals {
|
|
|
|
MarkUploadAsFavorite(filepath.Join(conf.OriginalsPath(), strings.TrimPrefix(r.URL.Path, router.BasePath())))
|
|
|
|
} else if router.BasePath() == WebDAVImport {
|
|
|
|
MarkUploadAsFavorite(filepath.Join(conf.ImportPath(), strings.TrimPrefix(r.URL.Path, router.BasePath())))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-02 18:56:15 +01:00
|
|
|
switch r.Method {
|
2021-01-04 10:32:43 +01:00
|
|
|
case MethodPut, MethodPost, MethodPatch, MethodDelete, MethodCopy, MethodMove:
|
2021-01-02 18:56:15 +01:00
|
|
|
log.Infof("webdav: %s %s", r.Method, r.URL)
|
|
|
|
|
|
|
|
if router.BasePath() == WebDAVOriginals {
|
|
|
|
auto.ShouldIndex()
|
|
|
|
} else if router.BasePath() == WebDAVImport {
|
|
|
|
auto.ShouldImport()
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
log.Tracef("webdav: %s %s", r.Method, r.URL)
|
|
|
|
}
|
2020-02-21 04:23:16 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
handler := func(c *gin.Context) {
|
|
|
|
w := c.Writer
|
|
|
|
r := c.Request
|
|
|
|
|
|
|
|
srv.ServeHTTP(w, r)
|
|
|
|
}
|
|
|
|
|
2021-01-04 10:32:43 +01:00
|
|
|
router.Handle(MethodHead, "/*path", handler)
|
|
|
|
router.Handle(MethodGet, "/*path", handler)
|
|
|
|
router.Handle(MethodPut, "/*path", handler)
|
|
|
|
router.Handle(MethodPost, "/*path", handler)
|
|
|
|
router.Handle(MethodPatch, "/*path", handler)
|
|
|
|
router.Handle(MethodDelete, "/*path", handler)
|
|
|
|
router.Handle(MethodOptions, "/*path", handler)
|
|
|
|
router.Handle(MethodMkcol, "/*path", handler)
|
|
|
|
router.Handle(MethodCopy, "/*path", handler)
|
|
|
|
router.Handle(MethodMove, "/*path", handler)
|
|
|
|
router.Handle(MethodLock, "/*path", handler)
|
|
|
|
router.Handle(MethodUnlock, "/*path", handler)
|
|
|
|
router.Handle(MethodPropfind, "/*path", handler)
|
|
|
|
router.Handle(MethodProppatch, "/*path", handler)
|
2020-02-21 04:23:16 +01:00
|
|
|
}
|