Skip to content

Commit

Permalink
Fix listobjects with metadata
Browse files Browse the repository at this point in the history
`UserMetadata` did not match actual format sent.

Change type of `UserTags`, so it can be unmarshaled from XML string.

Tested with mc.
  • Loading branch information
klauspost committed Mar 30, 2023
1 parent 6fcbe6d commit 88bc3c5
Showing 1 changed file with 62 additions and 8 deletions.
70 changes: 62 additions & 8 deletions api-datatypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"encoding/xml"
"io"
"net/http"
"net/url"
"strings"
"time"
)

Expand All @@ -43,26 +45,78 @@ type StringMap map[string]string
// if m is nil it can be initialized, which is often the case if m is
// nested in another xml structural. This is also why the first thing done
// on the first line is initialize it.
func (m *StringMap) UnmarshalXML(d *xml.Decoder, _ xml.StartElement) error {
func (m *StringMap) UnmarshalXML(d *xml.Decoder, s xml.StartElement) error {
*m = StringMap{}
type Item struct {
Key string
Value string
}
for {
var e Item
// Format is <key>value</key>
var e struct {
XMLName xml.Name
Value string `xml:",chardata"`
}
err := d.Decode(&e)
if err == io.EOF {
break
}
if err != nil {
return err
}
(*m)[e.Key] = e.Value
(*m)[e.XMLName.Local] = e.Value
}
return nil
}

// URLMap represents map with custom UnmarshalXML
type URLMap map[string]string

// UnmarshalXML unmarshals the XML into a map of string to strings,
// creating a key in the map for each tag and setting it's value to the
// tags contents.
//
// The fact this function is on the pointer of Map is important, so that
// if m is nil it can be initialized, which is often the case if m is
// nested in another xml structural. This is also why the first thing done
// on the first line is initialize it.
func (m *URLMap) UnmarshalXML(d *xml.Decoder, se xml.StartElement) error {
*m = URLMap{}
var tgs string
if err := d.DecodeElement(&tgs, &se); err != nil {
if err == io.EOF {
return nil
}
return err
}
for tgs != "" {
var key string
key, tgs, _ = stringsCut(tgs, "&")
if key == "" {
continue
}
key, value, _ := stringsCut(key, "=")
key, err := url.QueryUnescape(key)
if err != nil {
return err
}

value, err = url.QueryUnescape(value)
if err != nil {
return err
}
(*m)[key] = value
}
return nil
}

// stringsCut slices s around the first instance of sep,
// returning the text before and after sep.
// The found result reports whether sep appears in s.
// If sep does not appear in s, cut returns s, "", false.
func stringsCut(s, sep string) (before, after string, found bool) {
if i := strings.Index(s, sep); i >= 0 {
return s[:i], s[i+len(sep):], true
}
return s, "", false
}

// Owner name.
type Owner struct {
XMLName xml.Name `xml:"Owner" json:"owner"`
Expand Down Expand Up @@ -124,7 +178,7 @@ type ObjectInfo struct {
UserMetadata StringMap `json:"userMetadata,omitempty"`

// x-amz-tagging values in their k/v values.
UserTags map[string]string `json:"userTags"`
UserTags URLMap `json:"userTags" xml:"UserTags"`

// x-amz-tagging-count value
UserTagCount int
Expand Down

0 comments on commit 88bc3c5

Please sign in to comment.