mirror of https://github.com/cloudreve/Cloudreve
Fix: unable to save office file in root directory of WebDAV
parent
bb27d1d587
commit
cf90ab5a9a
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/HFO4/cloudreve/pkg/serializer"
|
"github.com/HFO4/cloudreve/pkg/serializer"
|
||||||
"github.com/gin-contrib/sessions"
|
"github.com/gin-contrib/sessions"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SignRequired 验证请求签名
|
// SignRequired 验证请求签名
|
||||||
|
@ -49,3 +50,47 @@ func AuthRequired() gin.HandlerFunc {
|
||||||
c.Abort()
|
c.Abort()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WebDAVAuth 验证WebDAV登录及权限
|
||||||
|
func WebDAVAuth() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
// OPTIONS 请求不需要鉴权,否则Windows10下无法保存文档
|
||||||
|
if c.Request.Method == "OPTIONS" {
|
||||||
|
c.Next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
username, password, ok := c.Request.BasicAuth()
|
||||||
|
if !ok {
|
||||||
|
c.Writer.Header()["WWW-Authenticate"] = []string{`Basic realm="cloudreve"`}
|
||||||
|
c.Status(http.StatusUnauthorized)
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedUser, err := model.GetUserByEmail(username)
|
||||||
|
if err != nil {
|
||||||
|
c.Status(http.StatusUnauthorized)
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密码正确?
|
||||||
|
ok, _ = expectedUser.CheckPassword(password)
|
||||||
|
if !ok {
|
||||||
|
c.Status(http.StatusUnauthorized)
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户组已启用WebDAV?
|
||||||
|
if !expectedUser.Group.WebDAVEnabled {
|
||||||
|
c.Status(http.StatusForbidden)
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Set("user", &expectedUser)
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ func Init() {
|
||||||
|
|
||||||
// Debug模式下,输出所有 SQL 日志
|
// Debug模式下,输出所有 SQL 日志
|
||||||
if conf.SystemConfig.Debug {
|
if conf.SystemConfig.Debug {
|
||||||
db.LogMode(true)
|
db.LogMode(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
//db.SetLogger(util.Log())
|
//db.SetLogger(util.Log())
|
||||||
|
|
|
@ -32,17 +32,17 @@ func moveFiles(ctx context.Context, fs *filesystem.FileSystem, src FileInfo, dst
|
||||||
folderIDs []uint
|
folderIDs []uint
|
||||||
)
|
)
|
||||||
if src.IsDir() {
|
if src.IsDir() {
|
||||||
fileIDs = []uint{src.(*model.Folder).ID}
|
folderIDs = []uint{src.(*model.Folder).ID}
|
||||||
} else {
|
} else {
|
||||||
folderIDs = []uint{src.(*model.File).ID}
|
fileIDs = []uint{src.(*model.File).ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否为重命名
|
// 判断是否为重命名
|
||||||
if src.GetPosition() == path.Dir(dst) {
|
if src.GetPosition() == path.Dir(dst) {
|
||||||
err = fs.Rename(
|
err = fs.Rename(
|
||||||
ctx,
|
ctx,
|
||||||
fileIDs,
|
|
||||||
folderIDs,
|
folderIDs,
|
||||||
|
fileIDs,
|
||||||
path.Base(dst),
|
path.Base(dst),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -35,8 +35,11 @@ func (h *Handler) stripPrefix(p string, uid uint) (string, int, error) {
|
||||||
if h.Prefix == "" {
|
if h.Prefix == "" {
|
||||||
return p, http.StatusOK, nil
|
return p, http.StatusOK, nil
|
||||||
}
|
}
|
||||||
prefix := h.Prefix + strconv.FormatUint(uint64(uid), 10)
|
prefix := h.Prefix
|
||||||
if r := strings.TrimPrefix(p, prefix); len(r) < len(p) {
|
if r := strings.TrimPrefix(p, prefix); len(r) < len(p) {
|
||||||
|
if len(r) == 0 {
|
||||||
|
r = "/"
|
||||||
|
}
|
||||||
return util.RemoveSlash(r), http.StatusOK, nil
|
return util.RemoveSlash(r), http.StatusOK, nil
|
||||||
}
|
}
|
||||||
return p, http.StatusNotFound, errPrefixMismatch
|
return p, http.StatusNotFound, errPrefixMismatch
|
||||||
|
@ -164,9 +167,9 @@ func (h *Handler) confirmLocks(r *http.Request, src, dst string, fs *filesystem.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if u.Host != r.Host {
|
//if u.Host != r.Host {
|
||||||
continue
|
// continue
|
||||||
}
|
//}
|
||||||
lsrc, status, err = h.stripPrefix(u.Path, fs.User.ID)
|
lsrc, status, err = h.stripPrefix(u.Path, fs.User.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, status, err
|
return nil, status, err
|
||||||
|
@ -381,9 +384,9 @@ func (h *Handler) handleCopyMove(w http.ResponseWriter, r *http.Request, fs *fil
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return http.StatusBadRequest, errInvalidDestination
|
return http.StatusBadRequest, errInvalidDestination
|
||||||
}
|
}
|
||||||
if u.Host != "" && u.Host != r.Host {
|
//if u.Host != "" && u.Host != r.Host {
|
||||||
return http.StatusBadGateway, errInvalidDestination
|
// return http.StatusBadGateway, errInvalidDestination
|
||||||
}
|
//}
|
||||||
|
|
||||||
src, status, err := h.stripPrefix(r.URL.Path, fs.User.ID)
|
src, status, err := h.stripPrefix(r.URL.Path, fs.User.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -436,7 +439,9 @@ func (h *Handler) handleCopyMove(w http.ResponseWriter, r *http.Request, fs *fil
|
||||||
return copyFiles(ctx, fs, target, dst, r.Header.Get("Overwrite") != "F", depth, 0)
|
return copyFiles(ctx, fs, target, dst, r.Header.Get("Overwrite") != "F", depth, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
release, status, err := h.confirmLocks(r, src, dst, fs)
|
// windows下,某些情况下(网盘根目录下)Office保存文件时附带的锁token只包含源文件,
|
||||||
|
// 此处暂时去除了对dst锁的检查
|
||||||
|
release, status, err := h.confirmLocks(r, src, "", fs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return status, err
|
return status, err
|
||||||
}
|
}
|
||||||
|
@ -575,9 +580,6 @@ func (h *Handler) handleUnlock(w http.ResponseWriter, r *http.Request, fs *files
|
||||||
// OK
|
// OK
|
||||||
func (h *Handler) handlePropfind(w http.ResponseWriter, r *http.Request, fs *filesystem.FileSystem) (status int, err error) {
|
func (h *Handler) handlePropfind(w http.ResponseWriter, r *http.Request, fs *filesystem.FileSystem) (status int, err error) {
|
||||||
reqPath, status, err := h.stripPrefix(r.URL.Path, fs.User.ID)
|
reqPath, status, err := h.stripPrefix(r.URL.Path, fs.User.ID)
|
||||||
if reqPath == "" {
|
|
||||||
reqPath = "/"
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return status, err
|
return status, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
model "github.com/HFO4/cloudreve/models"
|
|
||||||
"github.com/HFO4/cloudreve/pkg/filesystem"
|
"github.com/HFO4/cloudreve/pkg/filesystem"
|
||||||
"github.com/HFO4/cloudreve/pkg/util"
|
"github.com/HFO4/cloudreve/pkg/util"
|
||||||
"github.com/HFO4/cloudreve/pkg/webdav"
|
"github.com/HFO4/cloudreve/pkg/webdav"
|
||||||
|
@ -12,18 +11,17 @@ var handler *webdav.Handler
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
handler = &webdav.Handler{
|
handler = &webdav.Handler{
|
||||||
Prefix: "/dav/",
|
Prefix: "/dav",
|
||||||
LockSystem: make(map[uint]webdav.LockSystem),
|
LockSystem: make(map[uint]webdav.LockSystem),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServeWebDAV 处理WebDAV相关请求
|
||||||
func ServeWebDAV(c *gin.Context) {
|
func ServeWebDAV(c *gin.Context) {
|
||||||
// 测试用user
|
|
||||||
user, _ := model.GetUserByID(1)
|
|
||||||
c.Set("user", &user)
|
|
||||||
fs, err := filesystem.NewFileSystemFromContext(c)
|
fs, err := filesystem.NewFileSystemFromContext(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.Log().Panic("%s", err)
|
util.Log().Warning("无法为WebDAV初始化文件系统,%s", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.ServeHTTP(c.Writer, c.Request, fs)
|
handler.ServeHTTP(c.Writer, c.Request, fs)
|
||||||
|
|
|
@ -11,21 +11,18 @@ import (
|
||||||
// initWebDAV 初始化WebDAV相关路由
|
// initWebDAV 初始化WebDAV相关路由
|
||||||
func initWebDAV(group *gin.RouterGroup) {
|
func initWebDAV(group *gin.RouterGroup) {
|
||||||
{
|
{
|
||||||
group.Any("", func(context *gin.Context) {
|
group.Use(middleware.WebDAVAuth())
|
||||||
context.Status(403)
|
|
||||||
context.Abort()
|
|
||||||
})
|
|
||||||
|
|
||||||
group.Any(":uid/*path", controllers.ServeWebDAV)
|
group.Any("/*path", controllers.ServeWebDAV)
|
||||||
group.Any(":uid", controllers.ServeWebDAV)
|
group.Any("", controllers.ServeWebDAV)
|
||||||
group.Handle("PROPFIND", ":uid/*path", controllers.ServeWebDAV)
|
group.Handle("PROPFIND", "/*path", controllers.ServeWebDAV)
|
||||||
group.Handle("PROPFIND", ":uid", controllers.ServeWebDAV)
|
group.Handle("PROPFIND", "", controllers.ServeWebDAV)
|
||||||
group.Handle("MKCOL", ":uid/*path", controllers.ServeWebDAV)
|
group.Handle("MKCOL", "/*path", controllers.ServeWebDAV)
|
||||||
group.Handle("LOCK", ":uid/*path", controllers.ServeWebDAV)
|
group.Handle("LOCK", "/*path", controllers.ServeWebDAV)
|
||||||
group.Handle("UNLOCK", ":uid/*path", controllers.ServeWebDAV)
|
group.Handle("UNLOCK", "/*path", controllers.ServeWebDAV)
|
||||||
group.Handle("PROPPATCH", ":uid/*path", controllers.ServeWebDAV)
|
group.Handle("PROPPATCH", "/*path", controllers.ServeWebDAV)
|
||||||
group.Handle("COPY", ":uid/*path", controllers.ServeWebDAV)
|
group.Handle("COPY", "/*path", controllers.ServeWebDAV)
|
||||||
group.Handle("MOVE", ":uid/*path", controllers.ServeWebDAV)
|
group.Handle("MOVE", "/*path", controllers.ServeWebDAV)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue