forked from kamba4/sunders
Merge pull request 'Fix security issues' (#38) from security-fixes into main
Reviewed-on: #38
This commit is contained in:
commit
60694442c2
7 changed files with 160 additions and 107 deletions
|
|
@ -2,6 +2,18 @@
|
|||
|
||||
include "config.php";
|
||||
|
||||
$seqNum = $_SERVER['argv'][1] ?? '';
|
||||
if (!ctype_digit($seqNum)) {
|
||||
echo "Invalid sequence number\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Quote a value for the generated SQL file. Values come from OSM data and are untrusted.
|
||||
function sqlString($value) {
|
||||
global $mysqli;
|
||||
return "'" . $mysqli->real_escape_string((string) $value) . "'";
|
||||
}
|
||||
|
||||
$elementTypes = array();
|
||||
$count = 0;
|
||||
$countDelete = 0;
|
||||
|
|
@ -91,7 +103,7 @@ function endElement ($parser, $name) {
|
|||
$mode = '';
|
||||
} else if ($name == 'node') {
|
||||
if ($mode == 'delete') {
|
||||
$id = $curNodeAttrs['id'];
|
||||
$id = (int) $curNodeAttrs['id'];
|
||||
|
||||
if (! $deleteTagStmt->execute()) {
|
||||
echo "***** Error : Deleting tags $id : ". $deleteTagStmt->error . "\n";
|
||||
|
|
@ -119,7 +131,7 @@ function endElement ($parser, $name) {
|
|||
|
||||
|
||||
|
||||
$id = $curNodeAttrs['id'];
|
||||
$id = (int) $curNodeAttrs['id'];
|
||||
|
||||
if ($mode == 'modify') {
|
||||
if (! $deleteTagStmt->execute()) {
|
||||
|
|
@ -140,36 +152,36 @@ function endElement ($parser, $name) {
|
|||
|
||||
$k = 'lat';
|
||||
$v = $curNodeAttrs['lat'];
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, '$k', '$v');\n";
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, " . sqlString($k) . ", " . sqlString($v) . ");\n";
|
||||
|
||||
|
||||
$k = 'lon';
|
||||
$v = $curNodeAttrs['lon'];
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, '$k', '$v');\n";
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, " . sqlString($k) . ", " . sqlString($v) . ");\n";
|
||||
|
||||
|
||||
$k = 'userid';
|
||||
$v = $curNodeAttrs['user'];
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, '$k', '$v');\n";
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, " . sqlString($k) . ", " . sqlString($v) . ");\n";
|
||||
|
||||
|
||||
$k = 'version';
|
||||
$v = $curNodeAttrs['version'];
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, '$k', '$v');\n";
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, " . sqlString($k) . ", " . sqlString($v) . ");\n";
|
||||
|
||||
|
||||
|
||||
$k = 'timestamp';
|
||||
$v = $curNodeAttrs['timestamp'];
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, '$k', '$v');\n";
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, " . sqlString($k) . ", " . sqlString($v) . ");\n";
|
||||
|
||||
foreach($curNodeTags as $k => $v) {
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, '$k', '$v');\n";
|
||||
$sql_statement = $sql_statement . "INSERT INTO tag (id, k, v) VALUES ($id, " . sqlString($k) . ", " . sqlString($v) . ");\n";
|
||||
|
||||
}
|
||||
} else if ($mode == 'modify') {
|
||||
// delete former surveillance nodes that were modified to non-surveillance nodes
|
||||
$id = $curNodeAttrs['id'];
|
||||
$id = (int) $curNodeAttrs['id'];
|
||||
|
||||
if (! $deleteTagStmt->execute()) {
|
||||
echo "***** Error : Deleting tags $id for non-surveillance node : ". $deleteTagStmt->error . "\n";
|
||||
|
|
@ -208,11 +220,13 @@ while ($data = fread($fp, 4096)) {
|
|||
}
|
||||
}
|
||||
|
||||
$sql="UPDATE sync_state SET v='" . $_SERVER['argv'][1] ."' WHERE k='sequenceNumber';";
|
||||
$mysqli->query($sql);
|
||||
$sql_statement = $sql_statement . "UPDATE sync_state SET v='" . $_SERVER['argv'][1] ."' WHERE k='sequenceNumber';\n";
|
||||
$syncStmt = $mysqli->prepare("UPDATE sync_state SET v=? WHERE k='sequenceNumber'");
|
||||
$syncStmt->bind_param('s', $seqNum);
|
||||
$syncStmt->execute();
|
||||
$syncStmt->close();
|
||||
$sql_statement = $sql_statement . "UPDATE sync_state SET v='" . $seqNum ."' WHERE k='sequenceNumber';\n";
|
||||
$sql_statement = $sql_statement . "COMMIT;";
|
||||
$sql_file = "/migrations/".$_SERVER['argv'][1].".sql";
|
||||
$sql_file = "/migrations/".$seqNum.".sql";
|
||||
|
||||
file_put_contents($sql_file, $sql_statement);
|
||||
$mysqli->close();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
include "config.php";
|
||||
|
||||
$seqNum = $_SERVER['argv'][1] ?? '';
|
||||
if (!ctype_digit($seqNum)) {
|
||||
echo "Invalid sequence number\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$elementTypes = array();
|
||||
$count = 0;
|
||||
$countDelete = 0;
|
||||
|
|
@ -281,8 +287,10 @@ while ($data = fread($fp, 4096)) {
|
|||
}
|
||||
}
|
||||
|
||||
$sql="UPDATE sync_state SET v='" . $_SERVER['argv'][1] ."' WHERE k='sequenceNumber';";
|
||||
$mysqli->query($sql);
|
||||
$syncStmt = $mysqli->prepare("UPDATE sync_state SET v=? WHERE k='sequenceNumber'");
|
||||
$syncStmt->bind_param('s', $seqNum);
|
||||
$syncStmt->execute();
|
||||
$syncStmt->close();
|
||||
$mysqli->commit();
|
||||
|
||||
printDebug();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,17 @@
|
|||
FROM docker.io/library/php:apache
|
||||
|
||||
RUN docker-php-ext-install mysqli bcmath
|
||||
COPY ./www/* /var/www/html
|
||||
|
||||
# Use PHP's production defaults (no error output to clients) and hide the PHP version.
|
||||
RUN cp "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \
|
||||
&& printf 'expose_php = Off\n' > "$PHP_INI_DIR/conf.d/zz-hardening.ini"
|
||||
|
||||
# Disable directory listings and reduce the server signature.
|
||||
RUN sed -i 's/^\(\s*Options\) Indexes FollowSymLinks/\1 FollowSymLinks/' /etc/apache2/apache2.conf \
|
||||
&& sed -i -e 's/^ServerTokens .*/ServerTokens Prod/' -e 's/^ServerSignature .*/ServerSignature Off/' /etc/apache2/conf-available/security.conf
|
||||
|
||||
COPY ./www/* /var/www/html
|
||||
|
||||
# The web server must not be able to create or modify files in the document root.
|
||||
RUN chown -R root:root /var/www/html \
|
||||
&& chmod -R u=rwX,go=rX /var/www/html
|
||||
|
|
|
|||
|
|
@ -4,6 +4,17 @@
|
|||
|
||||
define('MAX_POINTS_FOR_QUICKHULL', 3000);
|
||||
|
||||
// Fields set by this script; OSM tags with these keys are not passed on.
|
||||
define('RESERVED_KEYS', array('lat', 'lon', 'id', 'count', 'multi', 'poly'));
|
||||
|
||||
define('JSON_FLAGS', JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE);
|
||||
|
||||
function exitWithError($message) {
|
||||
header('Content-type: application/json; charset=utf-8');
|
||||
echo json_encode(array('error' => $message), JSON_FLAGS);
|
||||
exit;
|
||||
}
|
||||
|
||||
class OsmPoint {
|
||||
var $id;
|
||||
var $lat;
|
||||
|
|
@ -179,63 +190,47 @@
|
|||
|| !array_key_exists('zoom', $_GET)
|
||||
|| !array_key_exists('width', $_GET)
|
||||
|| !array_key_exists('height', $_GET)) {
|
||||
header('Content-type: application/json');
|
||||
$result = '{"error":"bbox, zoom, width and height parameters are required. '
|
||||
exitWithError('bbox, zoom, width and height parameters are required. '
|
||||
.(array_key_exists('bbox', $_GET) ? '' : 'bbox is empty. ')
|
||||
.(array_key_exists('zoom', $_GET) ? '' : 'zoom is empty. ')
|
||||
.(array_key_exists('width', $_GET) ? '' : 'width is empty. ')
|
||||
.(array_key_exists('height', $_GET) ? '' : 'height is empty. ')
|
||||
.'"}';
|
||||
echo $result;
|
||||
exit;
|
||||
.(array_key_exists('height', $_GET) ? '' : 'height is empty. '));
|
||||
}
|
||||
|
||||
/* Check zoom */
|
||||
$zoom = $_GET['zoom'];
|
||||
|
||||
if ( !is_numeric($zoom)
|
||||
if ( !is_string($zoom)
|
||||
|| !is_numeric($zoom)
|
||||
|| intval($zoom) < 1
|
||||
|| intval($zoom) > 19) {
|
||||
header('Content-type: application/json');
|
||||
$result = '{"error":"unexpected zoom value : '
|
||||
.htmlentities($zoom)
|
||||
.'"}';
|
||||
echo $result;
|
||||
exit;
|
||||
exitWithError('unexpected zoom value');
|
||||
}
|
||||
|
||||
/* Check bounds box --> bbox=boundsSW.lng,boundsSW.lat,boundsNE.lng,boundsNE.lat */
|
||||
if (!is_string($_GET['bbox'])) {
|
||||
exitWithError('unexpected bbox value');
|
||||
}
|
||||
$bbox = explode(',', $_GET['bbox']);
|
||||
|
||||
if ( !is_numeric($bbox[0]) || $bbox[0] > 180 // 0 = SW.lng
|
||||
if ( count($bbox) != 4
|
||||
|| !is_numeric($bbox[0]) || $bbox[0] > 180 // 0 = SW.lng
|
||||
|| !is_numeric($bbox[2]) || $bbox[2] < -180 // 2 = NE.lng
|
||||
|| !is_numeric($bbox[1]) || $bbox[1] < -90 || $bbox[1] > 90 // 1 = SW.lat
|
||||
|| !is_numeric($bbox[3]) || $bbox[3] < -90 || $bbox[3] > 90) { // 3 = NE.lat
|
||||
header('Content-type: application/json');
|
||||
$result = '{"error":"unexpected bbox longitude and latitude values : '
|
||||
.'lon ['.htmlentities($bbox[0]).', '.htmlentities($bbox[2]).'], '
|
||||
.'lat ['.htmlentities($bbox[1]).', '.htmlentities($bbox[3]).']'
|
||||
.'"}';
|
||||
echo $result;
|
||||
exit;
|
||||
exitWithError('unexpected bbox longitude and latitude values : '
|
||||
.'lon ['.$bbox[0].', '.$bbox[2].'], '
|
||||
.'lat ['.$bbox[1].', '.$bbox[3].']');
|
||||
}
|
||||
|
||||
if ($bbox[0] >= $bbox[2]) { // 0 = SW.lng | 2 = NE.lng
|
||||
header('Content-type: application/json');
|
||||
$result = '{"error":"min longitude greater than max longitude : '
|
||||
.'lon ['.htmlentities($bbox[0]).', '.htmlentities($bbox[2]).']'
|
||||
.'"}';
|
||||
echo $result;
|
||||
exit;
|
||||
exitWithError('min longitude greater than max longitude : '
|
||||
.'lon ['.$bbox[0].', '.$bbox[2].']');
|
||||
}
|
||||
|
||||
if ($bbox[1] >= $bbox[3]) { // 1 = SW.lat | 3 = NE.lat
|
||||
header('Content-type: application/json');
|
||||
$result = '{"error":"min latitude greater than max latitude : '
|
||||
.'lat ['.htmlentities($bbox[1]).', '.htmlentities($bbox[3]).']'
|
||||
.'"}';
|
||||
echo $result;
|
||||
exit;
|
||||
exitWithError('min latitude greater than max latitude : '
|
||||
.'lat ['.$bbox[1].', '.$bbox[3].']');
|
||||
}
|
||||
|
||||
$lonMin = $bbox[0]; // 0 = SW.lng
|
||||
|
|
@ -247,12 +242,7 @@
|
|||
$pixelHeight = (int) $_GET['height'];
|
||||
|
||||
if ($pixelWidth == 0 || $pixelHeight == 0) {
|
||||
header('Content-type: application/json');
|
||||
$result = '{"error":"width or height is null : '
|
||||
.htmlentities($pixelWidth).'x'.htmlentities($pixelHeight)
|
||||
.'"}';
|
||||
echo $result;
|
||||
exit;
|
||||
exitWithError('width or height is null : '.$pixelWidth.'x'.$pixelHeight);
|
||||
}
|
||||
|
||||
$lonWidth = $lonMax - $lonMin; // NE.lng - SW.lng
|
||||
|
|
@ -268,10 +258,7 @@
|
|||
/* Connect to database */
|
||||
$mysqli = new mysqli(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB);
|
||||
if($mysqli->connect_errno) {
|
||||
header('Content-type: application/json');
|
||||
$result = '{"error":"error while connecting to db : ' . $mysqli->error . '"}';
|
||||
echo $result;
|
||||
exit;
|
||||
exitWithError('error while connecting to db');
|
||||
}
|
||||
|
||||
$rqtLonMin = $lonMin; // SW.lng
|
||||
|
|
@ -365,10 +352,7 @@
|
|||
$stmt->close();
|
||||
} else {
|
||||
$mysqli->close();
|
||||
header('Content-type: application/json');
|
||||
$result = '{"error":"Error while request : ' . $mysqli->error . '"}';
|
||||
echo $result;
|
||||
exit;
|
||||
exitWithError('error while querying db');
|
||||
}
|
||||
|
||||
/* Unify some clusters if nodes center are near */
|
||||
|
|
@ -380,8 +364,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
$result='[';
|
||||
$separator='';
|
||||
$result = array();
|
||||
|
||||
/* Writing selected points */
|
||||
$sql='SELECT k, v
|
||||
|
|
@ -393,53 +376,49 @@
|
|||
$stmt->bind_param('d', $id);
|
||||
$stmt->bind_result($k, $v);
|
||||
|
||||
/* Writing grouped items or not */
|
||||
/* Writing grouped items or not. All values are passed on unescaped; the client
|
||||
must escape them before inserting them into HTML. */
|
||||
foreach($resArray as $val) {
|
||||
if ($val['count'] > 0) {
|
||||
$result = $result.$separator
|
||||
.'{"lat":"'.($val['latitude'] / $val['count']).'"'
|
||||
.',"lon":"'.($val['longitude'] / $val['count']).'"';
|
||||
$entry = array(
|
||||
'lat' => (string) ($val['latitude'] / $val['count']),
|
||||
'lon' => (string) ($val['longitude'] / $val['count']));
|
||||
|
||||
if ($val['count'] == 1) {
|
||||
$id = $val['points'][0]->id;
|
||||
$result = $result.',"id":"'.$id.'"';
|
||||
$entry['id'] = (string) $id;
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
while($stmt->fetch()) {
|
||||
$result = $result.',"'.htmlentities($k).'":"'.htmlentities($v, ENT_COMPAT, 'UTF-8').'"';
|
||||
if (!in_array($k, RESERVED_KEYS, true)) {
|
||||
$entry[$k] = (string) $v;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = $result
|
||||
.',"count":"'.$val['count'].'"'
|
||||
.',"multi":"yes"'
|
||||
.',"poly":[';
|
||||
$entry['count'] = (string) $val['count'];
|
||||
$entry['multi'] = 'yes';
|
||||
$entry['poly'] = array();
|
||||
|
||||
if ($pointsCount < MAX_POINTS_FOR_QUICKHULL) {
|
||||
$convexPoly = quickHull($val['points'], $val['count']);
|
||||
$sepPoly = '';
|
||||
foreach($convexPoly as $point) {
|
||||
$result = $result.$sepPoly.'{'
|
||||
.'"lat":"'.$point->lat.'"'
|
||||
.',"id":"'.$point->id.'"'
|
||||
.',"lon":"'.$point->lon.'"}';
|
||||
$sepPoly=',';
|
||||
$entry['poly'][] = array(
|
||||
'lat' => (string) $point->lat,
|
||||
'id' => (string) $point->id,
|
||||
'lon' => (string) $point->lon);
|
||||
}
|
||||
}
|
||||
$result=$result.']';
|
||||
}
|
||||
|
||||
$result = $result.'}';
|
||||
$separator=',';
|
||||
$result[] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$result = $result . ']';
|
||||
|
||||
$mysqli->close();
|
||||
|
||||
header('Content-type: application/json; Charset : utf-8');
|
||||
echo $result;
|
||||
header('Content-type: application/json; charset=utf-8');
|
||||
echo json_encode($result, JSON_FLAGS);
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -129,7 +129,11 @@ function onClick(e) {
|
|||
function onStateChanged() {
|
||||
if (ajaxRequest.readyState == 4) { // 0 = UNSENT, 1 = OPENED, 2 = HEADERS_RECEIVED, 3 = LOADING, 4 = DONE
|
||||
if (ajaxRequest.status == 200) { // 200 = OK, 404 = Page not found
|
||||
plotList = eval('(' + ajaxRequest.responseText + ')');
|
||||
try {
|
||||
plotList = JSON.parse(ajaxRequest.responseText);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
removeMarkers();
|
||||
for (i=0; i<plotList.length; i++) {
|
||||
var plotLatLng;
|
||||
|
|
@ -421,26 +425,39 @@ function drawCameraFocusDome(plotLatLng, focusRadius, focusColor) {
|
|||
return(new L.Circle(plotLatLng, focusRadius, { weight:1, color:focusColor, fillOpacity:0.1 }));
|
||||
}
|
||||
|
||||
// Escape a value for use in HTML text and in double-quoted attributes.
|
||||
function escapeHtml(value) {
|
||||
return String(value)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
// Add camera popup to camera marker.
|
||||
// All values in plot come unescaped from OSM data and must be escaped.
|
||||
function addCameraDetailsData(plotMarker, plot) {
|
||||
var id = escapeHtml(plot.id);
|
||||
popupDataTable = '<table class="popup-content">'
|
||||
+ '<tr><td>id</td><td><a href="https://www.openstreetmap.org/node/' + (plot.id) + '">' + (plot.id) + '</a></td></tr>'
|
||||
// + '<tr><td>user osm</td><td>' + (plot.userid) + '</td></tr>'
|
||||
+ '<tr><td>latitude</td><td>' + (plot.lat) + '</td></tr>'
|
||||
+ '<tr><td>longitude</td><td>' + (plot.lon) + '</td></tr>';
|
||||
+ '<tr><td>id</td><td><a href="https://www.openstreetmap.org/node/' + encodeURIComponent(plot.id) + '">' + id + '</a></td></tr>'
|
||||
// + '<tr><td>user osm</td><td>' + escapeHtml(plot.userid) + '</td></tr>'
|
||||
+ '<tr><td>latitude</td><td>' + escapeHtml(plot.lat) + '</td></tr>'
|
||||
+ '<tr><td>longitude</td><td>' + escapeHtml(plot.lon) + '</td></tr>';
|
||||
for (x in plot) {
|
||||
if (plot[x] !== '' && x != 'multi' && x != 'id' && x != 'userid' && x != 'lat' && x != 'lon') {
|
||||
popupDataTable = popupDataTable + '<tr><td>' + x + '</td><td>';
|
||||
var descr = plot[x];
|
||||
if (descr.substr(0, 4) == 'http') {
|
||||
popupDataTable = popupDataTable + '<tr><td>' + escapeHtml(x) + '</td><td>';
|
||||
var descr = String(plot[x]);
|
||||
if (/^https?:\/\//i.test(descr)) {
|
||||
var url = escapeHtml(descr);
|
||||
var suffix = descr.slice(-3).toLowerCase();
|
||||
if (suffix == 'jpg' || suffix == 'gif' || suffix == 'png') {
|
||||
popupDataTable = popupDataTable + '<a href="' + descr + '"><img alt="Link" src="' + descr + '" width="200"/></a>';
|
||||
popupDataTable = popupDataTable + '<a href="' + url + '"><img alt="Link" src="' + url + '" width="200"/></a>';
|
||||
} else {
|
||||
popupDataTable = popupDataTable + '<a href="' + descr + '">Link</a>';
|
||||
popupDataTable = popupDataTable + '<a href="' + url + '">Link</a>';
|
||||
}
|
||||
} else {
|
||||
popupDataTable = popupDataTable + plot[x];
|
||||
popupDataTable = popupDataTable + escapeHtml(descr);
|
||||
}
|
||||
popupDataTable = popupDataTable + '</td></tr>';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, '"')
|
||||
.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<lastResultIndex; i++) {
|
||||
searchResult = response[i];
|
||||
var lat = Number(searchResult.lat);
|
||||
var lon = Number(searchResult.lon);
|
||||
if (!isFinite(lat) || !isFinite(lon)) {
|
||||
continue;
|
||||
}
|
||||
searchResultDivs +=
|
||||
'<div class="search-result" onClick="gotoLocation(' + searchResult.lat + ', ' + searchResult.lon + ');return false;">' +
|
||||
'<div class="text-medium">' + searchResult.class + ' / ' + searchResult.type + '</div>' +
|
||||
'<div>' + searchResult.display_name + '</div>' +
|
||||
'<div class="search-result" onClick="gotoLocation(' + lat + ', ' + lon + ');return false;">' +
|
||||
'<div class="text-medium">' + escapeSearchHtml(searchResult.class) + ' / ' + escapeSearchHtml(searchResult.type) + '</div>' +
|
||||
'<div>' + escapeSearchHtml(searchResult.display_name) + '</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@
|
|||
} else {
|
||||
$i18n = $i18nCountries;
|
||||
$i18nDefault = $i18nCountriesDefault;
|
||||
// Check if $key consists of 2 capital letters.
|
||||
$key = preg_match('/\b[A-Z]{2}\b/', $valsArray[$i]) === 1 || '--' ? $valsArray[$i] : 'dontfindme';
|
||||
// Check if $key consists of 2 capital letters or is '--' (unknown country).
|
||||
$key = (preg_match('/^[A-Z]{2}$/', $valsArray[$i]) === 1 || $valsArray[$i] === '--') ? $valsArray[$i] : 'dontfindme';
|
||||
}
|
||||
if (!isValidValue($i18n, $i18nDefault, $key)) {
|
||||
// ignore 'vals' and 'cols'
|
||||
|
|
|
|||
Loading…
Reference in a new issue