introduce accessor function for URL parameter

These functions take care of type conversion and check that
the parameters contain legal values. The API now returns a
Bad Request error if the format is wrong.
This commit is contained in:
Sarah Hoffmann
2016-06-11 23:07:06 +02:00
parent aa9fff9199
commit d45524cbfb
9 changed files with 153 additions and 141 deletions

View File

@@ -1,5 +1,6 @@
<?php <?php
require_once('init.php'); require_once('init.php');
require_once('website.php');
if (CONST_NoAccessControl) if (CONST_NoAccessControl)
{ {

View File

@@ -39,13 +39,6 @@
exit; exit;
} }
function getParamBool($name, $default=false)
{
if (!isset($_GET[$name])) return $default;
return (bool) $_GET[$name];
}
function fail($sError, $sUserError = false) function fail($sError, $sUserError = false)
{ {
if (!$sUserError) $sUserError = $sError; if (!$sUserError) $sUserError = $sError;

57
lib/website.php Normal file
View File

@@ -0,0 +1,57 @@
<?php
/***************************************************************************
*
* Functions for parsing URL parameters
*
*/
function getParamBool($sName, $bDefault=false)
{
if (!isset($_GET[$sName])) return $bDefault;
return (bool) $_GET[$sName];
}
function getParamInt($sName, $bDefault=false)
{
if (!isset($_GET[$sName])) return $bDefault;
if (!preg_match('/^[+-][0-9]+$/', $_GET[$sName]))
{
userError("Integer number expected for parameter '$sName'");
}
return (int) $_GET[$sName];
}
function getParamFloat($sName, $bDefault=false)
{
if (!isset($_GET[$sName])) return $bDefault;
if (!preg_match('/^[+-]?[0-9]*\.?[0-9]+$/', $_GET[$sName]))
{
userError("Floating-point number expected for parameter '$sName'");
}
return (float) $_GET[$sName];
}
function getParamString($sName, $bDefault=false)
{
if (!isset($_GET[$sName])) return $bDefault;
return $_GET[$sName];
}
function getParamSet($sName, $aValues, $sDefault=false)
{
if (!isset($_GET[$sName])) return $sDefault;
if (!in_array($_GET[$sName], $aValues))
{
userError("Parameter '$sName' must be one of: ".join(', ', $aValues));
}
return $_GET[$sName];
}

View File

@@ -21,15 +21,18 @@
$aLangPrefOrder = getPreferredLanguages(); $aLangPrefOrder = getPreferredLanguages();
$sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted",$aLangPrefOrder))."]"; $sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted",$aLangPrefOrder))."]";
if (isset($_GET['osmtype']) && isset($_GET['osmid']) && (int)$_GET['osmid'] && ($_GET['osmtype'] == 'N' || $_GET['osmtype'] == 'W' || $_GET['osmtype'] == 'R')) $sPlaceId = getParamString('place_id');
$sOsmType = getParamSet('osmtype', array('N', 'W', 'R'));
$iOsmId = getParamInt('osmid', -1);
if ($sOsmType && $iOsmId > 0)
{ {
$_GET['place_id'] = $oDB->getOne("select place_id from placex where osm_type = '".$_GET['osmtype']."' and osm_id = ".(int)$_GET['osmid']." order by type = 'postcode' asc"); $sPlaceId = $oDB->getOne("select place_id from placex where osm_type = '".$sOsmType."' and osm_id = ".$iOsmId." order by type = 'postcode' asc");
// Be nice about our error messages for broken geometry // Be nice about our error messages for broken geometry
if (!$_GET['place_id']) if (!$sPlaceId)
{ {
$aPointDetails = $oDB->getRow("select osm_type, osm_id, errormessage, class, type, get_name_by_language(name,$sLanguagePrefArraySQL) as localname, ST_AsText(prevgeometry) as prevgeom, ST_AsText(newgeometry) as newgeom from import_polygon_error where osm_type = '".$_GET['osmtype']."' and osm_id = ".(int)$_GET['osmid']." order by updated desc limit 1"); $aPointDetails = $oDB->getRow("select osm_type, osm_id, errormessage, class, type, get_name_by_language(name,$sLanguagePrefArraySQL) as localname, ST_AsText(prevgeometry) as prevgeom, ST_AsText(newgeometry) as newgeom from import_polygon_error where osm_type = '".$sOsmType."' and osm_id = ".$iOsmId." order by updated desc limit 1");
if (!PEAR::isError($aPointDetails) && $aPointDetails) { if (!PEAR::isError($aPointDetails) && $aPointDetails) {
if (preg_match('/\[(-?\d+\.\d+) (-?\d+\.\d+)\]/', $aPointDetails['errormessage'], $aMatches)) if (preg_match('/\[(-?\d+\.\d+) (-?\d+\.\d+)\]/', $aPointDetails['errormessage'], $aMatches))
{ {
@@ -48,13 +51,9 @@
} }
if (!isset($_GET['place_id'])) if (!$sPlaceId) userError("Please select a place id");
{
echo "Please select a place id";
exit;
}
$iPlaceID = (int)$_GET['place_id']; $iPlaceID = (int)$sPlaceId;
if (CONST_Use_US_Tiger_Data) if (CONST_Use_US_Tiger_Data)
{ {
@@ -139,7 +138,7 @@
$aPlaceSearchNameKeywords = false; $aPlaceSearchNameKeywords = false;
$aPlaceSearchAddressKeywords = false; $aPlaceSearchAddressKeywords = false;
if (isset($_GET['keywords']) && $_GET['keywords']) if (getParamBool('keywords'))
{ {
$sSQL = "select * from search_name where place_id = $iPlaceID"; $sSQL = "select * from search_name where place_id = $iPlaceID";
$aPlaceSearchName = $oDB->getRow($sSQL); $aPlaceSearchName = $oDB->getRow($sSQL);

View File

@@ -5,28 +5,26 @@
require_once(CONST_BasePath.'/lib/init-website.php'); require_once(CONST_BasePath.'/lib/init-website.php');
require_once(CONST_BasePath.'/lib/log.php'); require_once(CONST_BasePath.'/lib/log.php');
require_once(CONST_BasePath.'/lib/PlaceLookup.php'); require_once(CONST_BasePath.'/lib/PlaceLookup.php');
$sOutputFormat = 'html';
if (isset($_GET['format']) && ($_GET['format'] == 'html' || $_GET['format'] == 'xml' || $_GET['format'] == 'json' || $_GET['format'] == 'jsonv2'))
{
$sOutputFormat = $_GET['format'];
}
ini_set('memory_limit', '200M'); ini_set('memory_limit', '200M');
$oDB =& getDB(); $oDB =& getDB();
$sOutputFormat = getParamSet('format', array('html', 'json'), 'html');
$aLangPrefOrder = getPreferredLanguages(); $aLangPrefOrder = getPreferredLanguages();
$sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted",$aLangPrefOrder))."]"; $sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted",$aLangPrefOrder))."]";
if (isset($_GET['osmtype']) && isset($_GET['osmid']) && (int)$_GET['osmid'] && ($_GET['osmtype'] == 'N' || $_GET['osmtype'] == 'W' || $_GET['osmtype'] == 'R')) $sPlaceId = getParamString('place_id');
$sOsmType = getParamSet('osmtype', array('N', 'W', 'R'));
$iOsmId = getParamInt('osmid', -1);
if ($sOsmType && $iOsmId > 0)
{ {
$_GET['place_id'] = $oDB->getOne("select place_id from placex where osm_type = '".$_GET['osmtype']."' and osm_id = ".(int)$_GET['osmid']." order by type = 'postcode' asc"); $sPlaceId = $oDB->getOne("select place_id from placex where osm_type = '".$sOsmType."' and osm_id = ".$iOsmId." order by type = 'postcode' asc");
// Be nice about our error messages for broken geometry // Be nice about our error messages for broken geometry
if (!$_GET['place_id']) if (!$sPlaceId)
{ {
$aPointDetails = $oDB->getRow("select osm_type, osm_id, errormessage, class, type, get_name_by_language(name,$sLanguagePrefArraySQL) as localname, ST_AsText(prevgeometry) as prevgeom, ST_AsText(newgeometry) as newgeom from import_polygon_error where osm_type = '".$_GET['osmtype']."' and osm_id = ".(int)$_GET['osmid']." order by updated desc limit 1"); $aPointDetails = $oDB->getRow("select osm_type, osm_id, errormessage, class, type, get_name_by_language(name,$sLanguagePrefArraySQL) as localname, ST_AsText(prevgeometry) as prevgeom, ST_AsText(newgeometry) as newgeom from import_polygon_error where osm_type = '".$sOsmType."' and osm_id = ".$iOsmId." order by updated desc limit 1");
if (!PEAR::isError($aPointDetails) && $aPointDetails) { if (!PEAR::isError($aPointDetails) && $aPointDetails) {
if (preg_match('/\[(-?\d+\.\d+) (-?\d+\.\d+)\]/', $aPointDetails['errormessage'], $aMatches)) if (preg_match('/\[(-?\d+\.\d+) (-?\d+\.\d+)\]/', $aPointDetails['errormessage'], $aMatches))
{ {
@@ -39,13 +37,9 @@
} }
} }
if (!isset($_GET['place_id'])) if (!$sPlaceId) userError("Please select a place id");
{
echo "Please select a place id";
exit;
}
$iPlaceID = (int)$_GET['place_id']; $iPlaceID = (int)$sPlaceId;
if (CONST_Use_US_Tiger_Data) if (CONST_Use_US_Tiger_Data)
{ {
@@ -66,11 +60,7 @@
$aPlaceAddress = array_reverse($oPlaceLookup->getAddressDetails()); $aPlaceAddress = array_reverse($oPlaceLookup->getAddressDetails());
if (!sizeof($aPlaceAddress)) if (!sizeof($aPlaceAddress)) userError("Unknown place id.");
{
echo "Unknown place id.";
exit;
}
$aBreadcrums = array(); $aBreadcrums = array();
foreach($aPlaceAddress as $i => $aPlace) foreach($aPlaceAddress as $i => $aPlace)
@@ -84,12 +74,12 @@
if ($sOutputFormat == 'html') echo '<a href="'.$sPlaceUrl.'">'.$aPlace['localname'].'</a> (<a href="'.$sOSMUrl.'">osm</a>)'; if ($sOutputFormat == 'html') echo '<a href="'.$sPlaceUrl.'">'.$aPlace['localname'].'</a> (<a href="'.$sOSMUrl.'">osm</a>)';
} }
$aDetails = array();
$aDetails['breadcrumbs'] = $aBreadcrums;
if ($sOutputFormat == 'json') if ($sOutputFormat == 'json')
{ {
header("content-type: application/json; charset=UTF-8"); header("content-type: application/json; charset=UTF-8");
$aDetails = array();
$aDetails['breadcrumbs'] = $aBreadcrums;
javascript_renderData($aDetails); javascript_renderData($aDetails);
exit; exit;
} }

View File

@@ -22,11 +22,7 @@
ini_set('memory_limit', '200M'); ini_set('memory_limit', '200M');
// Format for output // Format for output
$sOutputFormat = 'xml'; $sOutputFormat = getParamSet('format', array('xml', 'json'), 'xml');
if (isset($_GET['format']) && ($_GET['format'] == 'xml' || $_GET['format'] == 'json'))
{
$sOutputFormat = $_GET['format'];
}
// Preferred language // Preferred language
$aLangPrefOrder = getPreferredLanguages(); $aLangPrefOrder = getPreferredLanguages();
@@ -35,45 +31,42 @@
$aSearchResults = array(); $aSearchResults = array();
$aCleanedQueryParts = array(); $aCleanedQueryParts = array();
if (isset($_GET['osm_ids']))
$oPlaceLookup = new PlaceLookup($oDB);
$oPlaceLookup->setLanguagePreference($aLangPrefOrder);
$oPlaceLookup->setIncludeAddressDetails(getParamBool('addressdetails', true));
$oPlaceLookup->setIncludeExtraTags(getParamBool('extratags', false));
$oPlaceLookup->setIncludeNameDetails(getParamBool('namedetails', false));
$aOsmIds = explode(',', $getParamString('osm_ids', ''));
if (count($aOsmIds) > CONST_Places_Max_ID_count)
{ {
$oPlaceLookup = new PlaceLookup($oDB); userError('Bulk User: Only ' . CONST_Places_Max_ID_count . " ids are allowed in one request.");
$oPlaceLookup->setLanguagePreference($aLangPrefOrder); }
$oPlaceLookup->setIncludeAddressDetails(getParamBool('addressdetails', true));
$oPlaceLookup->setIncludeExtraTags(getParamBool('extratags', false)); foreach ($aOsmIds AS $sItem)
$oPlaceLookup->setIncludeNameDetails(getParamBool('namedetails', false)); {
// Skip empty sItem
if (empty($sItem)) continue;
$aOsmIds = explode(',', $_GET['osm_ids']); $sType = $sItem[0];
$iId = (int) substr($sItem, 1);
if ( count($aOsmIds) > CONST_Places_Max_ID_count ) if ( $iId > 0 && ($sType == 'N' || $sType == 'W' || $sType == 'R') )
{ {
userError('Bulk User: Only ' . CONST_Places_Max_ID_count . " ids are allowed in one request."); $aCleanedQueryParts[] = $sType . $iId;
exit; $oPlaceLookup->setOSMID($sType, $iId);
} $oPlace = $oPlaceLookup->lookup();
if ($oPlace){
foreach ($aOsmIds AS $sItem) // we want to use the search-* output templates, so we need to fill
{ // $aSearchResults and slightly change the (reverse search) oPlace
// Skip empty sItem // key names
if (empty($sItem)) continue; $oResult = $oPlace;
unset($oResult['aAddress']);
$sType = $sItem[0]; if (isset($oPlace['aAddress'])) $oResult['address'] = $oPlace['aAddress'];
$iId = (int) substr($sItem, 1); unset($oResult['langaddress']);
if ( $iId > 0 && ($sType == 'N' || $sType == 'W' || $sType == 'R') ) $oResult['name'] = $oPlace['langaddress'];
{ $aSearchResults[] = $oResult;
$aCleanedQueryParts[] = $sType . $iId;
$oPlaceLookup->setOSMID($sType, $iId);
$oPlace = $oPlaceLookup->lookup();
if ($oPlace){
// we want to use the search-* output templates, so we need to fill
// $aSearchResults and slightly change the (reverse search) oPlace
// key names
$oResult = $oPlace;
unset($oResult['aAddress']);
if (isset($oPlace['aAddress'])) $oResult['address'] = $oPlace['aAddress'];
unset($oResult['langaddress']);
$oResult['name'] = $oPlace['langaddress'];
$aSearchResults[] = $oResult;
}
} }
} }
} }

View File

@@ -2,16 +2,14 @@
require_once(dirname(dirname(__FILE__)).'/settings/settings.php'); require_once(dirname(dirname(__FILE__)).'/settings/settings.php');
require_once(CONST_BasePath.'/lib/init-website.php'); require_once(CONST_BasePath.'/lib/init-website.php');
require_once(CONST_BasePath.'/lib/log.php'); require_once(CONST_BasePath.'/lib/log.php');
$sOutputFormat = 'html';
ini_set('memory_limit', '200M'); ini_set('memory_limit', '200M');
$oDB =& getDB(); $oDB =& getDB();
if (!isset($_GET['days'])) $_GET['days'] = 1;
$bReduced = false; $sOutputFormat = 'html';
if (isset($_GET['reduced'])) $bReduced = true; $iDays = getParamInt('days', 1);
$sClass = false; $bReduced = getParamBool('reduced', false);
if (isset($_GET['class'])) $sClass = $_GET['class']; $sClass = getParamString('class', false);
$iTotalBroken = (int) $oDB->getOne('select count(*) from import_polygon_error'); $iTotalBroken = (int) $oDB->getOne('select count(*) from import_polygon_error');
@@ -21,19 +19,11 @@
$sSQL = 'select osm_type as "type",osm_id as "id",class as "key",type as "value",name->\'name\' as "name",'; $sSQL = 'select osm_type as "type",osm_id as "id",class as "key",type as "value",name->\'name\' as "name",';
$sSQL .= 'country_code as "country",errormessage as "error message",updated'; $sSQL .= 'country_code as "country",errormessage as "error message",updated';
$sSQL .= " from import_polygon_error"; $sSQL .= " from import_polygon_error";
if ($_GET['days']) $sSQL .= " where updated > 'now'::timestamp - '".$iDays." day'::interval";
{ $iDays++;
$sSQL .= " where updated > 'now'::timestamp - '".(int)$_GET['days']." day'::interval";
$_GET['days']++; if ($bReduced) $sSQL .= " and errormessage like 'Area reduced%'";
} if ($sClass) $sSQL .= " and class = '".pg_escape_string($sClass)."'";
if ($bReduced)
{
$sSQL .= " and errormessage like 'Area reduced%'";
}
if ($sClass)
{
$sSQL .= " and class = '".pg_escape_string($sClass)."'";
}
$sSQL .= " order by updated desc limit 1000"; $sSQL .= " order by updated desc limit 1000";
$aPolygons = $oDB->getAll($sSQL); $aPolygons = $oDB->getAll($sSQL);
} }

View File

@@ -21,16 +21,12 @@
$bAsPoints = false; $bAsPoints = false;
$bAsGeoJSON = (boolean)isset($_GET['polygon_geojson']) && $_GET['polygon_geojson']; $bAsGeoJSON = getParamBool('polygon_geojson');
$bAsKML = (boolean)isset($_GET['polygon_kml']) && $_GET['polygon_kml']; $bAsKML = getParamBool('polygon_kml');
$bAsSVG = (boolean)isset($_GET['polygon_svg']) && $_GET['polygon_svg']; $bAsSVG = getParamBool('polygon_svg');
$bAsText = (boolean)isset($_GET['polygon_text']) && $_GET['polygon_text']; $bAsText = getParamBool('polygon_text');
if ( ( ($bAsGeoJSON?1:0) if ((($bAsGeoJSON?1:0) + ($bAsKML?1:0) + ($bAsSVG?1:0)
+ ($bAsKML?1:0) + ($bAsText?1:0) + ($bAsPoints?1:0)) > CONST_PolygonOutput_MaximumTypes)
+ ($bAsSVG?1:0)
+ ($bAsText?1:0)
+ ($bAsPoints?1:0)
) > CONST_PolygonOutput_MaximumTypes)
{ {
if (CONST_PolygonOutput_MaximumTypes) if (CONST_PolygonOutput_MaximumTypes)
{ {
@@ -45,19 +41,14 @@
// Polygon simplification threshold (optional) // Polygon simplification threshold (optional)
$fThreshold = 0.0; $fThreshold = getParamFloat('polygon_threshold', 0.0);
if (isset($_GET['polygon_threshold'])) $fThreshold = (float)$_GET['polygon_threshold'];
$oDB =& getDB(); $oDB =& getDB();
ini_set('memory_limit', '200M'); ini_set('memory_limit', '200M');
// Format for output // Format for output
$sOutputFormat = 'xml'; $sOutputFormat = getParamSet('format', array('html', 'xml', 'json', 'jsonv2'), 'xml');
if (isset($_GET['format']) && ( $_GET['format'] == 'html' || $_GET['format'] == 'xml' || $_GET['format'] == 'json' || $_GET['format'] == 'jsonv2'))
{
$sOutputFormat = $_GET['format'];
}
// Preferred language // Preferred language
$aLangPrefOrder = getPreferredLanguages(); $aLangPrefOrder = getPreferredLanguages();
@@ -65,24 +56,28 @@
$hLog = logStart($oDB, 'reverse', $_SERVER['QUERY_STRING'], $aLangPrefOrder); $hLog = logStart($oDB, 'reverse', $_SERVER['QUERY_STRING'], $aLangPrefOrder);
if (isset($_GET['osm_type']) && isset($_GET['osm_id']) && (int)$_GET['osm_id'] && ($_GET['osm_type'] == 'N' || $_GET['osm_type'] == 'W' || $_GET['osm_type'] == 'R')) $sOsmType = getParamSet('osmtype', array('N', 'W', 'R'));
$iOsmId = getParamInt('osmid', -1);
$fLat = getParamFloat('lat');
$fLon = getParamFloat('lon');
if ($sOsmType && $iOsmId > 0)
{ {
$aLookup = array('osm_type' => $_GET['osm_type'], 'osm_id' => $_GET['osm_id']); $aLookup = array('osm_type' => $sOsmType, 'osm_id' => $iOsmId);
} }
else if (isset($_GET['lat']) && isset($_GET['lon']) && preg_match('/^[+-]?[0-9]*\.?[0-9]+$/', $_GET['lat']) && preg_match('/^[+-]?[0-9]*\.?[0-9]+$/', $_GET['lon'])) else if ($fLat !== false && $fLon !==false)
{ {
$oReverseGeocode = new ReverseGeocode($oDB); $oReverseGeocode = new ReverseGeocode($oDB);
$oReverseGeocode->setLanguagePreference($aLangPrefOrder); $oReverseGeocode->setLanguagePreference($aLangPrefOrder);
$oReverseGeocode->setLatLon($_GET['lat'], $_GET['lon']); $oReverseGeocode->setLatLon($fLat, $fLon);
$oReverseGeocode->setZoom(@$_GET['zoom']); $oReverseGeocode->setZoom(getParamInt('zoom'));
$aLookup = $oReverseGeocode->lookup(); $aLookup = $oReverseGeocode->lookup();
if (CONST_Debug) var_dump($aLookup); if (CONST_Debug) var_dump($aLookup);
} }
else else
{ {
$aLookup = null; userError("Need coordinates or OSM object to lookup.");
} }
if ($aLookup) if ($aLookup)

View File

@@ -25,24 +25,20 @@
} }
// Format for output // Format for output
$sOutputFormat = 'html'; $sOutputFormat = getParamSet('format', array('html', 'xml', 'json', 'jsonv2'), 'html');
if (isset($_GET['format']) && ($_GET['format'] == 'html' || $_GET['format'] == 'xml' || $_GET['format'] == 'json' || $_GET['format'] == 'jsonv2'))
{
$sOutputFormat = $_GET['format'];
}
// Show / use polygons // Show / use polygons
if ($sOutputFormat == 'html') if ($sOutputFormat == 'html')
{ {
if (isset($_GET['polygon'])) $oGeocode->setIncludePolygonAsText((bool)$_GET['polygon']); $oGeocode->setIncludePolygonAsText(getParamBool('polygon'));
} }
else else
{ {
$bAsPoints = (boolean)isset($_GET['polygon']) && $_GET['polygon']; $bAsPoints = getParamBool('polygon');
$bAsGeoJSON = (boolean)isset($_GET['polygon_geojson']) && $_GET['polygon_geojson']; $bAsGeoJSON = getParamBool('polygon_geojson');
$bAsKML = (boolean)isset($_GET['polygon_kml']) && $_GET['polygon_kml']; $bAsKML = getParamBool('polygon_kml');
$bAsSVG = (boolean)isset($_GET['polygon_svg']) && $_GET['polygon_svg']; $bAsSVG = getParamBool('polygon_svg');
$bAsText = (boolean)isset($_GET['polygon_text']) && $_GET['polygon_text']; $bAsText = getParamBool('polygon_text');
if ( ( ($bAsGeoJSON?1:0) if ( ( ($bAsGeoJSON?1:0)
+ ($bAsKML?1:0) + ($bAsKML?1:0)
+ ($bAsSVG?1:0) + ($bAsSVG?1:0)
@@ -68,9 +64,7 @@
} }
// Polygon simplification threshold (optional) // Polygon simplification threshold (optional)
$fThreshold = 0.0; $oGeocode->setPolygonSimplificationThreshold(getParamFloat('polygon_threshold', 0.0));
if (isset($_GET['polygon_threshold'])) $fThreshold = (float)$_GET['polygon_threshold'];
$oGeocode->setPolygonSimplificationThreshold($fThreshold);
$oGeocode->loadParamArray($_GET); $oGeocode->loadParamArray($_GET);
@@ -91,7 +85,7 @@
} }
else else
{ {
if (!(isset($_GET['q']) && $_GET['q']) && isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'][0] == '/') if (!getParamString('q') && isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'][0] == '/')
{ {
$sQuery = substr(rawurldecode($_SERVER['PATH_INFO']), 1); $sQuery = substr(rawurldecode($_SERVER['PATH_INFO']), 1);