On second thought: "Errors should never pass silently", so barf when a
string contains control chars that are illegal for XML
This commit is contained in:
parent
48ecaccf9e
commit
2dae7646c3
|
@ -200,18 +200,21 @@ def _dateToString(d):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Regex to strip all control chars, but for \t \n and \r
|
# Regex to find any control chars, except for \t \n and \r
|
||||||
_controlStripper = re.compile(
|
_controlCharPat = re.compile(
|
||||||
r"[\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f"
|
r"[\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c\x0e\x0f"
|
||||||
r"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]")
|
r"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f]")
|
||||||
|
|
||||||
def _escapeAndEncode(text):
|
def _escapeAndEncode(text):
|
||||||
|
m = _controlCharPat.search(text)
|
||||||
|
if m is not None:
|
||||||
|
raise ValueError("strings can't contains control characters; "
|
||||||
|
"use plistlib.Data instead")
|
||||||
text = text.replace("\r\n", "\n") # convert DOS line endings
|
text = text.replace("\r\n", "\n") # convert DOS line endings
|
||||||
text = text.replace("\r", "\n") # convert Mac line endings
|
text = text.replace("\r", "\n") # convert Mac line endings
|
||||||
text = text.replace("&", "&") # escape '&'
|
text = text.replace("&", "&") # escape '&'
|
||||||
text = text.replace("<", "<") # escape '<'
|
text = text.replace("<", "<") # escape '<'
|
||||||
text = text.replace(">", ">") # escape '>'
|
text = text.replace(">", ">") # escape '>'
|
||||||
text = _controlStripper.sub("?", text) # replace control chars with '?'
|
|
||||||
return text.encode("utf-8") # encode as UTF-8
|
return text.encode("utf-8") # encode as UTF-8
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -165,13 +165,16 @@ class TestPlistlib(unittest.TestCase):
|
||||||
self.assertEqual(dict(pl), dict(pl2))
|
self.assertEqual(dict(pl), dict(pl2))
|
||||||
|
|
||||||
def test_controlcharacters(self):
|
def test_controlcharacters(self):
|
||||||
# chars in the range 0..31 are replaced by '?', except for
|
for i in range(128):
|
||||||
# \r, \n and \t since they aren't legal XML characters
|
c = chr(i)
|
||||||
testString = "".join([chr(i) for i in range(32)])
|
testString = "string containing %s" % c
|
||||||
expectedResult = '?????????\t\n??\n??????????????????'
|
if i >= 32 or c in "\r\n\t":
|
||||||
xml = plistlib.writePlistToString(testString)
|
# \r, \n and \t are the only legal control chars in XML
|
||||||
result = plistlib.readPlistFromString(xml)
|
plistlib.writePlistToString(testString)
|
||||||
self.assertEqual(result, expectedResult)
|
else:
|
||||||
|
self.assertRaises(ValueError,
|
||||||
|
plistlib.writePlistToString,
|
||||||
|
testString)
|
||||||
|
|
||||||
def test_nondictroot(self):
|
def test_nondictroot(self):
|
||||||
test1 = "abc"
|
test1 = "abc"
|
||||||
|
|
Loading…
Reference in New Issue