From 6a640831753f0dacc4826567a7c4d6794fd046cc Mon Sep 17 00:00:00 2001 From: Stefan Bethke Date: Sun, 15 Nov 2026 11:36:49 +0100 Subject: [PATCH] fix: Escapes location search results Nominatim results were inserted via innerHTML and loaded as a JSONP script with an unencoded query. Results are now fetched as JSON, the query is URL encoded, text is escaped and coordinates must be numeric. --- web/www/sunders/js/search.js | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/web/www/sunders/js/search.js b/web/www/sunders/js/search.js index 4ba00a0..38f69a5 100644 --- a/web/www/sunders/js/search.js +++ b/web/www/sunders/js/search.js @@ -37,15 +37,32 @@ function searchLocation(maxResults) { searchLimit = 11; } - var searchScript = document.createElement('script'); - searchScript.src = 'https://nominatim.openstreetmap.org/search.php?q=' + searchString + '&format=json&json_callback=parseResult&limit=' + searchLimit; - document.body.appendChild(searchScript); + var searchUrl = 'https://nominatim.openstreetmap.org/search?q=' + encodeURIComponent(searchString) + + '&format=json&limit=' + encodeURIComponent(searchLimit); + fetch(searchUrl) + .then(function(response) { return response.json(); }) + .then(parseResult) + .catch(function() { parseResult([]); }); } } +// Escape a value for use in HTML text and in double-quoted attributes. +function escapeSearchHtml(value) { + return String(value) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + function parseResult(response) { var searchResultDivs = ''; + if (!Array.isArray(response)) { + response = []; + } + if (response.length == searchLimit) { var lastResultIndex = searchLimit - 1; var nextSearchLimit = searchLimit + 10; @@ -67,10 +84,15 @@ function parseResult(response) { // Show the current 10 search results. for (var i=searchLimit-11; i' + - '
' + searchResult.class + ' / ' + searchResult.type + '
' + - '
' + searchResult.display_name + '
' + + '
' + + '
' + escapeSearchHtml(searchResult.class) + ' / ' + escapeSearchHtml(searchResult.type) + '
' + + '
' + escapeSearchHtml(searchResult.display_name) + '
' + '
'; }