diff --git a/changelog/unreleased/more-robust-etag-handling.md b/changelog/unreleased/more-robust-etag-handling.md new file mode 100644 index 00000000000..9d54d176e4c --- /dev/null +++ b/changelog/unreleased/more-robust-etag-handling.md @@ -0,0 +1,5 @@ +Enhancement: Be defensive about wrongly quoted etags + +When ocdav renders etags it will now try to correct them to the definition as *quoted strings* which do not contain `"`. This prevents double or triple quoted etags on the webdav api. + +https://github.com/cs3org/reva/pull/1870 diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index 9e71d6b0369..c5279a917e3 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -405,7 +405,7 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide // 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, s.newProp("d:getetag", md.Etag)) + propstatOK.Prop = append(propstatOK.Prop, s.newProp("d:getetag", quoteEtag(md.Etag))) } if md.PermissionSet != nil { @@ -698,7 +698,7 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide switch pf.Prop[i].Local { case "getetag": // both if md.Etag != "" { - propstatOK.Prop = append(propstatOK.Prop, s.newProp("d:getetag", md.Etag)) + propstatOK.Prop = append(propstatOK.Prop, s.newProp("d:getetag", quoteEtag(md.Etag))) } else { propstatNotFound.Prop = append(propstatNotFound.Prop, s.newProp("d:getetag", "")) } @@ -802,6 +802,14 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide return &response, nil } +// be defensive about wrong encoded etags +func quoteEtag(etag string) string { + if strings.HasPrefix(etag, "W/") { + return `W/"` + strings.Trim(etag[2:], `"`) + `"` + } + return `"` + strings.Trim(etag, `"`) + `"` +} + // a file is only yours if you are the owner func isCurrentUserOwner(ctx context.Context, owner *userv1beta1.UserId) bool { contextUser, ok := ctxuser.ContextGetUser(ctx)