1
mirror of https://github.com/home-assistant/core synced 2024-07-27 18:58:57 +02:00

Add check for HTML in translations (#35615)

* Add check for HTML in translations

and remove existing html

* Add test
This commit is contained in:
Bram Kragten 2020-05-14 19:33:14 +02:00 committed by GitHub
parent a42a654590
commit cb7b8d94c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 47 additions and 18 deletions

View File

@ -3,7 +3,7 @@
"step": {
"auth": {
"title": "Authenticate Ambiclimate",
"description": "Please follow this [link]({authorization_url}) and <b>Allow</b> access to your Ambiclimate account, then come back and press <b>Submit</b> below.\n(Make sure the specified callback url is {cb_url})"
"description": "Please follow this [link]({authorization_url}) and **Allow** access to your Ambiclimate account, then come back and press **Submit** below.\n(Make sure the specified callback url is {cb_url})"
}
},
"create_entry": {

View File

@ -8,7 +8,7 @@
},
"auth": {
"title": "Authenticate with Logi Circle",
"description": "Please follow the link below and <b>Accept</b> access to your Logi Circle account, then come back and press <b>Submit</b> below.\n\n[Link]({authorization_url})"
"description": "Please follow the link below and **Accept** access to your Logi Circle account, then come back and press **Submit** below.\n\n[Link]({authorization_url})"
}
},
"create_entry": {

View File

@ -8,7 +8,7 @@
},
"auth": {
"title": "Authenticate Point",
"description": "Please follow the link below and <b>Accept</b> access to your Minut account, then come back and press <b>Submit</b> below.\n\n[Link]({authorization_url})"
"description": "Please follow the link below and **Accept** access to your Minut account, then come back and press **Submit** below.\n\n[Link]({authorization_url})"
}
},
"create_entry": {

View File

@ -3,7 +3,7 @@
"step": {
"auth_app": {
"title": "Application credentials",
"description": "Application ID and secret code from <a href=\"https://my.starline.ru/developer\" target=\"_blank\">StarLine developer account</a>",
"description": "Application ID and secret code from [StarLine developer account](https://my.starline.ru/developer)",
"data": {
"app_id": "App ID",
"app_secret": "Secret"

View File

@ -465,6 +465,15 @@ def string(value: Any) -> str:
return str(value)
def string_with_no_html(value: Any) -> str:
"""Validate that the value is a string without HTML."""
value = string(value)
regex = re.compile(r"<[a-z][\s\S]*>")
if regex.search(value):
raise vol.Invalid("the string should not contain HTML")
return str(value)
def temperature_unit(value: Any) -> str:
"""Validate and transform temperature unit."""
value = str(value).upper()

View File

@ -91,20 +91,20 @@ def gen_data_entry_schema(
"""Generate a data entry schema."""
step_title_class = vol.Required if require_step_title else vol.Optional
schema = {
vol.Optional("flow_title"): str,
vol.Optional("flow_title"): cv.string_with_no_html,
vol.Required("step"): {
str: {
step_title_class("title"): str,
vol.Optional("description"): str,
vol.Optional("data"): {str: str},
step_title_class("title"): cv.string_with_no_html,
vol.Optional("description"): cv.string_with_no_html,
vol.Optional("data"): {str: cv.string_with_no_html},
}
},
vol.Optional("error"): {str: str},
vol.Optional("abort"): {str: str},
vol.Optional("create_entry"): {str: str},
vol.Optional("error"): {str: cv.string_with_no_html},
vol.Optional("abort"): {str: cv.string_with_no_html},
vol.Optional("create_entry"): {str: cv.string_with_no_html},
}
if flow_title == REQUIRED:
schema[vol.Required("title")] = str
schema[vol.Required("title")] = cv.string_with_no_html
elif flow_title == REMOVED:
schema[vol.Optional("title", msg=REMOVED_TITLE_MSG)] = partial(
removed_title_validator, config, integration
@ -117,7 +117,7 @@ def gen_strings_schema(config: Config, integration: Integration):
"""Generate a strings schema."""
return vol.Schema(
{
vol.Optional("title"): str,
vol.Optional("title"): cv.string_with_no_html,
vol.Optional("config"): gen_data_entry_schema(
config=config,
integration=integration,
@ -131,10 +131,10 @@ def gen_strings_schema(config: Config, integration: Integration):
require_step_title=False,
),
vol.Optional("device_automation"): {
vol.Optional("action_type"): {str: str},
vol.Optional("condition_type"): {str: str},
vol.Optional("trigger_type"): {str: str},
vol.Optional("trigger_subtype"): {str: str},
vol.Optional("action_type"): {str: cv.string_with_no_html},
vol.Optional("condition_type"): {str: cv.string_with_no_html},
vol.Optional("trigger_type"): {str: cv.string_with_no_html},
vol.Optional("trigger_subtype"): {str: cv.string_with_no_html},
},
vol.Optional("state"): cv.schema_with_slug_keys(
cv.schema_with_slug_keys(str, slug_validator=lowercase_validator),
@ -203,7 +203,7 @@ def gen_platform_strings_schema(config: Config, integration: Integration):
)
ONBOARDING_SCHEMA = vol.Schema({vol.Required("area"): {str: str}})
ONBOARDING_SCHEMA = vol.Schema({vol.Required("area"): {str: cv.string_with_no_html}})
def validate_translation_file(config: Config, integration: Integration, all_strings):

View File

@ -351,6 +351,26 @@ def test_string():
schema(value)
def test_string_with_no_html():
"""Test string with no html validation."""
schema = vol.Schema(cv.string_with_no_html)
with pytest.raises(vol.Invalid):
schema("This has HTML in it <a>Link</a>")
with pytest.raises(vol.Invalid):
schema("<b>Bold</b>")
for value in (
True,
3,
"Hello",
"**Hello**",
"This has no HTML [Link](https://home-assistant.io)",
):
schema(value)
def test_temperature_unit():
"""Test temperature unit validation."""
schema = vol.Schema(cv.temperature_unit)