aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2023-05-25 20:59:43 +0200
committerDaniel Schadt <kingdread@gmx.de>2023-05-25 20:59:43 +0200
commite1aa29d92094aafe5109c9fb42e9146bc25ce380 (patch)
tree11ba8efb4faf39691e7de46ab9fe593c351d112e
parentcd60935d777aee984224844badc7f260caa3bb46 (diff)
downloadfietsboek-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 &amp;. It is a quick workaround, not a proper fix, but at least it makes BRouter exports working.
-rw-r--r--fietsboek/actions.py2
-rw-r--r--fietsboek/data.py10
-rw-r--r--fietsboek/util.py23
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