diff options
-rw-r--r-- | gemato/manifest.py | 22 | ||||
-rw-r--r-- | tests/test_manifest.py | 71 |
2 files changed, 64 insertions, 29 deletions
diff --git a/gemato/manifest.py b/gemato/manifest.py index 2739af4..0480c4a 100644 --- a/gemato/manifest.py +++ b/gemato/manifest.py @@ -59,9 +59,6 @@ class ManifestPathEntry(object): def __init__(self, path): assert path[0] != '/' - m = self.disallowed_path_re.search(path) - if m is not None: - raise gemato.exceptions.ManifestInvalidFilename(path, m.start()) self.path = path @staticmethod @@ -74,6 +71,21 @@ class ManifestPathEntry(object): '{} line: expected relative path, got: {}'.format(l[0], l[1:])) return l[1] + @staticmethod + def encode_char(m): + assert len(m.group(0)) == 1 + cp = ord(m.group(0)) + if cp <= 0x7F: + return '\\x{:02X}'.format(cp) + elif cp <= 0xFFFF: + return '\\u{:04X}'.format(cp) + else: + return '\\U{:08X}'.format(cp) + + @property + def encoded_path(self): + return self.disallowed_path_re.sub(self.encode_char, self.path) + def __eq__(self, other): return self.tag == other.tag and self.path == other.path @@ -95,7 +107,7 @@ class ManifestEntryIGNORE(ManifestPathEntry): return cls(cls.process_path(l)) def to_list(self): - return (self.tag, self.path) + return (self.tag, self.encoded_path) class ManifestFileEntry(ManifestPathEntry): @@ -141,7 +153,7 @@ class ManifestFileEntry(ManifestPathEntry): return size, checksums def to_list(self, tag): - ret = [tag, self.path, str(self.size)] + ret = [tag, self.encoded_path, str(self.size)] for k, v in sorted(self.checksums.items()): ret += [k, v] return ret diff --git a/tests/test_manifest.py b/tests/test_manifest.py index d9d8c08..6351dce 100644 --- a/tests/test_manifest.py +++ b/tests/test_manifest.py @@ -424,27 +424,50 @@ class NewManifestEntryTest(unittest.TestCase): 'test', 32, {}), gemato.manifest.ManifestEntryAUX) - def test_space_in_filename(self): - self.assertRaises(gemato.exceptions.ManifestInvalidFilename, - gemato.manifest.new_manifest_entry, 'DATA', - 'tes t', 32, {}), - - def test_tab_in_filename(self): - self.assertRaises(gemato.exceptions.ManifestInvalidFilename, - gemato.manifest.new_manifest_entry, 'DATA', - 'tes\tt', 32, {}), - - def test_nbsp_in_filename(self): - self.assertRaises(gemato.exceptions.ManifestInvalidFilename, - gemato.manifest.new_manifest_entry, 'DATA', - u'tes\u00a0t', 32, {}), - - def test_null_in_filename(self): - self.assertRaises(gemato.exceptions.ManifestInvalidFilename, - gemato.manifest.new_manifest_entry, 'DATA', - u'tes\0t', 32, {}), - - def test_backslash_in_filename(self): - self.assertRaises(gemato.exceptions.ManifestInvalidFilename, - gemato.manifest.new_manifest_entry, 'DATA', - u'tes\\t', 32, {}), + +class ManifestPathEncodingTest(unittest.TestCase): + """ + Tests for path encoding. + """ + + def test_encode_space_in_filename(self): + m = gemato.manifest.new_manifest_entry('DATA', + 'tes t', 32, {}) + self.assertEqual(m.path, 'tes t') + self.assertListEqual(list(m.to_list()), + ['DATA', 'tes\\x20t', '32']) + + def test_encode_tab_in_filename(self): + m = gemato.manifest.new_manifest_entry('DATA', + 'tes\tt', 32, {}) + self.assertEqual(m.path, 'tes\tt') + self.assertListEqual(list(m.to_list()), + ['DATA', 'tes\\x09t', '32']) + + def test_encode_nbsp_in_filename(self): + m = gemato.manifest.new_manifest_entry('DATA', + 'tes\u00a0t', 32, {}) + self.assertEqual(m.path, 'tes\u00a0t') + self.assertListEqual(list(m.to_list()), + ['DATA', 'tes\\u00A0t', '32']) + + def test_encode_en_quad_in_filename(self): + m = gemato.manifest.new_manifest_entry('DATA', + 'tes\u2000t', 32, {}) + self.assertEqual(m.path, 'tes\u2000t') + self.assertListEqual(list(m.to_list()), + ['DATA', 'tes\\u2000t', '32']) + + def test_encode_null_in_filename(self): + m = gemato.manifest.new_manifest_entry('DATA', + 'tes\x00t', 32, {}) + self.assertEqual(m.path, 'tes\x00t') + self.assertListEqual(list(m.to_list()), + ['DATA', 'tes\\x00t', '32']) + + def test_encode_backslash_in_filename(self): + m = gemato.manifest.new_manifest_entry('DATA', + 'tes\\t', 32, {}) + self.assertEqual(m.path, 'tes\\t') + self.assertListEqual(list(m.to_list()), + ['DATA', 'tes\\x5Ct', '32']) |