diff --git a/.drone.env b/.drone.env
index fd04cf6687..15c8d1ed6b 100644
--- a/.drone.env
+++ b/.drone.env
@@ -1,3 +1,3 @@
# The test runner source for API tests
-CORE_COMMITID=e285879a8a79e692497937ebf340bc6b9c925b4f
+CORE_COMMITID=cb558615d4a1850629be1c463454dabac71a4905
CORE_BRANCH=master
diff --git a/changelog/unreleased/ocdav-cleanup.md b/changelog/unreleased/ocdav-cleanup.md
new file mode 100644
index 0000000000..ecbe7e69d3
--- /dev/null
+++ b/changelog/unreleased/ocdav-cleanup.md
@@ -0,0 +1,5 @@
+Change: small clean up of the ocdav code
+
+Cleaned up the ocdav code to make it more readable and in one case a bit faster.
+
+https://github.com/cs3org/reva/pull/2658
diff --git a/internal/http/services/owncloud/ocdav/locks.go b/internal/http/services/owncloud/ocdav/locks.go
index e4bfb00446..822d23dc94 100644
--- a/internal/http/services/owncloud/ocdav/locks.go
+++ b/internal/http/services/owncloud/ocdav/locks.go
@@ -36,7 +36,7 @@ import (
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/errors"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net"
- "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/props"
+ "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/prop"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/spacelookup"
"github.com/cs3org/reva/v2/pkg/appctx"
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
@@ -557,10 +557,10 @@ func writeLockInfo(w io.Writer, token string, ld LockDetails) (int, error) {
lockdiscovery.WriteString(" Infinite\n")
}
if token != "" {
- lockdiscovery.WriteString(fmt.Sprintf(" %s\n", props.Escape(token)))
+ lockdiscovery.WriteString(fmt.Sprintf(" %s\n", prop.Escape(token)))
}
if href != "" {
- lockdiscovery.WriteString(fmt.Sprintf(" %s\n", props.Escape(href)))
+ lockdiscovery.WriteString(fmt.Sprintf(" %s\n", prop.Escape(href)))
}
lockdiscovery.WriteString("")
diff --git a/internal/http/services/owncloud/ocdav/net/net.go b/internal/http/services/owncloud/ocdav/net/net.go
index 586c8c7cc4..9fab05c963 100644
--- a/internal/http/services/owncloud/ocdav/net/net.go
+++ b/internal/http/services/owncloud/ocdav/net/net.go
@@ -19,9 +19,7 @@
package net
import (
- "fmt"
"net/url"
- "regexp"
"strings"
"github.com/pkg/errors"
@@ -69,37 +67,11 @@ func (d Depth) String() string {
return string(d)
}
-// replaceAllStringSubmatchFunc is taken from 'Go: Replace String with Regular Expression Callback'
-// see: https://elliotchance.medium.com/go-replace-string-with-regular-expression-callback-f89948bad0bb
-func replaceAllStringSubmatchFunc(re *regexp.Regexp, str string, repl func([]string) string) string {
- result := ""
- lastIndex := 0
- for _, v := range re.FindAllSubmatchIndex([]byte(str), -1) {
- groups := []string{}
- for i := 0; i < len(v); i += 2 {
- groups = append(groups, str[v[i]:v[i+1]])
- }
- result += str[lastIndex:v[0]] + repl(groups)
- lastIndex = v[1]
- }
- return result + str[lastIndex:]
-}
-
-var hrefre = regexp.MustCompile(`([^A-Za-z0-9_\-.~()/:@!$])`)
-
// EncodePath encodes the path of a url.
//
// slashes (/) are treated as path-separators.
-// ported from https://github.com/sabre-io/http/blob/bb27d1a8c92217b34e778ee09dcf79d9a2936e84/lib/functions.php#L369-L379
func EncodePath(path string) string {
- return replaceAllStringSubmatchFunc(hrefre, path, func(groups []string) string {
- b := groups[1]
- var sb strings.Builder
- for i := 0; i < len(b); i++ {
- sb.WriteString(fmt.Sprintf("%%%x", b[i]))
- }
- return sb.String()
- })
+ return (&url.URL{Path: path}).EscapedPath()
}
// ParseDepth parses the depth header value defined in https://tools.ietf.org/html/rfc4918#section-9.1
diff --git a/internal/http/services/owncloud/ocdav/net/net_test.go b/internal/http/services/owncloud/ocdav/net/net_test.go
index 24ee8da430..3b254067f3 100644
--- a/internal/http/services/owncloud/ocdav/net/net_test.go
+++ b/internal/http/services/owncloud/ocdav/net/net_test.go
@@ -64,7 +64,7 @@ var _ = Describe("Net", func() {
Describe("EncodePath", func() {
It("encodes paths", func() {
Expect(net.EncodePath("foo")).To(Equal("foo"))
- Expect(net.EncodePath("/some/path/Folder %^*(#1)")).To(Equal("/some/path/Folder%20%25%5e%2a(%231)"))
+ Expect(net.EncodePath("/some/path/Folder %^*(#1)")).To(Equal("/some/path/Folder%20%25%5E%2A%28%231%29"))
})
/*
diff --git a/internal/http/services/owncloud/ocdav/props/props.go b/internal/http/services/owncloud/ocdav/prop/prop.go
similarity index 80%
rename from internal/http/services/owncloud/ocdav/props/props.go
rename to internal/http/services/owncloud/ocdav/prop/prop.go
index f3065e357c..607679520c 100644
--- a/internal/http/services/owncloud/ocdav/props/props.go
+++ b/internal/http/services/owncloud/ocdav/prop/prop.go
@@ -16,7 +16,7 @@
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
-package props
+package prop
import (
"bytes"
@@ -49,29 +49,45 @@ func xmlEscaped(val string) []byte {
return buf.Bytes()
}
-// NewPropNS returns a new PropertyXML instance
-func NewPropNS(namespace string, local string, val string) *PropertyXML {
- return &PropertyXML{
+// EscapedNS returns a new PropertyXML instance while xml-escaping the value
+func EscapedNS(namespace string, local string, val string) PropertyXML {
+ return PropertyXML{
XMLName: xml.Name{Space: namespace, Local: local},
Lang: "",
InnerXML: xmlEscaped(val),
}
}
-// NewProp returns a new PropertyXML instance while xml-escaping the value
+// Escaped returns a new PropertyXML instance while xml-escaping the value
// TODO properly use the space
-func NewProp(key, val string) *PropertyXML {
- return &PropertyXML{
+func Escaped(key, val string) PropertyXML {
+ return PropertyXML{
XMLName: xml.Name{Space: "", Local: key},
Lang: "",
InnerXML: xmlEscaped(val),
}
}
-// NewPropRaw returns a new PropertyXML instance for the given key/value pair
+// NotFound returns a new PropertyXML instance with an empty value
+func NotFound(key string) PropertyXML {
+ return PropertyXML{
+ XMLName: xml.Name{Space: "", Local: key},
+ Lang: "",
+ }
+}
+
+// NotFoundNS returns a new PropertyXML instance with the given namespace and an empty value
+func NotFoundNS(namespace, key string) PropertyXML {
+ return PropertyXML{
+ XMLName: xml.Name{Space: namespace, Local: key},
+ Lang: "",
+ }
+}
+
+// Raw returns a new PropertyXML instance for the given key/value pair
// TODO properly use the space
-func NewPropRaw(key, val string) *PropertyXML {
- return &PropertyXML{
+func Raw(key, val string) PropertyXML {
+ return PropertyXML{
XMLName: xml.Name{Space: "", Local: key},
Lang: "",
InnerXML: []byte(val),
diff --git a/internal/http/services/owncloud/ocdav/propfind/propfind.go b/internal/http/services/owncloud/ocdav/propfind/propfind.go
index e109c08a83..1295f37ede 100644
--- a/internal/http/services/owncloud/ocdav/propfind/propfind.go
+++ b/internal/http/services/owncloud/ocdav/propfind/propfind.go
@@ -39,7 +39,7 @@ import (
"github.com/cs3org/reva/v2/internal/grpc/services/storageprovider"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/errors"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net"
- "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/props"
+ "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/prop"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/spacelookup"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/conversions"
"github.com/cs3org/reva/v2/pkg/appctx"
@@ -83,10 +83,10 @@ type PropstatXML struct {
// not honoring namespace declarations inside a xmltag with a
// parent element for anonymous slice elements.
// Use of multistatusWriter takes care of this.
- Prop []*props.PropertyXML `xml:"d:prop>_ignored_"`
- Status string `xml:"d:status"`
- Error *errors.ErrorXML `xml:"d:error"`
- ResponseDescription string `xml:"d:responsedescription,omitempty"`
+ Prop []prop.PropertyXML `xml:"d:prop>_ignored_"`
+ Status string `xml:"d:status"`
+ Error *errors.ErrorXML `xml:"d:error"`
+ ResponseDescription string `xml:"d:responsedescription,omitempty"`
}
// ResponseXML holds the xml representation of a propfind response
@@ -136,10 +136,10 @@ type PropstatUnmarshalXML struct {
// not honoring namespace declarations inside a xmltag with a
// parent element for anonymous slice elements.
// Use of multistatusWriter takes care of this.
- Prop []*props.PropertyXML `xml:"prop"`
- Status string `xml:"status"`
- Error *errors.ErrorXML `xml:"d:error"`
- ResponseDescription string `xml:"responsedescription,omitempty"`
+ Prop []*prop.PropertyXML `xml:"prop"`
+ Status string `xml:"status"`
+ Error *errors.ErrorXML `xml:"d:error"`
+ ResponseDescription string `xml:"responsedescription,omitempty"`
}
// NewMultiStatusResponseXML returns a preconfigured instance of MultiStatusResponseXML
@@ -728,11 +728,11 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
propstatOK := PropstatXML{
Status: "HTTP/1.1 200 OK",
- Prop: []*props.PropertyXML{},
+ Prop: []prop.PropertyXML{},
}
propstatNotFound := PropstatXML{
Status: "HTTP/1.1 404 Not Found",
- Prop: []*props.PropertyXML{},
+ Prop: []prop.PropertyXML{},
}
// when allprops has been requested
if pf.Allprop != nil {
@@ -741,9 +741,9 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
if md.Id != nil {
id := resourceid.OwnCloudResourceIDWrap(md.Id)
propstatOK.Prop = append(propstatOK.Prop,
- props.NewProp("oc:id", id),
- props.NewProp("oc:fileid", id),
- props.NewProp("oc:spaceid", md.Id.StorageId),
+ prop.Escaped("oc:id", id),
+ prop.Escaped("oc:fileid", id),
+ prop.Escaped("oc:spaceid", md.Id.StorageId),
)
}
@@ -751,37 +751,37 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
// etags must be enclosed in double quotes and cannot contain them.
// See https://tools.ietf.org/html/rfc7232#section-2.3 for details
// TODO(jfd) handle weak tags that start with 'W/'
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:getetag", quoteEtag(md.Etag)))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("d:getetag", quoteEtag(md.Etag)))
}
if md.PermissionSet != nil {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:permissions", wdp))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:permissions", wdp))
}
// always return size, well nearly always ... public link shares are a little weird
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropRaw("d:resourcetype", ""))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("d:resourcetype", ""))
if ls == nil {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:size", size))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:size", size))
}
// A PROPFIND request SHOULD NOT return DAV:quota-available-bytes and DAV:quota-used-bytes
// from https://www.rfc-editor.org/rfc/rfc4331.html#section-2
- // propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:quota-used-bytes", size))
- // propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:quota-available-bytes", quota))
+ // propstatOK.Prop = append(propstatOK.Prop, prop.NewProp("d:quota-used-bytes", size))
+ // propstatOK.Prop = append(propstatOK.Prop, prop.NewProp("d:quota-available-bytes", quota))
} else {
propstatOK.Prop = append(propstatOK.Prop,
- props.NewProp("d:resourcetype", ""),
- props.NewProp("d:getcontentlength", size),
+ prop.Escaped("d:resourcetype", ""),
+ prop.Escaped("d:getcontentlength", size),
)
if md.MimeType != "" {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:getcontenttype", md.MimeType))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("d:getcontenttype", md.MimeType))
}
}
// Finder needs the getLastModified property to work.
if md.Mtime != nil {
t := utils.TSToTime(md.Mtime).UTC()
lastModifiedString := t.Format(net.RFC1123)
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:getlastmodified", lastModifiedString))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("d:getlastmodified", lastModifiedString))
}
// stay bug compatible with oc10, see https://github.com/owncloud/core/pull/38304#issuecomment-762185241
@@ -812,25 +812,25 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
}
if checksums.Len() > 0 {
checksums.WriteString("")
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropRaw("oc:checksums", checksums.String()))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:checksums", checksums.String()))
}
// ls do not report any properties as missing by default
if ls == nil {
// favorites from arbitrary metadata
if k := md.GetArbitraryMetadata(); k == nil {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:favorite", "0"))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:favorite", "0"))
} else if amd := k.GetMetadata(); amd == nil {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:favorite", "0"))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:favorite", "0"))
} else if v, ok := amd[net.PropOcFavorite]; ok && v != "" {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:favorite", v))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:favorite", v))
} else {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:favorite", "0"))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:favorite", "0"))
}
}
if lock != nil {
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropRaw("d:lockdiscovery", activeLocks(&sublog, lock)))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("d:lockdiscovery", activeLocks(&sublog, lock)))
}
// TODO return other properties ... but how do we put them in a namespace?
} else {
@@ -843,21 +843,21 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
// I tested the desktop client and phoenix to annotate which properties are requestted, see below cases
case "fileid": // phoenix only
if md.Id != nil {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:fileid", resourceid.OwnCloudResourceIDWrap(md.Id)))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:fileid", resourceid.OwnCloudResourceIDWrap(md.Id)))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:fileid", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:fileid"))
}
case "id": // desktop client only
if md.Id != nil {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:id", resourceid.OwnCloudResourceIDWrap(md.Id)))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:id", resourceid.OwnCloudResourceIDWrap(md.Id)))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:id", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:id"))
}
case "spaceid":
if md.Id != nil {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:spaceid", md.Id.StorageId))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:spaceid", md.Id.StorageId))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:spaceid", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.Escaped("oc:spaceid", ""))
}
case "permissions": // both
// oc:permissions take several char flags to indicate the permissions the user has on this node:
@@ -869,78 +869,78 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
// R = Shareable (Reshare)
// M = Mounted
// in contrast, the ocs:share-permissions further down below indicate clients the maximum permissions that can be granted
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:permissions", wdp))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:permissions", wdp))
case "public-link-permission": // only on a share root node
if ls != nil && md.PermissionSet != nil {
propstatOK.Prop = append(
propstatOK.Prop,
- props.NewProp("oc:public-link-permission", strconv.FormatUint(uint64(role.OCSPermissions()), 10)))
+ prop.Escaped("oc:public-link-permission", role.OCSPermissions().String()))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:public-link-permission", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:public-link-permission"))
}
case "public-link-item-type": // only on a share root node
if ls != nil {
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:public-link-item-type", "folder"))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:public-link-item-type", "folder"))
} else {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:public-link-item-type", "file"))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:public-link-item-type", "file"))
// redirectref is another option
}
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:public-link-item-type", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:public-link-item-type"))
}
case "public-link-share-datetime":
if ls != nil && ls.Mtime != nil {
t := utils.TSToTime(ls.Mtime).UTC() // TODO or ctime?
shareTimeString := t.Format(net.RFC1123)
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:public-link-share-datetime", shareTimeString))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:public-link-share-datetime", shareTimeString))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:public-link-share-datetime", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:public-link-share-datetime"))
}
case "public-link-share-owner":
if ls != nil && ls.Owner != nil {
if net.IsCurrentUserOwner(ctx, ls.Owner) {
u := ctxpkg.ContextMustGetUser(ctx)
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:public-link-share-owner", u.Username))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:public-link-share-owner", u.Username))
} else {
u, _ := ctxpkg.ContextGetUser(ctx)
sublog.Error().Interface("share", ls).Interface("user", u).Msg("the current user in the context should be the owner of a public link share")
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:public-link-share-owner", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:public-link-share-owner"))
}
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:public-link-share-owner", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:public-link-share-owner"))
}
case "public-link-expiration":
if ls != nil && ls.Expiration != nil {
t := utils.TSToTime(ls.Expiration).UTC()
expireTimeString := t.Format(net.RFC1123)
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:public-link-expiration", expireTimeString))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:public-link-expiration", expireTimeString))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:public-link-expiration", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:public-link-expiration"))
}
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:public-link-expiration", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:public-link-expiration"))
case "size": // phoenix only
// TODO we cannot find out if md.Size is set or not because ints in go default to 0
// TODO what is the difference to d:quota-used-bytes (which only exists for collections)?
// oc:size is available on files and folders and behaves like d:getcontentlength or d:quota-used-bytes respectively
// The hasPrefix is a workaround to make children of the link root show a size if they have 0 bytes
if ls == nil || strings.HasPrefix(md.Path, "/"+ls.Token+"/") {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:size", size))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:size", size))
} else {
// link share root collection has no size
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:size", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:size"))
}
case "owner-id": // phoenix only
if md.Owner != nil {
if net.IsCurrentUserOwner(ctx, md.Owner) {
u := ctxpkg.ContextMustGetUser(ctx)
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:owner-id", u.Username))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:owner-id", u.Username))
} else {
sublog.Debug().Msg("TODO fetch user username")
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:owner-id", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:owner-id"))
}
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:owner-id", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:owner-id"))
}
case "favorite": // phoenix only
// TODO: can be 0 or 1?, in oc10 it is present or not
@@ -948,17 +948,17 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
// TODO: this boolean favorite property is so horribly wrong ... either it is presont, or it is not ... unless ... it is possible to have a non binary value ... we need to double check
if ls == nil {
if k := md.GetArbitraryMetadata(); k == nil {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:favorite", "0"))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:favorite", "0"))
} else if amd := k.GetMetadata(); amd == nil {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:favorite", "0"))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:favorite", "0"))
} else if v, ok := amd[net.PropOcFavorite]; ok && v != "" {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:favorite", "1"))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:favorite", "1"))
} else {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:favorite", "0"))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:favorite", "0"))
}
} else {
// link share root collection has no favorite
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:favorite", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:favorite"))
}
case "checksums": // desktop ... not really ... the desktop sends the OC-Checksum header
@@ -990,9 +990,9 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
}
if checksums.Len() > 13 {
checksums.WriteString("")
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropRaw("oc:checksums", checksums.String()))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:checksums", checksums.String()))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:checksums", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:checksums"))
}
case "share-types": // desktop
var types strings.Builder
@@ -1011,21 +1011,21 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
}
if types.Len() != 0 {
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropRaw("oc:share-types", types.String()))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:share-types", types.String()))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:"+pf.Prop[i].Local, ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:"+pf.Prop[i].Local))
}
case "owner-display-name": // phoenix only
if md.Owner != nil {
if net.IsCurrentUserOwner(ctx, md.Owner) {
u := ctxpkg.ContextMustGetUser(ctx)
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:owner-display-name", u.DisplayName))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:owner-display-name", u.DisplayName))
} else {
sublog.Debug().Msg("TODO fetch user displayname")
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:owner-display-name", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:owner-display-name"))
}
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:owner-display-name", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:owner-display-name"))
}
case "downloadURL": // desktop
if isPublic && md.Type == provider.ResourceType_RESOURCE_TYPE_FILE {
@@ -1044,9 +1044,9 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
path = sb.String()
}
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:downloadURL", publicURL+baseURI+path))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:downloadURL", publicURL+baseURI+path))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:"+pf.Prop[i].Local, ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:"+pf.Prop[i].Local))
}
case "signature-auth":
if isPublic {
@@ -1061,9 +1061,9 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
sb.WriteString(expiration.Format(time.RFC3339))
sb.WriteString("")
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropRaw("oc:signature-auth", sb.String()))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:signature-auth", sb.String()))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:signature-auth", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:signature-auth"))
}
}
case "privatelink": // phoenix only
@@ -1079,15 +1079,15 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
// TODO(jfd): double check the client behavior with reva on backup restore
fallthrough
default:
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:"+pf.Prop[i].Local, ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:"+pf.Prop[i].Local))
}
case net.NsDav:
switch pf.Prop[i].Local {
case "getetag": // both
if md.Etag != "" {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:getetag", quoteEtag(md.Etag)))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("d:getetag", quoteEtag(md.Etag)))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:getetag", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:getetag"))
}
case "getcontentlength": // both
// see everts stance on this https://stackoverflow.com/a/31621912, he points to http://tools.ietf.org/html/rfc4918#section-15.3
@@ -1096,57 +1096,57 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
// which is not the case ... so we don't return it on collections. owncloud has oc:size for that
// TODO we cannot find out if md.Size is set or not because ints in go default to 0
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:getcontentlength", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:getcontentlength"))
} else {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:getcontentlength", size))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("d:getcontentlength", size))
}
case "resourcetype": // both
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropRaw("d:resourcetype", ""))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("d:resourcetype", ""))
} else {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:resourcetype", ""))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("d:resourcetype", ""))
// redirectref is another option
}
case "getcontenttype": // phoenix
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
// directories have no contenttype
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:getcontenttype", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:getcontenttype"))
} else if md.MimeType != "" {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:getcontenttype", md.MimeType))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("d:getcontenttype", md.MimeType))
}
case "getlastmodified": // both
// TODO we cannot find out if md.Mtime is set or not because ints in go default to 0
if md.Mtime != nil {
t := utils.TSToTime(md.Mtime).UTC()
lastModifiedString := t.Format(net.RFC1123)
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:getlastmodified", lastModifiedString))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("d:getlastmodified", lastModifiedString))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:getlastmodified", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:getlastmodified"))
}
case "quota-used-bytes": // RFC 4331
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
// always returns the current usage,
// in oc10 there seems to be a bug that makes the size in webdav differ from the one in the user properties, not taking shares into account
// in ocis we plan to always mak the quota a property of the storage space
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:quota-used-bytes", size))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("d:quota-used-bytes", size))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:quota-used-bytes", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:quota-used-bytes"))
}
case "quota-available-bytes": // RFC 4331
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
// oc10 returns -3 for unlimited, -2 for unknown, -1 for uncalculated
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:quota-available-bytes", quota))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("d:quota-available-bytes", quota))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:quota-available-bytes", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:quota-available-bytes"))
}
case "lockdiscovery": // http://www.webdav.org/specs/rfc2518.html#PROPERTY_lockdiscovery
if lock == nil {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:lockdiscovery", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:lockdiscovery"))
} else {
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropRaw("d:lockdiscovery", activeLocks(&sublog, lock)))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("d:lockdiscovery", activeLocks(&sublog, lock)))
}
default:
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:"+pf.Prop[i].Local, ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:"+pf.Prop[i].Local))
}
case net.NsOCS:
switch pf.Prop[i].Local {
@@ -1165,21 +1165,21 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
perms &^= conversions.PermissionCreate
perms &^= conversions.PermissionDelete
}
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropNS(pf.Prop[i].Space, pf.Prop[i].Local, strconv.FormatUint(uint64(perms), 10)))
+ propstatOK.Prop = append(propstatOK.Prop, prop.EscapedNS(pf.Prop[i].Space, pf.Prop[i].Local, perms.String()))
}
default:
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:"+pf.Prop[i].Local, ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:"+pf.Prop[i].Local))
}
default:
// handle custom properties
if k := md.GetArbitraryMetadata(); k == nil {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewPropNS(pf.Prop[i].Space, pf.Prop[i].Local, ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFoundNS(pf.Prop[i].Space, pf.Prop[i].Local))
} else if amd := k.GetMetadata(); amd == nil {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewPropNS(pf.Prop[i].Space, pf.Prop[i].Local, ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFoundNS(pf.Prop[i].Space, pf.Prop[i].Local))
} else if v, ok := amd[metadataKeyOf(&pf.Prop[i])]; ok && v != "" {
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropNS(pf.Prop[i].Space, pf.Prop[i].Local, v))
+ propstatOK.Prop = append(propstatOK.Prop, prop.EscapedNS(pf.Prop[i].Space, pf.Prop[i].Local, v))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewPropNS(pf.Prop[i].Space, pf.Prop[i].Local, ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFoundNS(pf.Prop[i].Space, pf.Prop[i].Local))
}
}
}
@@ -1244,13 +1244,13 @@ func activeLocks(log *zerolog.Logger, lock *provider.Lock) string {
if lock.User != nil {
// TODO oc10 uses displayname and email, needs a user lookup
- activelocks.WriteString(props.Escape(lock.User.OpaqueId + "@" + lock.User.Idp))
+ activelocks.WriteString(prop.Escape(lock.User.OpaqueId + "@" + lock.User.Idp))
}
if lock.AppName != "" {
if lock.User != nil {
activelocks.WriteString(" via ")
}
- activelocks.WriteString(props.Escape(lock.AppName))
+ activelocks.WriteString(prop.Escape(lock.AppName))
}
activelocks.WriteString("")
}
@@ -1259,7 +1259,7 @@ func activeLocks(log *zerolog.Logger, lock *provider.Lock) string {
activelocks.WriteString("")
if lock.LockId != "" {
activelocks.WriteString("")
- activelocks.WriteString(props.Escape(lock.LockId))
+ activelocks.WriteString(prop.Escape(lock.LockId))
activelocks.WriteString("")
}
// lockroot is only used when setting the lock
@@ -1296,7 +1296,7 @@ func metadataKeyOf(n *xml.Name) string {
// properties contain values. Character data between properties is ignored.
func (pn *Props) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
- t, err := props.Next(d)
+ t, err := prop.Next(d)
if err != nil {
return err
}
@@ -1310,7 +1310,7 @@ func (pn *Props) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*/
return nil
case xml.StartElement:
- t, err = props.Next(d)
+ t, err = prop.Next(d)
if err != nil {
return err
}
diff --git a/internal/http/services/owncloud/ocdav/proppatch.go b/internal/http/services/owncloud/ocdav/proppatch.go
index 8d28bb2e13..950ea76abd 100644
--- a/internal/http/services/owncloud/ocdav/proppatch.go
+++ b/internal/http/services/owncloud/ocdav/proppatch.go
@@ -32,8 +32,8 @@ import (
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/errors"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net"
+ "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/prop"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind"
- "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/props"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/spacelookup"
"github.com/cs3org/reva/v2/pkg/appctx"
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
@@ -323,9 +323,9 @@ func (s *svc) formatProppatchResponse(ctx context.Context, acceptedProps []xml.N
}
if len(acceptedProps) > 0 {
- propstatBody := []*props.PropertyXML{}
+ propstatBody := []prop.PropertyXML{}
for i := range acceptedProps {
- propstatBody = append(propstatBody, props.NewPropNS(acceptedProps[i].Space, acceptedProps[i].Local, ""))
+ propstatBody = append(propstatBody, prop.EscapedNS(acceptedProps[i].Space, acceptedProps[i].Local, ""))
}
response.Propstat = append(response.Propstat, propfind.PropstatXML{
Status: "HTTP/1.1 200 OK",
@@ -334,9 +334,9 @@ func (s *svc) formatProppatchResponse(ctx context.Context, acceptedProps []xml.N
}
if len(removedProps) > 0 {
- propstatBody := []*props.PropertyXML{}
+ propstatBody := []prop.PropertyXML{}
for i := range removedProps {
- propstatBody = append(propstatBody, props.NewPropNS(removedProps[i].Space, removedProps[i].Local, ""))
+ propstatBody = append(propstatBody, prop.EscapedNS(removedProps[i].Space, removedProps[i].Local, ""))
}
response.Propstat = append(response.Propstat, propfind.PropstatXML{
Status: "HTTP/1.1 204 No Content",
@@ -386,11 +386,11 @@ type Proppatch struct {
// remove them, it sets them.
Remove bool
// Props contains the properties to be set or removed.
- Props []props.PropertyXML
+ Props []prop.PropertyXML
}
// http://www.webdav.org/specs/rfc4918.html#ELEMENT_prop (for proppatch)
-type proppatchProps []props.PropertyXML
+type proppatchProps []prop.PropertyXML
// UnmarshalXML appends the property names and values enclosed within start
// to ps.
@@ -403,7 +403,7 @@ type proppatchProps []props.PropertyXML
func (ps *proppatchProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
lang := xmlLang(start, "")
for {
- t, err := props.Next(d)
+ t, err := prop.Next(d)
if err != nil {
return err
}
@@ -414,7 +414,7 @@ func (ps *proppatchProps) UnmarshalXML(d *xml.Decoder, start xml.StartElement) e
}
return nil
case xml.StartElement:
- p := props.PropertyXML{}
+ p := prop.PropertyXML{}
err = d.DecodeElement(&p, &elem)
if err != nil {
return err
diff --git a/internal/http/services/owncloud/ocdav/trashbin.go b/internal/http/services/owncloud/ocdav/trashbin.go
index b94ee5f0d7..158acfe6ec 100644
--- a/internal/http/services/owncloud/ocdav/trashbin.go
+++ b/internal/http/services/owncloud/ocdav/trashbin.go
@@ -31,8 +31,8 @@ import (
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/errors"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net"
+ "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/prop"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind"
- "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/props"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/spacelookup"
rtrace "github.com/cs3org/reva/v2/pkg/trace"
"github.com/cs3org/reva/v2/pkg/utils/resourceid"
@@ -299,17 +299,17 @@ func (h *TrashbinHandler) formatTrashPropfind(ctx context.Context, s *svc, space
Propstat: []propfind.PropstatXML{
{
Status: "HTTP/1.1 200 OK",
- Prop: []*props.PropertyXML{
- props.NewPropRaw("d:resourcetype", ""),
+ Prop: []prop.PropertyXML{
+ prop.Raw("d:resourcetype", ""),
},
},
{
Status: "HTTP/1.1 404 Not Found",
- Prop: []*props.PropertyXML{
- props.NewProp("oc:trashbin-original-filename", ""),
- props.NewProp("oc:trashbin-original-location", ""),
- props.NewProp("oc:trashbin-delete-datetime", ""),
- props.NewProp("d:getcontentlength", ""),
+ Prop: []prop.PropertyXML{
+ prop.NotFound("oc:trashbin-original-filename"),
+ prop.NotFound("oc:trashbin-original-location"),
+ prop.NotFound("oc:trashbin-delete-datetime"),
+ prop.NotFound("d:getcontentlength"),
},
},
},
@@ -362,33 +362,33 @@ func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, spaceI
// return all known properties
propstatOK := propfind.PropstatXML{
Status: "HTTP/1.1 200 OK",
- Prop: []*props.PropertyXML{},
+ Prop: []prop.PropertyXML{},
}
// yes this is redundant, can be derived from oc:trashbin-original-location which contains the full path, clients should not fetch it
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:trashbin-original-filename", path.Base(item.Ref.Path)))
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:trashbin-original-location", strings.TrimPrefix(item.Ref.Path, "/")))
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:trashbin-delete-timestamp", strconv.FormatUint(item.DeletionTime.Seconds, 10)))
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:trashbin-delete-datetime", dTime))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:trashbin-original-filename", path.Base(item.Ref.Path)))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:trashbin-original-location", strings.TrimPrefix(item.Ref.Path, "/")))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:trashbin-delete-timestamp", strconv.FormatUint(item.DeletionTime.Seconds, 10)))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:trashbin-delete-datetime", dTime))
if item.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropRaw("d:resourcetype", ""))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("d:resourcetype", ""))
// TODO(jfd): decide if we can and want to list oc:size for folders
} else {
propstatOK.Prop = append(propstatOK.Prop,
- props.NewProp("d:resourcetype", ""),
- props.NewProp("d:getcontentlength", size),
+ prop.Escaped("d:resourcetype", ""),
+ prop.Escaped("d:getcontentlength", size),
)
}
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:spaceid", spaceID))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:spaceid", spaceID))
response.Propstat = append(response.Propstat, propstatOK)
} else {
// otherwise return only the requested properties
propstatOK := propfind.PropstatXML{
Status: "HTTP/1.1 200 OK",
- Prop: []*props.PropertyXML{},
+ Prop: []prop.PropertyXML{},
}
propstatNotFound := propfind.PropstatXML{
Status: "HTTP/1.1 404 Not Found",
- Prop: []*props.PropertyXML{},
+ Prop: []prop.PropertyXML{},
}
for i := range pf.Prop {
switch pf.Prop[i].Space {
@@ -396,52 +396,52 @@ func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, spaceI
switch pf.Prop[i].Local {
case "oc:size":
if item.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:getcontentlength", size))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("d:getcontentlength", size))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:size", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:size"))
}
case "trashbin-original-filename":
// yes this is redundant, can be derived from oc:trashbin-original-location which contains the full path, clients should not fetch it
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:trashbin-original-filename", path.Base(item.Ref.Path)))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:trashbin-original-filename", path.Base(item.Ref.Path)))
case "trashbin-original-location":
// TODO (jfd) double check and clarify the cs3 spec what the Key is about and if Path is only the folder that contains the file or if it includes the filename
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:trashbin-original-location", strings.TrimPrefix(item.Ref.Path, "/")))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:trashbin-original-location", strings.TrimPrefix(item.Ref.Path, "/")))
case "trashbin-delete-datetime":
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:trashbin-delete-datetime", dTime))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:trashbin-delete-datetime", dTime))
case "trashbin-delete-timestamp":
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:trashbin-delete-timestamp", strconv.FormatUint(item.DeletionTime.Seconds, 10)))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:trashbin-delete-timestamp", strconv.FormatUint(item.DeletionTime.Seconds, 10)))
case "spaceid":
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("oc:spaceid", spaceID))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:spaceid", spaceID))
default:
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("oc:"+pf.Prop[i].Local, ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:"+pf.Prop[i].Local))
}
case net.NsDav:
switch pf.Prop[i].Local {
case "getcontentlength":
if item.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:getcontentlength", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:getcontentlength"))
} else {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:getcontentlength", size))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("d:getcontentlength", size))
}
case "resourcetype":
if item.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
- propstatOK.Prop = append(propstatOK.Prop, props.NewPropRaw("d:resourcetype", ""))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("d:resourcetype", ""))
} else {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:resourcetype", ""))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("d:resourcetype", ""))
// redirectref is another option
}
case "getcontenttype":
if item.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
- propstatOK.Prop = append(propstatOK.Prop, props.NewProp("d:getcontenttype", "httpd/unix-directory"))
+ propstatOK.Prop = append(propstatOK.Prop, prop.Raw("d:getcontenttype", "httpd/unix-directory"))
} else {
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:getcontenttype", ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:getcontenttype"))
}
default:
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp("d:"+pf.Prop[i].Local, ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("d:"+pf.Prop[i].Local))
}
default:
// TODO (jfd) lookup shortname for unknown namespaces?
- propstatNotFound.Prop = append(propstatNotFound.Prop, props.NewProp(pf.Prop[i].Space+":"+pf.Prop[i].Local, ""))
+ propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound(pf.Prop[i].Space+":"+pf.Prop[i].Local))
}
}
response.Propstat = append(response.Propstat, propstatOK, propstatNotFound)
diff --git a/internal/http/services/owncloud/ocs/conversions/permissions.go b/internal/http/services/owncloud/ocs/conversions/permissions.go
index b3cc3a2eb4..bc2f86e0e5 100644
--- a/internal/http/services/owncloud/ocs/conversions/permissions.go
+++ b/internal/http/services/owncloud/ocs/conversions/permissions.go
@@ -20,6 +20,7 @@ package conversions
import (
"fmt"
+ "strconv"
)
// Permissions reflects the CRUD permissions used in the OCS sharing API
@@ -62,3 +63,7 @@ func NewPermissions(val int) (Permissions, error) {
func (p Permissions) Contain(other Permissions) bool {
return p&other == other
}
+
+func (p Permissions) String() string {
+ return strconv.FormatUint(uint64(p), 10)
+}