Sanitize filenames of downloads.

Some routes have characters like ":" in them which can be illegal on
certain filesystems. Remove the known common ones and replace them with
an underscore.
This commit is contained in:
Sebastian Hugentobler 2024-06-24 11:07:53 +02:00
parent 59d0f01f87
commit 6e91a15ca7
Signed by: shu
GPG Key ID: BB32CF3CA052C2F0
3 changed files with 67 additions and 24 deletions

View File

@ -1,23 +1,28 @@
# SAC Route Portal GPX Downloader # SAC Route Portal GPX Downloader
The [Swiss Alpine Club](https://www.sac-cas.ch/en/) has a great The [Swiss Alpine Club](https://www.sac-cas.ch/en/) has a great
[route portal](https://www.sac-cas.ch/en/huts-and-tours/sac-route-portal/) [route portal](https://www.sac-cas.ch/en/huts-and-tours/sac-route-portal/) for
for finding interesting hiking routes. finding interesting hiking routes.
However you can not download the tracks as gpx files, as they argue that the exact However you can not download the tracks as gpx files, as they argue that the
paths are subject to change and it could be dangerous to adhere too closely to them. exact paths are subject to change and it could be dangerous to adhere too
closely to them.
I do agree with that, but you can draw your own routes I do agree with that, but you can draw your own routes and download those,
and download those, mainly taking some time to draw after the route they are mainly taking some time to draw after the route they are already showing on the
already showing on the map. map.
With this extension you can select any track and then download it as a gpx file With this extension you can select any track and then download it as a gpx file
(an active subscription is needed). (an active subscription is needed).
## Be Cautious! ## Be Cautious!
Heed their warning and do not blindly follow the gps track! Use your brain and Heed their warning and do not blindly follow the gps track! Use your brain and
plan your route beforehand to be aware of dangerous parts and alternatives. plan your route beforehand to be aware of dangerous parts and alternatives.
Take a look at their [safety instructions](https://www.sac-cas.ch/en/training-and-safety/safety/). Take a look at their
[safety instructions](https://www.sac-cas.ch/en/training-and-safety/safety/).
## Contributors ## Contributors
- wizche - wizche

View File

@ -21,14 +21,16 @@ function toWGS84(point) {
const x_aux = (point[1] - 1200000) / 1000000; const x_aux = (point[1] - 1200000) / 1000000;
// calculate longitude and latitude in the unit 10000" // calculate longitude and latitude in the unit 10000"
let lat = 16.9023892 + let lat =
16.9023892 +
3.238272 * x_aux - 3.238272 * x_aux -
0.270978 * Math.pow(y_aux, 2) - 0.270978 * Math.pow(y_aux, 2) -
0.002528 * Math.pow(x_aux, 2) - 0.002528 * Math.pow(x_aux, 2) -
0.0447 * Math.pow(y_aux, 2) * x_aux - 0.0447 * Math.pow(y_aux, 2) * x_aux -
0.014 * Math.pow(x_aux, 3); 0.014 * Math.pow(x_aux, 3);
let lon = 2.6779094 + let lon =
2.6779094 +
4.728982 * y_aux + 4.728982 * y_aux +
0.791484 * y_aux * x_aux + 0.791484 * y_aux * x_aux +
0.1306 * y_aux * Math.pow(x_aux, 2) - 0.1306 * y_aux * Math.pow(x_aux, 2) -
@ -102,10 +104,10 @@ function toGpx(geoJson) {
const endPoint = geoJson.end_point ? toWayPoint(geoJson.end_point) : ""; const endPoint = geoJson.end_point ? toWayPoint(geoJson.end_point) : "";
const waypoints = geoJson.waypoints const waypoints = geoJson.waypoints
? geoJson.waypoints ? geoJson.waypoints
.map((wp) => { .map((wp) => {
return toWayPoint(wp.reference_poi); return toWayPoint(wp.reference_poi);
}) })
.join("") .join("")
: ""; : "";
const routeTitle = trackTitle(geoJson); const routeTitle = trackTitle(geoJson);
@ -179,6 +181,41 @@ function checkTrack(tab) {
return tab.url.match("https://www.sac-cas.ch/.*") && gpxTrack; return tab.url.match("https://www.sac-cas.ch/.*") && gpxTrack;
} }
/**
* Remove characters that lead to problems in common filesystems.
*
* Windows (NTFS) seems to have the most restrictions, so it is mostly sourced from there.
*
* Reserved names on windows: https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
*
* Code comes from https://github.com/parshap/node-sanitize-filename/blob/master/index.js
*/
function sanitizeFilename(input) {
const illegal = /[\/\?<>\\:\*\|"]/g;
// deno-lint-ignore no-control-regex
const control = /[\x00-\x1f\x80-\x9f]/g;
const reserved = /^\.+$/;
const windowsReserved = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i;
const windowsTrailing = /[\. ]+$/;
const replacement = "_";
const sanitized = input
.replace(illegal, replacement)
.replace(control, replacement)
.replace(reserved, replacement)
.replace(windowsReserved, replacement)
.replace(windowsTrailing, replacement);
if (sanitized.length === 0) {
sanitized = "unnamed";
}
const maxLength = 250;
const uint8Array = new TextEncoder().encode(sanitized);
const truncated = uint8Array.slice(0, maxLength);
return new TextDecoder().decode(truncated);
}
/** /**
* If a valid tack was selected, download it as a gpx file. * If a valid tack was selected, download it as a gpx file.
*/ */
@ -191,9 +228,10 @@ function handleClick(tab) {
const blob = new Blob([gpxTrack.data], { type: "application/gpx+xml" }); const blob = new Blob([gpxTrack.data], { type: "application/gpx+xml" });
const objectURL = URL.createObjectURL(blob); const objectURL = URL.createObjectURL(blob);
const filename = sanitizeFilename(gpxTrack.title);
const downloading = browser.downloads.download({ const downloading = browser.downloads.download({
url: objectURL, url: objectURL,
filename: `${gpxTrack.title}.gpx`, filename: `${filename}.gpx`,
saveAs: true, saveAs: true,
conflictAction: "uniquify", conflictAction: "uniquify",
}); });
@ -231,11 +269,11 @@ function updateIcon(tab) {
browser.browserAction.setIcon({ browser.browserAction.setIcon({
path: hasTrack path: hasTrack
? { ? {
48: "icons/map.png", 48: "icons/map.png",
} }
: { : {
48: "icons/map-disabled.png", 48: "icons/map-disabled.png",
}, },
tabId: tab.id, tabId: tab.id,
}); });
browser.browserAction.setTitle({ browser.browserAction.setTitle({

View File

@ -1,7 +1,7 @@
{ {
"manifest_version": 2, "manifest_version": 2,
"name": "SAC Route Portal GPX Downloader", "name": "SAC Route Portal GPX Downloader",
"version": "0.8", "version": "0.9",
"developer": { "developer": {
"name": "Sebastian Hugentobler", "name": "Sebastian Hugentobler",
"url": "https://code.vanwa.ch/sebastian/sac-route-portal-gpx-fx" "url": "https://code.vanwa.ch/sebastian/sac-route-portal-gpx-fx"