Skip to content

Commit

Permalink
Merge pull request #2287 from uktrade/LTD-5730-eu-xml-bad-chars
Browse files Browse the repository at this point in the history
LTD-5730-eu-xml-bad-chars
  • Loading branch information
depsiatwal authored Jan 7, 2025
2 parents a8a9a87 + e32f790 commit f20b5fd
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
6 changes: 6 additions & 0 deletions core/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,9 @@ def stream_document_response(api_response):
]:
response.headers[header_to_copy] = api_response.headers[header_to_copy]
return response


def remove_non_printable_characters(str):
# Given a string this will remove all non_printable_characters from ascii table
# Chars 9(/h), 10 (/n), 13(/r) are maintained
return "".join([c for c in str if ord(c) > 31 or ord(c) in [9, 10, 13]])
9 changes: 9 additions & 0 deletions exporter/applications/forms/parties.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from core.helpers import remove_non_printable_characters
from crispy_forms_gds.choices import Choice
from crispy_forms_gds.helper import FormHelper
from crispy_forms_gds.layout import Layout, Submit, HTML
Expand Down Expand Up @@ -225,6 +226,10 @@ class PartyNameForm(BaseForm):
],
)

def clean_name(self):
name = self.cleaned_data["name"]
return remove_non_printable_characters(name)

def get_layout_fields(self):
return ("name",)

Expand Down Expand Up @@ -315,6 +320,10 @@ def __init__(self, *args, **kwargs):
country_choices = [(country["id"], country["name"]) for country in countries]
self.fields["country"].choices += country_choices

def clean_address(self):
address = self.cleaned_data["address"]
return remove_non_printable_characters(address)

def get_layout_fields(self):
return (
"address",
Expand Down
45 changes: 45 additions & 0 deletions unit_tests/exporter/applications/forms/test_parties.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,26 @@ def test_consignee_name_form(data, valid, errors):
assert form.errors == errors


@pytest.mark.parametrize(
"data, expected",
(
({"name": "\x02 test1"}, " test1"),
({"name": "\x02test2"}, "test2"),
({"name": "this is \n test3"}, "this is \n test3"),
({"name": "this is \t test4"}, "this is \t test4"),
({"name": "this is \r test5"}, "this is \r test5"),
({"name": "namé 6"}, "namé 6"),
({"name": "namé's"}, "namé's"),
({"name": "test 8"}, "test 8"),
),
)
def test_consignee_name_removes_non_printable(data, expected):
form = parties.ConsigneeNameForm(data=data)

form.is_valid()
assert form.cleaned_data["name"] == expected


@pytest.mark.parametrize(
"data, valid, errors",
(
Expand Down Expand Up @@ -186,6 +206,31 @@ class Request:
assert form.errors == errors


@pytest.mark.parametrize(
"data, expected",
(
({"address": "1 somewhere", "country": "aus"}, "1 somewhere"),
({"address": "1 \x02 somewhere", "country": "aus"}, "1 somewhere"),
({"address": "1 \x02 \n somewhere's", "country": "aus"}, "1 \n somewhere's"),
({"address": "1 \x01somewhere", "country": "aus"}, "somewhere"),
({"address": "1 \x03 \n somewhere", "country": "aus"}, "1 somewhere"),
({"address": "1 \x03 \n ô somewhere", "country": "aus"}, "1 ô somewhere"),
({"address": "1 \x02 \r somewhere's", "country": "aus"}, "1 \r somewhere's"),
({"address": "1 \x02 \t somewhere's", "country": "aus"}, "1 \t somewhere's"),
),
)
@patch("exporter.applications.forms.parties.get_countries")
def test_end_user_address_removes_non_printable(mock_get_countries, data, expected):
class Request:
csp_nonce = "test"

request = Request()
mock_get_countries.return_value = [{"id": "aus", "name": "Austria"}, {"id": "fr", "name": "France"}]
form = parties.EndUserAddressForm(request=request, data=data)

form.is_valid()


@pytest.mark.parametrize(
"data, valid, errors",
(
Expand Down

0 comments on commit f20b5fd

Please sign in to comment.