Fix: unable to save office file in root directory of WebDAV

pull/247/head
HFO4 5 years ago
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("/*path", controllers.ServeWebDAV)
}) group.Any("", controllers.ServeWebDAV)
group.Handle("PROPFIND", "/*path", controllers.ServeWebDAV)
group.Any(":uid/*path", controllers.ServeWebDAV) group.Handle("PROPFIND", "", controllers.ServeWebDAV)
group.Any(":uid", controllers.ServeWebDAV) group.Handle("MKCOL", "/*path", controllers.ServeWebDAV)
group.Handle("PROPFIND", ":uid/*path", controllers.ServeWebDAV) group.Handle("LOCK", "/*path", controllers.ServeWebDAV)
group.Handle("PROPFIND", ":uid", controllers.ServeWebDAV) group.Handle("UNLOCK", "/*path", controllers.ServeWebDAV)
group.Handle("MKCOL", ":uid/*path", controllers.ServeWebDAV) group.Handle("PROPPATCH", "/*path", controllers.ServeWebDAV)
group.Handle("LOCK", ":uid/*path", controllers.ServeWebDAV) group.Handle("COPY", "/*path", controllers.ServeWebDAV)
group.Handle("UNLOCK", ":uid/*path", controllers.ServeWebDAV) group.Handle("MOVE", "/*path", controllers.ServeWebDAV)
group.Handle("PROPPATCH", ":uid/*path", controllers.ServeWebDAV)
group.Handle("COPY", ":uid/*path", controllers.ServeWebDAV)
group.Handle("MOVE", ":uid/*path", controllers.ServeWebDAV)
} }
} }

Loading…
Cancel
Save