Skip to content

Commit

Permalink
Improved validating android package names
Browse files Browse the repository at this point in the history
  • Loading branch information
grzesiek2010 committed Oct 3, 2023
1 parent af0764c commit 524f2b7
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 8 deletions.
34 changes: 34 additions & 0 deletions pyxform/validators/pyxform/android_package_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
def validate_android_package_name(name: str) -> str | None:
prefix = "Invalid Android package name - "

if not name.strip():
return f"{prefix}package name is missing."

if "." not in name:
return f"{prefix}the package name must have at least one '.' separator."

front = True

for i in range(len(name)):
c = name[i]

if ("a" <= c <= "z") or ("A" <= c <= "Z"):
front = False
continue

if ("0" <= c <= "9") or c == "_":
if not front:
continue
else:
if c == "_":
return f"{prefix}the character '_' cannot be the first character in a package name segment."
else:
return f"{prefix}a digit cannot be the first character in a package name segment."

if c == ".":
front = True
continue

return f"{prefix}the character '{c}' is not allowed in Android application package names."

return None
11 changes: 5 additions & 6 deletions pyxform/xls2json.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from pyxform.errors import PyXFormError
from pyxform.utils import PYXFORM_REFERENCE_REGEX, default_is_dynamic
from pyxform.validators.pyxform import parameters_generic, select_from_file_params
from pyxform.validators.pyxform.android_package_name import validate_android_package_name
from pyxform.validators.pyxform.translations_checks import SheetTranslations
from pyxform.xls2json_backends import csv_to_dict, xls_to_dict, xlsx_to_dict
from pyxform.xlsparseutils import find_sheet_misspellings, is_valid_xml_tag
Expand Down Expand Up @@ -1334,17 +1335,15 @@ def workbook_to_json(
if "app" in parameters.keys():
appearance = row.get("control", {}).get("appearance")
if appearance is None or appearance == "annotate":
android_package_regex_pattern = (
"^[a-z][a-z0-9_]*(\.[a-z0-9_]+)+[0-9a-z_]$"
)
app_package_name = str(parameters["app"])
if re.fullmatch(android_package_regex_pattern, app_package_name):
validation_result = validate_android_package_name(app_package_name)
if validation_result is None:
new_dict["control"] = new_dict.get("control", {})
new_dict["control"].update({"intent": app_package_name})
else:
aaa = (ROW_FORMAT_STRING % row_number) + " " + validation_result
raise PyXFormError(
(ROW_FORMAT_STRING % row_number)
+ " Invalid Android package name format."
(ROW_FORMAT_STRING % row_number) + " " + validation_result
)

parent_children_array.append(new_dict)
Expand Down
26 changes: 24 additions & 2 deletions tests/test_image_app_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""
from tests.pyxform_test_case import PyxformTestCase


class TestImageAppParameter(PyxformTestCase):
def test_adding_valid_android_package_name_in_image_with_supported_appearances(self):
appearances = ("", "annotate")
Expand All @@ -22,19 +23,40 @@ def test_adding_valid_android_package_name_in_image_with_supported_appearances(s
],
)

def test_throwing_error_when_invalid_android_package_name_is_used(self):
def test_throwing_error_when_invalid_android_package_name_is_used_with_supported_appearances(
self,
):
appearances = ("", "annotate")
md = """
| survey | | | | | |
| | type | name | label | parameters | appearance |
| | image | my_image | Image | app=something | {case} |
"""
error__contains = (["[row = 2] Invalid Android package name format"],)
for case in appearances:
with self.subTest(msg=case):
self.assertPyxformXform(
name="data",
errored=True,
error__contains="[row : 2] Invalid Android package name - the package name must have at least one '.' separator.",
md=md.format(case=case),
xml__xpath_match=[
"/h:html/h:body/x:upload[not(@intent) and @mediatype='image/*' and @ref='/data/my_image']"
],
)

def test_ignoring_invalid_android_package_name_is_used_with_not_supported_appearances(
self,
):
appearances = ("signature", "draw", "new-front")
md = """
| survey | | | | | |
| | type | name | label | parameters | appearance |
| | image | my_image | Image | app=something | {case} |
"""
for case in appearances:
with self.subTest(msg=case):
self.assertPyxformXform(
name="data",
md=md.format(case=case),
xml__xpath_match=[
"/h:html/h:body/x:upload[not(@intent) and @mediatype='image/*' and @ref='/data/my_image']"
Expand Down
66 changes: 66 additions & 0 deletions tests/validators/pyxform/test_android_package_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from pyxform.validators.pyxform.android_package_name import validate_android_package_name
from tests.pyxform_test_case import PyxformTestCase


class TestAndroidPackageNameValidator(PyxformTestCase):
def test_empty_package_name(self):
result = validate_android_package_name("")
self.assertEqual(
result, "Invalid Android package name - package name is missing."
)

def test_blank_package_name(self):
result = validate_android_package_name(" ")
self.assertEqual(
result, "Invalid Android package name - package name is missing."
)

def test_missing_separator(self):
result = validate_android_package_name("comexampleapp")
self.assertEqual(
result,
"Invalid Android package name - the package name must have at least one '.' separator.",
)

def test_invalid_start_with_underscore(self):
result = validate_android_package_name("_com.example.app")
expected_error = "Invalid Android package name - the character '_' cannot be the first character in a package name segment."
self.assertEqual(result, expected_error)

def test_invalid_start_with_digit(self):
result = validate_android_package_name("1com.example.app")
expected_error = "Invalid Android package name - a digit cannot be the first character in a package name segment."
self.assertEqual(result, expected_error)

def test_invalid_character(self):
result = validate_android_package_name("com.example.app$")
expected_error = "Invalid Android package name - the character '$' is not allowed in Android application package names."
self.assertEqual(result, expected_error)

def test_valid_package_name(self):
package_names = (
"com.zenstudios.zenpinball",
"com.kiloo.subwaysurf",
"jp.mixi.monsterstrike",
"com.outfit7.talkingtom",
"com.supercell.clashofclans",
"com.bandainamcoent.narutoblazingna",
"com.zeptolab.ctr2.f2p.google",
"com.etermax.preguntados.lite",
"com.nianticlabs.pokemongo",
"com.king.candycrushsaga",
"com.ea.game.pvzfree_row",
"com.rovio.angrybirdsspace.premium",
"com.squareenixmontreal.lcgo",
"com.nintendo.zara",
"com.nway.powerrangerslegacywars",
"com.mojang.minecraftpe",
"com.tencent.ig",
"com.ubisoft.hungrysharkworld",
"com.ea.games.simsfreeplay_na",
"com.bethsoft.falloutshelter",
)

for case in package_names:
result = validate_android_package_name(case)
self.assertIsNone(result)

0 comments on commit 524f2b7

Please sign in to comment.