From 9ffc9ac56a29ff8ab8ad27d26e85bf6814169856 Mon Sep 17 00:00:00 2001 From: Aris Katsikaridis Date: Wed, 13 Dec 2023 15:56:36 +0200 Subject: [PATCH] Fix Android XML format special characters escape/ unescape --- openformats/formats/android_unescaped.py | 29 +++++++++ .../tests/formats/android/files/1_el.xml | 3 + .../tests/formats/android/files/1_en.xml | 3 + .../tests/formats/android/files/1_tpl.xml | 3 + .../formats/android/test_android_unescaped.py | 60 +++++++++++++++++++ 5 files changed, 98 insertions(+) create mode 100644 openformats/formats/android_unescaped.py create mode 100644 openformats/tests/formats/android/test_android_unescaped.py diff --git a/openformats/formats/android_unescaped.py b/openformats/formats/android_unescaped.py new file mode 100644 index 00000000..d75e6948 --- /dev/null +++ b/openformats/formats/android_unescaped.py @@ -0,0 +1,29 @@ +from openformats.formats.android import AndroidHandler + + +class AndroidUnescapedHandler(AndroidHandler): + @staticmethod + def escape(string): + string = AndroidHandler.escape(string) + return ( + string.replace("&", "&") + .replace("<", "<") + .replace(">", ">") + .replace("\n", "\\n") + .replace("\t", "\\t") + .replace("@", "\\@") + .replace("?", "\\?") + ) + + @staticmethod + def unescape(string): + string = AndroidHandler.unescape(string) + return ( + string.replace("\\?", "?") + .replace("\\@", "@") + .replace("\\t", "\t") + .replace("\\n", "\n") + .replace(">", ">") + .replace("<", "<") + .replace("&", "&") + ) diff --git a/openformats/tests/formats/android/files/1_el.xml b/openformats/tests/formats/android/files/1_el.xml index 5d967496..5fcb8d2d 100644 --- a/openformats/tests/formats/android/files/1_el.xml +++ b/openformats/tests/formats/android/files/1_el.xml @@ -3,6 +3,9 @@ el:Simple string + + el:Simple string & \"with\" \'special characters\' + el:Simple string with product diff --git a/openformats/tests/formats/android/files/1_en.xml b/openformats/tests/formats/android/files/1_en.xml index bdd85673..0153ed1e 100644 --- a/openformats/tests/formats/android/files/1_en.xml +++ b/openformats/tests/formats/android/files/1_en.xml @@ -3,6 +3,9 @@ Simple string + + Simple string & \"with\" \'special characters\' + Simple string with product diff --git a/openformats/tests/formats/android/files/1_tpl.xml b/openformats/tests/formats/android/files/1_tpl.xml index 6bcf65cc..24ea8e9f 100644 --- a/openformats/tests/formats/android/files/1_tpl.xml +++ b/openformats/tests/formats/android/files/1_tpl.xml @@ -3,6 +3,9 @@ ac2562b9f825de04b7ae4736274b1e5f_tr + + 2cb7c4a9823431f0a9a4efc70603b465_tr + 160db9c24b122af9e0f4218ad732d0ce_tr diff --git a/openformats/tests/formats/android/test_android_unescaped.py b/openformats/tests/formats/android/test_android_unescaped.py new file mode 100644 index 00000000..cb3637bf --- /dev/null +++ b/openformats/tests/formats/android/test_android_unescaped.py @@ -0,0 +1,60 @@ +import unittest +from openformats.formats.android_unescaped import AndroidUnescapedHandler +from openformats.tests.formats.common import CommonFormatTestMixin +from openformats.tests.utils.strings import ( + generate_random_string, + strip_leading_spaces, + bytes_to_string, +) + +from openformats.strings import OpenString + + +class AndroidUnescapedTestCase(CommonFormatTestMixin, unittest.TestCase): + HANDLER_CLASS = AndroidUnescapedHandler + TESTFILE_BASE = "openformats/tests/formats/android/files" + + def setUp(self): + super(AndroidUnescapedTestCase, self).setUp() + self.handler = AndroidUnescapedHandler() + + def test_string(self): + random_key = generate_random_string() + random_string = generate_random_string() + random_openstring = OpenString(random_key, random_string, order=0) + random_hash = random_openstring.template_replacement + + source_python_template = """ + + {string} + + """ + source = source_python_template.format(key=random_key, string=random_string) + + template, stringset = self.handler.parse(source) + compiled = self.handler.compile(template, [random_openstring]) + + self.assertEqual( + template, source_python_template.format(key=random_key, string=random_hash) + ) + self.assertEqual(len(stringset), 1) + self.assertEqual(stringset[0].__dict__, random_openstring.__dict__) + self.assertEqual(compiled, source) + + def test_escape(self): + rich = "&<>'\n\t@?" + '"' + raw = "&<>\\'\\n\\t\\@\\?" + '\\"' + + self.assertEqual( + AndroidUnescapedHandler.escape(rich), + raw, + ) + + def test_unescape(self): + rich = "&<>'\n\t@?" + '"' + raw = "&<>\\'\\n\\t\\@\\?" + '\\"' + + self.assertEqual( + AndroidUnescapedHandler.unescape(raw), + rich, + )