From 4c18e5acd15e3c42b2c44f368a5b6888ca93eaa0 Mon Sep 17 00:00:00 2001 From: WeidiDeng Date: Wed, 24 May 2023 12:10:03 +0800 Subject: [PATCH] =?UTF-8?q?webdav=E5=85=BC=E5=AE=B9nextcloud=20propset?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E4=BF=AE=E6=94=B9=E6=97=B6=E9=97=B4=20(#1710?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/webdav/prop.go | 71 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/pkg/webdav/prop.go b/pkg/webdav/prop.go index 8a6e562..e60775c 100644 --- a/pkg/webdav/prop.go +++ b/pkg/webdav/prop.go @@ -36,10 +36,56 @@ func (file *FileDeadProps) DeadProps() (map[xml.Name]Property, error) { }, nil } -func (file *FileDeadProps) Patch([]Proppatch) ([]Propstat, error) { +func (file *FileDeadProps) Patch(proppatches []Proppatch) ([]Propstat, error) { + var ( + stat Propstat + err error + ) + stat.Status = http.StatusOK + for _, patch := range proppatches { + for _, prop := range patch.Props { + stat.Props = append(stat.Props, Property{XMLName: prop.XMLName}) + if prop.XMLName.Space == "DAV:" && prop.XMLName.Local == "lastmodified" { + var modtimeUnix int64 + modtimeUnix, err = strconv.ParseInt(string(prop.InnerXML), 10, 64) + if err == nil { + err = model.DB.Model(file).UpdateColumn("updated_at", time.Unix(modtimeUnix, 0)).Error + } + } + } + } + return []Propstat{stat}, err +} + +type FolderDeadProps struct { + *model.Folder +} + +func (folder *FolderDeadProps) DeadProps() (map[xml.Name]Property, error) { return nil, nil } +func (folder *FolderDeadProps) Patch(proppatches []Proppatch) ([]Propstat, error) { + var ( + stat Propstat + err error + ) + stat.Status = http.StatusOK + for _, patch := range proppatches { + for _, prop := range patch.Props { + stat.Props = append(stat.Props, Property{XMLName: prop.XMLName}) + if prop.XMLName.Space == "DAV:" && prop.XMLName.Local == "lastmodified" { + var modtimeUnix int64 + modtimeUnix, err = strconv.ParseInt(string(prop.InnerXML), 10, 64) + if err == nil { + err = model.DB.Model(folder).UpdateColumn("updated_at", time.Unix(modtimeUnix, 0)).Error + } + } + } + } + return []Propstat{stat}, err +} + type FileInfo interface { GetSize() uint64 GetName() string @@ -325,6 +371,29 @@ loop: return makePropstats(pstatForbidden, pstatFailedDep), nil } + // very unlikely to be false + exist, info := isPathExist(ctx, fs, name) + if exist { + var dph DeadPropsHolder + if info.IsDir() { + dph = &FolderDeadProps{info.(*model.Folder)} + } else { + dph = &FileDeadProps{info.(*model.File)} + } + ret, err := dph.Patch(patches) + if err != nil { + return nil, err + } + // http://www.webdav.org/specs/rfc4918.html#ELEMENT_propstat says that + // "The contents of the prop XML element must only list the names of + // properties to which the result in the status element applies." + for _, pstat := range ret { + for i, p := range pstat.Props { + pstat.Props[i] = Property{XMLName: p.XMLName} + } + } + return ret, nil + } // The file doesn't implement the optional DeadPropsHolder interface, so // all patches are forbidden. pstat := Propstat{Status: http.StatusOK}