Skip to content

SR-10759: Avoid double encoding in stringValue of XMLNode. #2330

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions Foundation/XMLNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -372,27 +372,33 @@ open class XMLNode: NSObject, NSCopying {
case .namespace:
return _CFXMLNamespaceCopyValue(_xmlNode)?._swiftObject

case .element:
// As with Darwin, children's string values are just concanated without spaces.
return children?.compactMap({ $0.stringValue }).joined() ?? ""

default:
return _CFXMLNodeCopyContent(_xmlNode)?._swiftObject
}
}
set {
if case .namespace = kind {
switch kind {
case .namespace:
if let newValue = newValue {
precondition(URL(string: newValue) != nil, "namespace stringValue must be a valid href")
}

_CFXMLNamespaceSetValue(_xmlNode, newValue, Int64(newValue?.utf8.count ?? 0))
return
}

_removeAllChildNodesExceptAttributes() // in case anyone is holding a reference to any of these children we're about to destroy
case .comment, .text:
_CFXMLNodeSetContent(_xmlNode, newValue)

if let string = newValue {
let newContent = _CFXMLEncodeEntities(_CFXMLNodeGetDocument(_xmlNode), string)?._swiftObject ?? ""
_CFXMLNodeSetContent(_xmlNode, newContent)
} else {
_CFXMLNodeSetContent(_xmlNode, nil)
default:
_removeAllChildNodesExceptAttributes() // in case anyone is holding a reference to any of these children we're about to destroy
if let string = newValue {
let newContent = _CFXMLEncodeEntities(_CFXMLNodeGetDocument(_xmlNode), string)?._swiftObject ?? ""
_CFXMLNodeSetContent(_xmlNode, newContent)
} else {
_CFXMLNodeSetContent(_xmlNode, nil)
}
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions TestFoundation/TestXMLDocument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,26 @@ class TestXMLDocument : LoopbackServerTest {
func test_stringValue() {
let element = XMLElement(name: "root")
let foo = XMLElement(name: "foo")
let text = XMLNode.text(withStringValue:"<text>") as! XMLNode
let comment = XMLNode.comment(withStringValue:"<comment>") as! XMLNode
foo.addChild(text)
foo.addChild(comment)
element.addChild(foo)

XCTAssertEqual(text.stringValue, "<text>")
XCTAssertEqual(comment.stringValue, "<comment>")
XCTAssertEqual(foo.stringValue, "<text><comment>") // Same with Darwin
XCTAssertEqual(element.stringValue, "<text><comment>") // Same with Darwin

// Confirm that SR-10759 is resolved.
// https://bugs.swift.org/browse/SR-10759
text.stringValue = "<modified text>"
comment.stringValue = "<modified comment>"
XCTAssertEqual(text.stringValue, "<modified text>")
XCTAssertEqual(comment.stringValue, "<modified comment>")

XCTAssertEqual(element.stringValue, "<modified text><modified comment>")
XCTAssertEqual(element.xmlString, "<root><foo>&lt;modified text&gt;<!--<modified comment>--></foo></root>")

element.stringValue = "Hello!<evil/>"
XCTAssertEqual(element.xmlString, "<root>Hello!&lt;evil/&gt;</root>")
Expand Down