From 103835b2c54e9a23451e92841cb23496243cad53 Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Wed, 6 Dec 2023 01:55:14 +0100 Subject: [PATCH 1/2] feat(propfind): add audio and location props --- .../add-audio-and-location-props.md | 5 ++ .../owncloud/ocdav/propfind/propfind.go | 76 ++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 changelog/unreleased/add-audio-and-location-props.md diff --git a/changelog/unreleased/add-audio-and-location-props.md b/changelog/unreleased/add-audio-and-location-props.md new file mode 100644 index 0000000000..3b214ca3aa --- /dev/null +++ b/changelog/unreleased/add-audio-and-location-props.md @@ -0,0 +1,5 @@ +Enhancement: Add audio and location props + +Add `oc:audio` and `oc:location` props to PROPFIND responses for propall requests or when they are explicitly requested. + +https://github.com/cs3org/reva/pull/4389 \ No newline at end of file diff --git a/internal/http/services/owncloud/ocdav/propfind/propfind.go b/internal/http/services/owncloud/ocdav/propfind/propfind.go index 648ded6210..4db5b07214 100644 --- a/internal/http/services/owncloud/ocdav/propfind/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind/propfind.go @@ -64,6 +64,32 @@ const ( tracerName = "ocdav" ) +var ( + audioKeys = []string{ + "album", + "albumArtist", + "artist", + "bitrate", + "composers", + "copyright", + "disc", + "discCount", + "duration", + "genre", + "hasDrm", + "isVariableBitrate", + "title", + "track", + "trackCount", + "year", + } + locationKeys = []string{ + "altitude", + "latitude", + "longitude", + } +) + type countingReader struct { n int r io.Reader @@ -786,6 +812,14 @@ func (p *Handler) getSpaceResourceInfos(ctx context.Context, w http.ResponseWrit return resourceInfos, true } +func metadataKeysWithPrefix(prefix string, keys []string) []string { + fullKeys := []string{} + for _, key := range keys { + fullKeys = append(fullKeys, fmt.Sprintf("%s.%s", prefix, key)) + } + return fullKeys +} + // metadataKeys splits the propfind properties into arbitrary metadata and ResourceInfo field mask paths func metadataKeys(pf XML) ([]string, []string) { @@ -809,6 +843,10 @@ func metadataKeys(pf XML) ([]string, []string) { switch key { case "share-types": fieldMaskKeys = append(fieldMaskKeys, key) + case "http://owncloud.org/ns/audio": + metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.audio", audioKeys)...) + case "http://owncloud.org/ns/location": + metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.location", locationKeys)...) default: metadataKeys = append(metadataKeys, key) } @@ -866,7 +904,7 @@ func requiresExplicitFetching(n *xml.Name) bool { } case net.NsOwncloud: switch n.Local { - case "favorite", "share-types", "checksums", "size", "tags": + case "favorite", "share-types", "checksums", "size", "tags", "audio", "location": return true default: return false @@ -1082,6 +1120,32 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p appendToNotFound = func(p ...prop.PropertyXML) {} } + appendMetadataProp := func(metadata map[string]string, tagNamespace string, name string, metadataPrefix string, keys []string) { + content := strings.Builder{} + for _, key := range keys { + if v, ok := metadata[fmt.Sprintf("%s.%s", metadataPrefix, key)]; ok { + content.WriteString("<") + content.WriteString(tagNamespace) + content.WriteString(":") + content.WriteString(key) + content.WriteString(">") + content.Write(prop.Escaped("", v).InnerXML) + content.WriteString("") + } + } + + propName := fmt.Sprintf("%s:%s", tagNamespace, name) + if content.Len() > 0 { + appendToOK(prop.Raw(propName, content.String())) + } else { + appendToNotFound(prop.NotFound(propName)) + } + } + // when allprops has been requested if pf.Allprop != nil { // return all known properties @@ -1180,6 +1244,8 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p if k := md.GetArbitraryMetadata().GetMetadata(); k != nil { propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:tags", k["tags"])) + appendMetadataProp(k, "oc", "audio", "libre.graph.audio", audioKeys) + appendMetadataProp(k, "oc", "location", "libre.graph.location", locationKeys) } // ls do not report any properties as missing by default @@ -1453,6 +1519,14 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p if k := md.GetArbitraryMetadata().GetMetadata(); k != nil { propstatOK.Prop = append(propstatOK.Prop, prop.Raw("oc:tags", k["tags"])) } + case "audio": + if k := md.GetArbitraryMetadata().GetMetadata(); k != nil { + appendMetadataProp(k, "oc", "audio", "libre.graph.audio", audioKeys) + } + case "location": + if k := md.GetArbitraryMetadata().GetMetadata(); k != nil { + appendMetadataProp(k, "oc", "location", "libre.graph.location", locationKeys) + } case "name": appendToOK(prop.Escaped("oc:name", md.Name)) case "shareid": From 22b5f8a1f41866d8a299932a555ba15c8036b2a6 Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Wed, 6 Dec 2023 13:21:15 +0100 Subject: [PATCH 2/2] fix(propfind): make audio sub props lowercase --- internal/http/services/owncloud/ocdav/propfind/propfind.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/http/services/owncloud/ocdav/propfind/propfind.go b/internal/http/services/owncloud/ocdav/propfind/propfind.go index 4db5b07214..d410bfcba7 100644 --- a/internal/http/services/owncloud/ocdav/propfind/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind/propfind.go @@ -64,6 +64,7 @@ const ( tracerName = "ocdav" ) +// these keys are used to lookup in ArbitraryMetadata, generated prop names are lowercased var ( audioKeys = []string{ "album", @@ -1123,17 +1124,18 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p appendMetadataProp := func(metadata map[string]string, tagNamespace string, name string, metadataPrefix string, keys []string) { content := strings.Builder{} for _, key := range keys { + lowerCaseKey := strings.ToLower(key) if v, ok := metadata[fmt.Sprintf("%s.%s", metadataPrefix, key)]; ok { content.WriteString("<") content.WriteString(tagNamespace) content.WriteString(":") - content.WriteString(key) + content.WriteString(lowerCaseKey) content.WriteString(">") content.Write(prop.Escaped("", v).InnerXML) content.WriteString("") } }