diff --git a/web/www/sunders/camera.php b/web/www/sunders/camera.php
index 97a77e7..9aa2f85 100644
--- a/web/www/sunders/camera.php
+++ b/web/www/sunders/camera.php
@@ -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);
?>
diff --git a/web/www/sunders/js/leafletembed_functions.js b/web/www/sunders/js/leafletembed_functions.js
index cb199a0..75e461e 100644
--- a/web/www/sunders/js/leafletembed_functions.js
+++ b/web/www/sunders/js/leafletembed_functions.js
@@ -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
| id | ' + (plot.id) + ' |
| user osm | ' + (plot.userid) + ' |
| latitude | ' + (plot.lat) + ' |
| longitude | ' + (plot.lon) + ' |
| id | ' + id + ' |
| user osm | ' + escapeHtml(plot.userid) + ' |
| latitude | ' + escapeHtml(plot.lat) + ' |
| longitude | ' + escapeHtml(plot.lon) + ' |
| ' + x + ' | '; - var descr = plot[x]; - if (descr.substr(0, 4) == 'http') { + popupDataTable = popupDataTable + ' |
| ' + escapeHtml(x) + ' | ';
+ 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 + ' |