diff options
author | Daniel Schadt <kingdread@gmx.de> | 2023-05-25 20:59:43 +0200 |
---|---|---|
committer | Daniel Schadt <kingdread@gmx.de> | 2023-05-25 20:59:43 +0200 |
commit | e1aa29d92094aafe5109c9fb42e9146bc25ce380 (patch) | |
tree | 11ba8efb4faf39691e7de46ab9fe593c351d112e | |
parent | cd60935d777aee984224844badc7f260caa3bb46 (diff) | |
download | fietsboek-e1aa29d92094aafe5109c9fb42e9146bc25ce380.tar.gz fietsboek-e1aa29d92094aafe5109c9fb42e9146bc25ce380.tar.bz2 fietsboek-e1aa29d92094aafe5109c9fb42e9146bc25ce380.zip |
html-encode the link when saving GPX files
This fixes links that contain ampersands by encoding them as &. It
is a quick workaround, not a proper fix, but at least it makes BRouter
exports working.
-rw-r--r-- | fietsboek/actions.py | 2 | ||||
-rw-r--r-- | fietsboek/data.py | 10 | ||||
-rw-r--r-- | fietsboek/util.py | 23 |
3 files changed, 26 insertions, 9 deletions
diff --git a/fietsboek/actions.py b/fietsboek/actions.py index 6afbfa4..b9221c3 100644 --- a/fietsboek/actions.py +++ b/fietsboek/actions.py @@ -208,7 +208,7 @@ def execute_transformers(request: Request, track: models.Track) -> Optional[gpxp transformer.execute(gpx) LOGGER.debug("Saving transformed file for %d", track.id) - manager.compress_gpx(gpx.to_xml().encode("utf-8")) + manager.compress_gpx(util.encode_gpx(gpx)) LOGGER.debug("Saving new transformers on %d", track.id) track.transformers = serialized diff --git a/fietsboek/data.py b/fietsboek/data.py index 7457986..debddf1 100644 --- a/fietsboek/data.py +++ b/fietsboek/data.py @@ -16,7 +16,7 @@ import brotli import gpxpy from filelock import FileLock -from .util import secure_filename +from . import util LOGGER = logging.getLogger(__name__) @@ -31,7 +31,7 @@ def generate_filename(filename: Optional[str]) -> str: :return: The generated filename. """ if filename: - good_name = secure_filename(filename) + good_name = util.secure_filename(filename) if good_name: random_prefix = "".join(random.choice(string.ascii_lowercase) for _ in range(5)) return f"{random_prefix}_{good_name}" @@ -313,7 +313,7 @@ class TrackDataDir: gpx.description = description gpx.time = time - self.compress_gpx(gpx.to_xml().encode("utf-8")) + self.compress_gpx(util.encode_gpx(gpx)) def backup(self): """Create a backup of the GPX file.""" @@ -345,7 +345,7 @@ class TrackDataDir: :param image_id: ID of the image. :return: A path pointing to the requested image. """ - image = self.path / "images" / secure_filename(image_id) + image = self.path / "images" / util.secure_filename(image_id) if not image.exists(): raise FileNotFoundError("The requested image does not exist") return image @@ -377,7 +377,7 @@ class TrackDataDir: :param image_id: ID of the image. """ # Be sure to not delete anything else than the image file - image_id = secure_filename(image_id) + image_id = util.secure_filename(image_id) if "/" in image_id or "\\" in image_id: return path = self.image_path(image_id) diff --git a/fietsboek/util.py b/fietsboek/util.py index a296151..199baab 100644 --- a/fietsboek/util.py +++ b/fietsboek/util.py @@ -1,5 +1,6 @@ """Various utility functions.""" import datetime +import html import importlib.resources import os import re @@ -65,9 +66,9 @@ def safe_markdown(md_source: str) -> Markup: :param md_source: The markdown source. :return: The safe HTML transformed version. """ - html = markdown.markdown(md_source, output_format="html") - html = nh3.clean(html, tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRIBUTES) - return Markup(html) + converted = markdown.markdown(md_source, output_format="html") + converted = nh3.clean(converted, tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRIBUTES) + return Markup(converted) def fix_iso_timestamp(timestamp: str) -> str: @@ -354,6 +355,22 @@ def tile_url(request: Request, route_name: str, **kwargs: str) -> str: return route.replace("__x__", "{x}").replace("__y__", "{y}").replace("__z__", "{z}") +def encode_gpx(gpx: gpxpy.gpx.GPX) -> bytes: + """Encodes a GPX in-memory representation to the XML representation. + + This ensures that the resulting XML file is valid. + + Returns the contents of the XML as bytes, ready to be written to disk. + + :param gpx: The GPX file to encode. Might be modified! + :return: The encoded GPX content. + """ + for track in gpx.tracks: + if track.link: + track.link = html.escape(track.link) + return gpx.to_xml().encode("utf-8") + + def secure_filename(filename: str) -> str: r"""Pass it a filename and it will return a secure version of it. This filename can then safely be stored on a regular file system and passed |