diff --git a/src/features/route/RoutePopup.jsx b/src/features/route/RoutePopup.jsx index 09cc7b068..f750619a5 100644 --- a/src/features/route/RoutePopup.jsx +++ b/src/features/route/RoutePopup.jsx @@ -388,6 +388,24 @@ export function RoutePopup({ end, inline = false, ...props }) { } function DownloadRouteGPX({ route }) { + const escapeXml = (value = '') => + String(value).replace( + /[<>&'"]/g, + (c) => + ({ + '<': '<', + '>': '>', + '&': '&', + "'": ''', + '"': '"', + })[c], + ) + + const sanitizeFilename = (name = '') => + String(name) + .replace(/[\/:*?"<>|]/g, '') + .slice(0, 200) || 'route' + const GPXContent = React.useMemo(() => { if (!route.waypoints.length) { return null @@ -396,8 +414,8 @@ function DownloadRouteGPX({ route }) { return ` - ${route.name} - ${route.description} + ${escapeXml(route.name)} + ${escapeXml(route.description)} ${route.waypoints .map( (waypoint) => @@ -417,7 +435,7 @@ function DownloadRouteGPX({ route }) { href={`data:application/gpx;charset=utf-8,${encodeURIComponent( GPXContent, )}`} - download={`${route.name}.gpx`} + download={`${sanitizeFilename(route.name)}.gpx`} size="small" style={{ color: 'inherit' }} >