Skip to content

Commit

Permalink
private/protocol/xml/xmlutil: Updated XML encoding to ensure line fee…
Browse files Browse the repository at this point in the history
…d is escaped.
  • Loading branch information
skmcgrail committed Apr 26, 2021
1 parent 92c4507 commit e2224a6
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 17 deletions.
6 changes: 6 additions & 0 deletions private/protocol/xml/xmlutil/build_test.go
Expand Up @@ -153,6 +153,12 @@ func TestBuildXML(t *testing.T) {
Input: &namedEmptyPayload{},
Expect: "<namedEmptyPayload></namedEmptyPayload>",
},
"escape line feed and carriage return": {
Input: &implicitPayload{
StrVal: aws.String("this\nstring\rhas\r\nescapable\n\rcharacters"),
},
Expect: "<StrVal>this&#xA;string&#xD;has&#xD;&#xA;escapable&#xA;&#xD;characters</StrVal>",
},
}

for name, c := range cases {
Expand Down
47 changes: 30 additions & 17 deletions private/protocol/xml/xmlutil/xml_to_struct.go
Expand Up @@ -18,6 +18,14 @@ type XMLNode struct {
parent *XMLNode
}

// textEncoder is a string type alias that implemnts the TextMarshaler interface.
// This alias type is used to ensure that the line feed (\n) (U+000A) is escaped.
type textEncoder string

func (t textEncoder) MarshalText() (text []byte, err error) {
return []byte(t), nil
}

// NewXMLElement returns a pointer to a new XMLNode initialized to default values.
func NewXMLElement(name xml.Name) *XMLNode {
return &XMLNode{
Expand Down Expand Up @@ -130,30 +138,35 @@ func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error {
attrs = sortedAttrs
}

e.EncodeToken(xml.StartElement{Name: node.Name, Attr: attrs})
startElement := xml.StartElement{Name: node.Name, Attr: attrs}

if node.Text != "" {
e.EncodeToken(xml.CharData([]byte(node.Text)))
} else if sorted {
sortedNames := []string{}
for k := range node.Children {
sortedNames = append(sortedNames, k)
}
sort.Strings(sortedNames)
e.EncodeElement(textEncoder(node.Text), startElement)
} else {
e.EncodeToken(startElement)

for _, k := range sortedNames {
for _, v := range node.Children[k] {
StructToXML(e, v, sorted)
if sorted {
sortedNames := []string{}
for k := range node.Children {
sortedNames = append(sortedNames, k)
}
}
} else {
for _, c := range node.Children {
for _, v := range c {
StructToXML(e, v, sorted)
sort.Strings(sortedNames)

for _, k := range sortedNames {
for _, v := range node.Children[k] {
StructToXML(e, v, sorted)
}
}
} else {
for _, c := range node.Children {
for _, v := range c {
StructToXML(e, v, sorted)
}
}
}

e.EncodeToken(xml.EndElement{Name: node.Name})
}

e.EncodeToken(xml.EndElement{Name: node.Name})
return e.Flush()
}

0 comments on commit e2224a6

Please sign in to comment.