From: Marc Tobias Metten Date: Tue, 23 Aug 2016 22:03:40 +0000 (+0200) Subject: Merge remote-tracking branch 'upstream/master' into move-mouse-position-info-on-map X-Git-Tag: v3.0.0~139^2~1 X-Git-Url: https://git.openstreetmap.org./nominatim.git/commitdiff_plain/797c2d1e74a14d8d52d963f1efad9be53fca5f5f?hp=bb403e2e589434e862c1b6d1206b7a61144011c6 Merge remote-tracking branch 'upstream/master' into move-mouse-position-info-on-map --- diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..13c3d68d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +--- +language: + - 'python' +sudo: required +dist: trusty +before_install: + - git submodule update --init --recursive +install: + - vagrant/install-on-travis-ci.sh +before_script: + - cd $TRAVIS_BUILD_DIR/build + - wget --no-verbose --output-document=../data/monaco.osm.pbf http://download.geofabrik.de/europe/monaco-latest.osm.pbf + - ./utils/setup.php --osm-file ../data/monaco.osm.pbf --osm2pgsql-cache 1000 --all 2>&1 | grep -v 'ETA (seconds)' + - ./utils/specialphrases.php --countries > ../data/specialphrases_countries.sql + - psql -d nominatim -f ../data/specialphrases_countries.sql +script: + - cd $TRAVIS_BUILD_DIR/tests-php + - phpunit ./ + - cd $TRAVIS_BUILD_DIR/tests + - #lettuce features/api --verbosity=1 + - lettuce features/db --verbosity=1 -t -Fail -t -Tiger -t -poldi-only + - lettuce features/osm2pgsql --verbosity=1 -t -Fail +notifications: + email: false diff --git a/CMakeLists.txt b/CMakeLists.txt index 1aaf05f0..65254b1c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,6 @@ include_directories(${LIBXML2_INCLUDE_DIR}) #----------------------------------------------------------------------------- set(CUSTOMFILES - settings/settings.php settings/phrase_settings.php website/deletable.php website/details.php @@ -92,6 +91,8 @@ foreach (cfile ${CUSTOMFILES}) configure_file(${PROJECT_SOURCE_DIR}/${cfile} ${PROJECT_BINARY_DIR}/${cfile}) endforeach() +configure_file(${PROJECT_SOURCE_DIR}/settings/defaults.php ${PROJECT_BINARY_DIR}/settings/settings.php) + set(WEBPATHS css images js) foreach (wp ${WEBPATHS}) diff --git a/VAGRANT.md b/VAGRANT.md index e6a0fbb3..cd3ed311 100644 --- a/VAGRANT.md +++ b/VAGRANT.md @@ -45,11 +45,12 @@ is. ``` # inside the virtual machine: - cd Nominatim - wget --no-verbose --output-document=data/monaco.osm.pbf http://download.geofabrik.de/europe/monaco-latest.osm.pbf - ./utils/setup.php --osm-file data/monaco.osm.pbf --osm2pgsql-cache 1000 --all 2>&1 | tee monaco.$$.log - ./utils/specialphrases.php --countries > data/specialphrases_countries.sql - psql -d nominatim -f data/specialphrases_countries.sql + mkdir data + cd build + wget --no-verbose --output-document=../data/monaco.osm.pbf http://download.geofabrik.de/europe/monaco-latest.osm.pbf + ./utils/setup.php --osm-file ../data/monaco.osm.pbf --osm2pgsql-cache 1000 --all 2>&1 | tee monaco.$$.log + ./utils/specialphrases.php --countries > ../data/specialphrases_countries.sql + psql -d nominatim -f ../data/specialphrases_countries.sql ``` To repeat an import you'd need to delete the database first diff --git a/Vagrantfile b/Vagrantfile index 96d03a2e..15d66e9e 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -14,7 +14,7 @@ Vagrant.configure("2") do |config| checkout = "no" end - config.vm.define "ubuntu" do |sub| + config.vm.define "ubuntu", primary: true do |sub| sub.vm.box = "bento/ubuntu-16.04" sub.vm.provision :shell do |s| s.path = "vagrant/install-on-ubuntu-16.sh" diff --git a/docs/Import_and_update.md b/docs/Import_and_update.md index a4ad604d..b367a430 100644 --- a/docs/Import_and_update.md +++ b/docs/Import_and_update.md @@ -19,6 +19,8 @@ Add to your settings/local.php: @define('CONST_Osm2pgsql_Flatnode_File', '/path/to/flatnode.file'); +Replace the second part with a suitable path on your system and make sure +the directory exists. There should be at least 35GB of free space. Downloading additional data --------------------------- diff --git a/docs/Installation.md b/docs/Installation.md index fd4f8d0b..2e624396 100644 --- a/docs/Installation.md +++ b/docs/Installation.md @@ -74,7 +74,7 @@ your `postgresql.conf` file. work_mem (50MB) effective_cache_size (24GB) synchronous_commit = off - checkpoint_segments = 100 + checkpoint_segments = 100 # only for postgresql <= 9.4 checkpoint_timeout = 10min checkpoint_completion_target = 0.9 diff --git a/lib/Geocode.php b/lib/Geocode.php index 9249b314..b102c4b2 100644 --- a/lib/Geocode.php +++ b/lib/Geocode.php @@ -33,9 +33,9 @@ protected $bBoundedSearch = false; protected $aViewBox = false; + protected $sViewboxCentreSQL = false; protected $sViewboxSmallSQL = false; protected $sViewboxLargeSQL = false; - protected $aRoutePoints = false; protected $iMaxRank = 20; protected $iMinAddressRank = 0; @@ -114,7 +114,7 @@ if ($iLimit < 1) $iLimit = 1; $this->iFinalLimit = $iLimit; - $this->iLimit = $this->iFinalLimit + min($this->iFinalLimit, 10); + $this->iLimit = $iLimit + min($iLimit, 10); } function getExcludedPlaceIDs() @@ -122,11 +122,6 @@ return $this->aExcludePlaceIDs; } - function setViewBox($fLeft, $fBottom, $fRight, $fTop) - { - $this->aViewBox = array($fLeft, $fBottom, $fRight, $fTop); - } - function getViewBoxString() { if (!$this->aViewBox) return null; @@ -158,6 +153,43 @@ $this->iMaxAddressRank = $iMax; } + function setRoute($aRoutePoints, $fRouteWidth) + { + $this->aViewBox = false; + + $this->sViewboxCentreSQL = "ST_SetSRID('LINESTRING("; + $sSep = ''; + foreach($this->aRoutePoints as $aPoint) + { + $fPoint = (float)$aPoint; + $this->sViewboxCentreSQL .= $sSep.$fPoint; + $sSep = ($sSep == ' ') ? ',' : ' '; + } + $this->sViewboxCentreSQL .= ")'::geometry,4326)"; + + $this->sViewboxSmallSQL = 'st_buffer('.$this->sViewboxCentreSQL; + $this->sViewboxSmallSQL .= ','.($fRouteWidth/69).')'; + + $this->sViewboxLargeSQL = 'st_buffer('.$this->sViewboxCentreSQL; + $this->sViewboxLargeSQL .= ','.($fRouteWidth/30).')'; + } + + function setViewbox($aViewbox) + { + $this->aViewBox = array_map('floatval', $aViewbox); + + $fHeight = $this->aViewBox[0] - $this->aViewBox[2]; + $fWidth = $this->aViewBox[1] - $this->aViewBox[3]; + $aBigViewBox[0] = $this->aViewBox[0] + $fHeight; + $aBigViewBox[2] = $this->aViewBox[2] - $fHeight; + $aBigViewBox[1] = $this->aViewBox[1] + $fWidth; + $aBigViewBox[3] = $this->aViewBox[3] - $fWidth; + + $this->sViewboxCentreSQL = false; + $this->sViewboxSmallSQL = "ST_SetSRID(ST_MakeBox2D(ST_Point(".$this->aViewBox[0].",".$this->aViewBox[1]."),ST_Point(".$this->aViewBox[2].",".$this->aViewBox[3].")),4326)"; + $this->sViewboxLargeSQL = "ST_SetSRID(ST_MakeBox2D(ST_Point(".$aBigViewBox[0].",".$aBigViewBox[1]."),ST_Point(".$aBigViewBox[2].",".$aBigViewBox[3].")),4326)"; + } + function setNearPoint($aNearPoint, $fRadiusDeg = 0.1) { $this->aNearPoint = array((float)$aNearPoint[0], (float)$aNearPoint[1], (float)$fRadiusDeg); @@ -175,24 +207,28 @@ } - function loadParamArray($aParams) + function loadParamArray($oParams) { - if (isset($aParams['addressdetails'])) $this->bIncludeAddressDetails = (bool)$aParams['addressdetails']; - if (isset($aParams['extratags'])) $this->bIncludeExtraTags = (bool)$aParams['extratags']; - if (isset($aParams['namedetails'])) $this->bIncludeNameDetails = (bool)$aParams['namedetails']; + $this->bIncludeAddressDetails = $oParams->getBool('addressdetails', + $this->bIncludeAddressDetails); + $this->bIncludeExtraTags = $oParams->getBool('extratags', + $this->bIncludeExtraTags); + $this->bIncludeNameDetails = $oParams->getBool('namedetails', + $this->bIncludeNameDetails); - if (isset($aParams['bounded'])) $this->bBoundedSearch = (bool)$aParams['bounded']; - if (isset($aParams['dedupe'])) $this->bDeDupe = (bool)$aParams['dedupe']; + $this->bBoundedSearch = $oParams->getBool('bounded', $this->bBoundedSearch); + $this->bDeDupe = $oParams->getBool('dedupe', $this->bDeDupe); - if (isset($aParams['limit'])) $this->setLimit((int)$aParams['limit']); - if (isset($aParams['offset'])) $this->iOffset = (int)$aParams['offset']; + $this->setLimit($oParams->getInt('limit', $this->iFinalLimit)); + $this->iOffset = $oParams->getInt('offset', $this->iOffset); - if (isset($aParams['fallback'])) $this->bFallback = (bool)$aParams['fallback']; + $this->bFallback = $oParams->getBool('fallback', $this->bFallback); // List of excluded Place IDs - used for more acurate pageing - if (isset($aParams['exclude_place_ids']) && $aParams['exclude_place_ids']) + $sExcluded = $oParams->getStringList('exclude_place_ids'); + if ($sExcluded) { - foreach(explode(',',$aParams['exclude_place_ids']) as $iExcludedPlaceID) + foreach($sExcluded as $iExcludedPlaceID) { $iExcludedPlaceID = (int)$iExcludedPlaceID; if ($iExcludedPlaceID) @@ -204,66 +240,63 @@ } // Only certain ranks of feature - if (isset($aParams['featureType'])) $this->setFeatureType($aParams['featureType']); - if (isset($aParams['featuretype'])) $this->setFeatureType($aParams['featuretype']); + $sFeatureType = $oParams->getString('featureType'); + if (!$sFeatureType) $sFeatureType = $oParams->getString('featuretype'); + if ($sFeatureType) $this->setFeatureType($sFeatureType); // Country code list - if (isset($aParams['countrycodes'])) + $sCountries = $oParams->getStringList('countrycodes'); + if ($sCountries) { - $aCountryCodes = array(); - foreach(explode(',',$aParams['countrycodes']) as $sCountryCode) + foreach($sCountries as $sCountryCode) { if (preg_match('/^[a-zA-Z][a-zA-Z]$/', $sCountryCode)) { - $aCountryCodes[] = strtolower($sCountryCode); + $aCountries[] = strtolower($sCountryCode); } } - $this->aCountryCodes = $aCountryCodes; + if (isset($aCountryCodes)) + $this->aCountryCodes = $aCountries; } - if (isset($aParams['viewboxlbrt']) && $aParams['viewboxlbrt']) + $aViewbox = $oParams->getStringList('viewboxlbrt'); + if ($aViewbox) { - $aCoOrdinatesLBRT = explode(',',$aParams['viewboxlbrt']); - $this->setViewBox($aCoOrdinatesLBRT[0], $aCoOrdinatesLBRT[1], $aCoOrdinatesLBRT[2], $aCoOrdinatesLBRT[3]); + $this->setViewbox($aViewbox); } - else if (isset($aParams['viewbox']) && $aParams['viewbox']) - { - $aCoOrdinatesLTRB = explode(',',$aParams['viewbox']); - $this->setViewBox($aCoOrdinatesLTRB[0], $aCoOrdinatesLTRB[3], $aCoOrdinatesLTRB[2], $aCoOrdinatesLTRB[1]); - } - - if (isset($aParams['route']) && $aParams['route'] && isset($aParams['routewidth']) && $aParams['routewidth']) + else { - $aPoints = explode(',',$aParams['route']); - if (sizeof($aPoints) % 2 != 0) + $aViewbox = $oParams->getStringList('viewbox'); + if ($aViewbox) { - userError("Uneven number of points"); - exit; + $this->setViewBox(array($aViewbox[0], $aViewbox[3], + $aViewbox[2], $aViewbox[1])); } - $fPrevCoord = false; - $aRoute = array(); - foreach($aPoints as $i => $fPoint) + else { - if ($i%2) - { - $aRoute[] = array((float)$fPoint, $fPrevCoord); - } - else + $aRoute = $oParams->getStringList('route'); + $fRouteWidth = $oParams->getFloat('routewidth'); + if ($aRoute && $fRouteWidth) { - $fPrevCoord = (float)$fPoint; + $this->setRoute($aRoute, $fRouteWidth); } } - $this->aRoutePoints = $aRoute; } } - function setQueryFromParams($aParams) + function setQueryFromParams($oParams) { // Search query - $sQuery = (isset($aParams['q'])?trim($aParams['q']):''); + $sQuery = $oParams->getString('q'); if (!$sQuery) { - $this->setStructuredQuery(@$aParams['amenity'], @$aParams['street'], @$aParams['city'], @$aParams['county'], @$aParams['state'], @$aParams['country'], @$aParams['postalcode']); + $this->setStructuredQuery($oParams->getString('amenity'), + $oParams->getString('street'), + $oParams->getString('city'), + $oParams->getString('county'), + $oParams->getString('state'), + $oParams->getString('country'), + $oParams->getString('postalcode')); $this->setReverseInPlan(false); } else @@ -783,7 +816,7 @@ $sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted",$this->aLangPrefOrder))."]"; $sCountryCodesSQL = false; - if ($this->aCountryCodes && sizeof($this->aCountryCodes)) + if ($this->aCountryCodes) { $sCountryCodesSQL = join(',', array_map('addQuotes', $this->aCountryCodes)); } @@ -798,46 +831,17 @@ $sQuery = preg_replace('/(^|,)\s*la\s*(,|$)/','\1louisiana\2', $sQuery); } - // View Box SQL - $sViewboxCentreSQL = false; - $bBoundingBoxSearch = false; - if ($this->aViewBox) - { - $fHeight = $this->aViewBox[0]-$this->aViewBox[2]; - $fWidth = $this->aViewBox[1]-$this->aViewBox[3]; - $aBigViewBox[0] = $this->aViewBox[0] + $fHeight; - $aBigViewBox[2] = $this->aViewBox[2] - $fHeight; - $aBigViewBox[1] = $this->aViewBox[1] + $fWidth; - $aBigViewBox[3] = $this->aViewBox[3] - $fWidth; - - $this->sViewboxSmallSQL = "ST_SetSRID(ST_MakeBox2D(ST_Point(".(float)$this->aViewBox[0].",".(float)$this->aViewBox[1]."),ST_Point(".(float)$this->aViewBox[2].",".(float)$this->aViewBox[3].")),4326)"; - $this->sViewboxLargeSQL = "ST_SetSRID(ST_MakeBox2D(ST_Point(".(float)$aBigViewBox[0].",".(float)$aBigViewBox[1]."),ST_Point(".(float)$aBigViewBox[2].",".(float)$aBigViewBox[3].")),4326)"; - $bBoundingBoxSearch = $this->bBoundedSearch; - } - - // Route SQL - if ($this->aRoutePoints) + $bBoundingBoxSearch = $this->bBoundedSearch && $this->sViewboxSmallSQL; + if ($this->sViewboxCentreSQL) { - $sViewboxCentreSQL = "ST_SetSRID('LINESTRING("; - $bFirst = true; - foreach($this->aRoutePoints as $aPoint) - { - if (!$bFirst) $sViewboxCentreSQL .= ","; - $sViewboxCentreSQL .= $aPoint[0].' '.$aPoint[1]; - $bFirst = false; - } - $sViewboxCentreSQL .= ")'::geometry,4326)"; - - $sSQL = "select st_buffer(".$sViewboxCentreSQL.",".(float)($_GET['routewidth']/69).")"; - $this->sViewboxSmallSQL = chksql($this->oDB->getOne($sSQL), - "Could not get small viewbox."); - $this->sViewboxSmallSQL = "'".$this->sViewboxSmallSQL."'::geometry"; - - $sSQL = "select st_buffer(".$sViewboxCentreSQL.",".(float)($_GET['routewidth']/30).")"; - $this->sViewboxLargeSQL = chksql($this->oDB->getOne($sSQL), - "Could not get large viewbox."); - $this->sViewboxLargeSQL = "'".$this->sViewboxLargeSQL."'::geometry"; - $bBoundingBoxSearch = $this->bBoundedSearch; + // For complex viewboxes (routes) precompute the bounding geometry + $sGeom = chksql($this->oDB->getOne("select ".$this->sViewboxSmallSQL), + "Could not get small viewbox"); + $this->sViewboxSmallSQL = "'".$sGeom."'::geometry"; + + $sGeom = chksql($this->oDB->getOne("select ".$this->sViewboxLargeSQL), + "Could not get large viewbox"); + $this->sViewboxLargeSQL = "'".$sGeom."'::geometry"; } // Do we have anything that looks like a lat/lon pair? @@ -1224,7 +1228,7 @@ { $sSQL .= " and place_id not in (".join(',',$this->aExcludePlaceIDs).")"; } - if ($sViewboxCentreSQL) $sSQL .= " order by st_distance($sViewboxCentreSQL, ct.centroid) asc"; + if ($this->sViewboxCentreSQL) $sSQL .= " order by st_distance($this->sViewboxCentreSQL, ct.centroid) asc"; $sSQL .= " limit $this->iLimit"; if (CONST_Debug) var_dump($sSQL); $aPlaceIDs = chksql($this->oDB->getCol($sSQL)); @@ -1239,7 +1243,7 @@ if ($sCountryCodesSQL) $sSQL .= " join placex using (place_id)"; $sSQL .= " where st_contains($this->sViewboxLargeSQL, ct.centroid)"; if ($sCountryCodesSQL) $sSQL .= " and calculated_country_code in ($sCountryCodesSQL)"; - if ($sViewboxCentreSQL) $sSQL .= " order by st_distance($sViewboxCentreSQL, ct.centroid) asc"; + if ($this->sViewboxCentreSQL) $sSQL .= " order by st_distance($this->sViewboxCentreSQL, ct.centroid) asc"; $sSQL .= " limit $this->iLimit"; if (CONST_Debug) var_dump($sSQL); $aPlaceIDs = chksql($this->oDB->getCol($sSQL)); @@ -1250,7 +1254,7 @@ $sSQL = "select place_id from placex where class='".$aSearch['sClass']."' and type='".$aSearch['sType']."'"; $sSQL .= " and st_contains($this->sViewboxSmallSQL, geometry) and linked_place_id is null"; if ($sCountryCodesSQL) $sSQL .= " and calculated_country_code in ($sCountryCodesSQL)"; - if ($sViewboxCentreSQL) $sSQL .= " order by st_distance($sViewboxCentreSQL, centroid) asc"; + if ($this->sViewboxCentreSQL) $sSQL .= " order by st_distance($this->sViewboxCentreSQL, centroid) asc"; $sSQL .= " limit $this->iLimit"; if (CONST_Debug) var_dump($sSQL); $aPlaceIDs = chksql($this->oDB->getCol($sSQL)); diff --git a/lib/ParameterParser.php b/lib/ParameterParser.php new file mode 100644 index 00000000..95a3281b --- /dev/null +++ b/lib/ParameterParser.php @@ -0,0 +1,133 @@ +aParams = ($aParams === NULL) ? $_GET : $aParams; + } + + function getBool($sName, $bDefault=false) + { + if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) + { + return $bDefault; + } + + return (bool) $this->aParams[$sName]; + } + + function getInt($sName, $bDefault=false) + { + if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) + { + return $bDefault; + } + + if (!preg_match('/^[+-]?[0-9]+$/', $this->aParams[$sName])) + { + userError("Integer number expected for parameter '$sName'"); + } + + return (int) $this->aParams[$sName]; + } + + function getFloat($sName, $bDefault=false) + { + if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) + { + return $bDefault; + } + + if (!preg_match('/^[+-]?[0-9]*\.?[0-9]+$/', $this->aParams[$sName])) + { + userError("Floating-point number expected for parameter '$sName'"); + } + + return (float) $this->aParams[$sName]; + } + + function getString($sName, $bDefault=false) + { + if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) + { + return $bDefault; + } + + return $this->aParams[$sName]; + } + + function getSet($sName, $aValues, $sDefault=false) + { + if (!isset($this->aParams[$sName]) || strlen($this->aParams[$sName]) == 0) + { + return $sDefault; + } + + if (!in_array($this->aParams[$sName], $aValues)) + { + userError("Parameter '$sName' must be one of: ".join(', ', $aValues)); + } + + return $this->aParams[$sName]; + } + + function getStringList($sName, $aDefault=false) + { + $sValue = $this->getString($sName); + + if ($sValue) + { + return explode(',', $sValue); + } + + return $aDefault; + } + + function getPreferredLanguages($sFallback=NULL) + { + if ($sFallback === NULL && isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])) + { + $sFallback = $_SERVER["HTTP_ACCEPT_LANGUAGE"]; + } + + $aLanguages = array(); + $sLangString = $this->getString('accept-language', $sFallback); + + if ($sLangString) + { + if (preg_match_all('/(([a-z]{1,8})(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $sLangString, $aLanguagesParse, PREG_SET_ORDER)) + { + foreach($aLanguagesParse as $iLang => $aLanguage) + { + $aLanguages[$aLanguage[1]] = isset($aLanguage[5])?(float)$aLanguage[5]:1 - ($iLang/100); + if (!isset($aLanguages[$aLanguage[2]])) $aLanguages[$aLanguage[2]] = $aLanguages[$aLanguage[1]]/10; + } + arsort($aLanguages); + } + } + if (!sizeof($aLanguages) && CONST_Default_Language) + { + $aLanguages[CONST_Default_Language] = 1; + } + + foreach($aLanguages as $sLanguage => $fLanguagePref) + { + $aLangPrefOrder['short_name:'.$sLanguage] = 'short_name:'.$sLanguage; + $aLangPrefOrder['name:'.$sLanguage] = 'name:'.$sLanguage; + } + $aLangPrefOrder['short_name'] = 'short_name'; + $aLangPrefOrder['name'] = 'name'; + $aLangPrefOrder['brand'] = 'brand'; + foreach($aLanguages as $sLanguage => $fLanguagePref) + { + $aLangPrefOrder['official_name:'.$sLanguage] = 'official_name:'.$sLanguage; + } + $aLangPrefOrder['official_name'] = 'official_name'; + $aLangPrefOrder['ref'] = 'ref'; + $aLangPrefOrder['type'] = 'type'; + return $aLangPrefOrder; + } +} diff --git a/lib/init-website.php b/lib/init-website.php index 61a41731..9d66a9ac 100644 --- a/lib/init-website.php +++ b/lib/init-website.php @@ -1,6 +1,93 @@ getMessage(); + + echo << + Internal Server Error + +

Internal Server Error

+

Nominatim has encountered an internal error while accessing the database. + This may happen because the database is broken or because of a bug in + the software. If you think it is a bug, feel free to report + it over on + Github. Please include the URL that caused the problem and the + complete error details below.

+

Message: $sMsg

+

SQL Error: $sSqlError

+

Details:

+INTERNALFAIL;
+
+		if (CONST_Debug)
+		{
+			var_dump($oSql);
+		}
+		else
+		{
+			echo "
\n".$oSql->getUserInfo()."
"; + } + + echo "

"; + exit; + } + + function failInternalError($sError, $sSQL = false, $vDumpVar = false) + { + header('HTTP/1.0 500 Internal Server Error'); + header('Content-type: text/html; charset=utf-8'); + echo "

Internal Server Error

"; + echo '

Nominatim has encountered an internal error while processing your request. This is most likely because of a bug in the software.

'; + echo "

Details: ".$sError,"

"; + echo '

Feel free to file an issue on Github. Please include the error message above and the URL you used.

'; + if (CONST_Debug) + { + echo "

Debugging Information


"; + if ($sSQL) + { + echo "

SQL query

".$sSQL.""; + } + if ($vDumpVar) + { + echo "

Result

"; + var_dump($vDumpVar); + echo ""; + } + } + echo "\n\n"; + exit; + } + + + function userError($sError) + { + header('HTTP/1.0 400 Bad Request'); + header('Content-type: text/html; charset=utf-8'); + echo "

Bad Request

"; + echo '

Nominatim has encountered an error with your request.

'; + echo "

Details: ".$sError."

"; + echo '

If you feel this error is incorrect feel file an issue on Github. Please include the error message above and the URL you used.

'; + echo "\n\n"; + exit; + } + + +/*************************************************************************** + * HTTP Reply header setup + */ if (CONST_NoAccessControl) { @@ -13,5 +100,5 @@ } if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') exit; - header('Content-type: text/html; charset=utf-8'); + if (CONST_Debug) header('Content-type: text/html; charset=utf-8'); diff --git a/lib/lib.php b/lib/lib.php index 94bed6d8..3aa80e80 100644 --- a/lib/lib.php +++ b/lib/lib.php @@ -50,62 +50,6 @@ } - function getPreferredLanguages($sLangString=false) - { - if (!$sLangString) - { - // If we have been provided the value in $_GET it overrides browser value - if (isset($_GET['accept-language']) && $_GET['accept-language']) - { - $_SERVER["HTTP_ACCEPT_LANGUAGE"] = $_GET['accept-language']; - $sLangString = $_GET['accept-language']; - } - else if (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])) - { - $sLangString = $_SERVER["HTTP_ACCEPT_LANGUAGE"]; - } - } - - $aLanguages = array(); - if ($sLangString) - { - if (preg_match_all('/(([a-z]{1,8})(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $sLangString, $aLanguagesParse, PREG_SET_ORDER)) - { - foreach($aLanguagesParse as $iLang => $aLanguage) - { - $aLanguages[$aLanguage[1]] = isset($aLanguage[5])?(float)$aLanguage[5]:1 - ($iLang/100); - if (!isset($aLanguages[$aLanguage[2]])) $aLanguages[$aLanguage[2]] = $aLanguages[$aLanguage[1]]/10; - } - arsort($aLanguages); - } - } - if (!sizeof($aLanguages) && CONST_Default_Language) $aLanguages = array(CONST_Default_Language=>1); - foreach($aLanguages as $sLangauge => $fLangauagePref) - { - $aLangPrefOrder['short_name:'.$sLangauge] = 'short_name:'.$sLangauge; - } - foreach($aLanguages as $sLangauge => $fLangauagePref) - { - $aLangPrefOrder['name:'.$sLangauge] = 'name:'.$sLangauge; - } - foreach($aLanguages as $sLangauge => $fLangauagePref) - { - $aLangPrefOrder['place_name:'.$sLangauge] = 'place_name:'.$sLangauge; - } - foreach($aLanguages as $sLangauge => $fLangauagePref) - { - $aLangPrefOrder['official_name:'.$sLangauge] = 'official_name:'.$sLangauge; - } - $aLangPrefOrder['short_name'] = 'short_name'; - $aLangPrefOrder['name'] = 'name'; - $aLangPrefOrder['place_name'] = 'place_name'; - $aLangPrefOrder['official_name'] = 'official_name'; - $aLangPrefOrder['ref'] = 'ref'; - $aLangPrefOrder['type'] = 'type'; - return $aLangPrefOrder; - } - - function getWordSets($aWords, $iDepth) { $aResult = array(array(join(' ',$aWords))); diff --git a/lib/website.php b/lib/website.php deleted file mode 100644 index a6afb698..00000000 --- a/lib/website.php +++ /dev/null @@ -1,140 +0,0 @@ -getMessage(); - - echo << - Internal Server Error - -

Internal Server Error

-

Nominatim has encountered an internal error while accessing the database. - This may happen because the database is broken or because of a bug in - the software. If you think it is a bug, feel free to report - it over on - Github. Please include the URL that caused the problem and the - complete error details below.

-

Message: $sMsg

-

SQL Error: $sSqlError

-

Details:

-INTERNALFAIL;
-
-		if (CONST_Debug)
-		{
-			var_dump($oSql);
-		}
-		else
-		{
-			echo "
\n".$oSql->getUserInfo()."
"; - } - - echo "

"; - exit; - } - - function failInternalError($sError, $sSQL = false, $vDumpVar = false) - { - header('HTTP/1.0 500 Internal Server Error'); - header('Content-type: text/html; charset=utf-8'); - echo "

Internal Server Error

"; - echo '

Nominatim has encountered an internal error while processing your request. This is most likely because of a bug in the software.

'; - echo "

Details: ".$sError,"

"; - echo '

Feel free to file an issue on Github. Please include the error message above and the URL you used.

'; - if (CONST_Debug) - { - echo "

Debugging Information


"; - if ($sSQL) - { - echo "

SQL query

".$sSQL.""; - } - if ($vDumpVar) - { - echo "

Result

"; - var_dump($vDumpVar); - echo ""; - } - } - echo "\n\n"; - exit; - } - - - function userError($sError) - { - header('HTTP/1.0 400 Bad Request'); - header('Content-type: text/html; charset=utf-8'); - echo "

Bad Request

"; - echo '

Nominatim has encountered an error with your request.

'; - echo "

Details: ".$sError."

"; - echo '

If you feel this error is incorrect feel file an issue on Github. Please include the error message above and the URL you used.

'; - echo "\n\n"; - exit; - } - - -/*************************************************************************** - * - * Functions for parsing URL parameters - * - */ - - function getParamBool($sName, $bDefault=false) - { - if (!isset($_GET[$sName]) || strlen($_GET[$sName]) == 0) return $bDefault; - - return (bool) $_GET[$sName]; - } - - function getParamInt($sName, $bDefault=false) - { - if (!isset($_GET[$sName]) || strlen($_GET[$sName]) == 0) 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]) || strlen($_GET[$sName]) == 0) 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]) || strlen($_GET[$sName]) == 0) return $bDefault; - - return $_GET[$sName]; - } - - function getParamSet($sName, $aValues, $sDefault=false) - { - if (!isset($_GET[$sName]) || strlen($_GET[$sName]) == 0) return $sDefault; - - if (!in_array($_GET[$sName], $aValues)) - { - userError("Parameter '$sName' must be one of: ".join(', ', $aValues)); - } - - return $_GET[$sName]; - } diff --git a/settings/defaults.php b/settings/defaults.php new file mode 100644 index 00000000..cdb02924 --- /dev/null +++ b/settings/defaults.php @@ -0,0 +1,105 @@ +://:@:/ + @define('CONST_Database_Web_User', 'www-data'); + @define('CONST_Max_Word_Frequency', '50000'); + @define('CONST_Limit_Reindexing', true); + // Set to false to avoid importing extra postcodes for the US. + @define('CONST_Use_Extra_US_Postcodes', true); + // Set to true after importing Tiger house number data for the US. + // Note: The tables must already exist or queries will throw errors. + // After changing this setting run ./utils/setup --create-functions + // again. + @define('CONST_Use_US_Tiger_Data', false); + // Set to true after importing other external house number data. + // Note: the aux tables must already exist or queries will throw errors. + // After changing this setting run ./utils/setup --create-functions + // again. + @define('CONST_Use_Aux_Location_data', false); + + // Proxy settings + @define('CONST_HTTP_Proxy', false); + @define('CONST_HTTP_Proxy_Host', 'proxy.mydomain.com'); + @define('CONST_HTTP_Proxy_Port', '3128'); + @define('CONST_HTTP_Proxy_Login', ''); + @define('CONST_HTTP_Proxy_Password', ''); + + // Paths + @define('CONST_Osm2pgsql_Binary', CONST_InstallPath.'/osm2pgsql/osm2pgsql'); + @define('CONST_Osmosis_Binary', '/usr/bin/osmosis'); + @define('CONST_Tiger_Data_Path', CONST_BasePath.'/data/tiger'); + + // osm2pgsql settings + @define('CONST_Osm2pgsql_Flatnode_File', null); + + // tablespace settings + // osm2pgsql caching tables (aka slim mode tables) - update only + @define('CONST_Tablespace_Osm2pgsql_Data', false); + @define('CONST_Tablespace_Osm2pgsql_Index', false); + // osm2pgsql output tables (aka main table) - update only + @define('CONST_Tablespace_Place_Data', false); + @define('CONST_Tablespace_Place_Index', false); + // address computation tables - update only + @define('CONST_Tablespace_Address_Data', false); + @define('CONST_Tablespace_Address_Index', false); + // search tables - needed for lookups + @define('CONST_Tablespace_Search_Data', false); + @define('CONST_Tablespace_Search_Index', false); + // additional data, e.g. TIGER data, type searches - needed for lookups + @define('CONST_Tablespace_Aux_Data', false); + @define('CONST_Tablespace_Aux_Index', false); + + // Replication settings + @define('CONST_Replication_Url', 'http://planet.openstreetmap.org/replication/minute'); + @define('CONST_Replication_MaxInterval', '3600'); + @define('CONST_Replication_Update_Interval', '60'); // How often upstream publishes diffs + @define('CONST_Replication_Recheck_Interval', '60'); // How long to sleep if no update found yet + + // Website settings + @define('CONST_NoAccessControl', true); + + @define('CONST_Website_BaseURL', 'http://'.php_uname('n').'/'); + // Language to assume when none is supplied with the query. + // When set to false, the local language (i.e. the name tag without suffix) + // will be used. + @define('CONST_Default_Language', false); + // Appearance of the map in the debug interface. + @define('CONST_Default_Lat', 20.0); + @define('CONST_Default_Lon', 0.0); + @define('CONST_Default_Zoom', 2); + @define('CONST_Map_Tile_URL', 'http://{s}.tile.osm.org/{z}/{x}/{y}.png'); + @define('CONST_Map_Tile_Attribution', ''); // Set if tile source isn't osm.org + + @define('CONST_Search_AreaPolygons', true); + + @define('CONST_Search_BatchMode', false); + + @define('CONST_Search_TryDroppedAddressTerms', false); + @define('CONST_Search_NameOnlySearchFrequencyThreshold', 500); + // If set to true, then reverse order of queries will be tried by default. + // When set to false only selected languages alloow reverse search. + @define('CONST_Search_ReversePlanForAll', true); + + // Maximum number of OSM ids that may be queried at once + // for the places endpoint. + @define('CONST_Places_Max_ID_count', 50); + + // Number of different geometry formats that may be queried in parallel. + // Set to zero to disable polygon output. + @define('CONST_PolygonOutput_MaximumTypes', 1); + + // Log settings + // Set to true to log into new_query_log table. + // You should set up a cron job that regularly clears out this table. + @define('CONST_Log_DB', false); + // Set to a file name to enable logging to a file. + @define('CONST_Log_File', false); + + diff --git a/settings/settings.php b/settings/settings.php index cdb02924..3475ae7b 100644 --- a/settings/settings.php +++ b/settings/settings.php @@ -1,105 +1,4 @@ ://:@:/ - @define('CONST_Database_Web_User', 'www-data'); - @define('CONST_Max_Word_Frequency', '50000'); - @define('CONST_Limit_Reindexing', true); - // Set to false to avoid importing extra postcodes for the US. - @define('CONST_Use_Extra_US_Postcodes', true); - // Set to true after importing Tiger house number data for the US. - // Note: The tables must already exist or queries will throw errors. - // After changing this setting run ./utils/setup --create-functions - // again. - @define('CONST_Use_US_Tiger_Data', false); - // Set to true after importing other external house number data. - // Note: the aux tables must already exist or queries will throw errors. - // After changing this setting run ./utils/setup --create-functions - // again. - @define('CONST_Use_Aux_Location_data', false); - - // Proxy settings - @define('CONST_HTTP_Proxy', false); - @define('CONST_HTTP_Proxy_Host', 'proxy.mydomain.com'); - @define('CONST_HTTP_Proxy_Port', '3128'); - @define('CONST_HTTP_Proxy_Login', ''); - @define('CONST_HTTP_Proxy_Password', ''); - - // Paths - @define('CONST_Osm2pgsql_Binary', CONST_InstallPath.'/osm2pgsql/osm2pgsql'); - @define('CONST_Osmosis_Binary', '/usr/bin/osmosis'); - @define('CONST_Tiger_Data_Path', CONST_BasePath.'/data/tiger'); - - // osm2pgsql settings - @define('CONST_Osm2pgsql_Flatnode_File', null); - - // tablespace settings - // osm2pgsql caching tables (aka slim mode tables) - update only - @define('CONST_Tablespace_Osm2pgsql_Data', false); - @define('CONST_Tablespace_Osm2pgsql_Index', false); - // osm2pgsql output tables (aka main table) - update only - @define('CONST_Tablespace_Place_Data', false); - @define('CONST_Tablespace_Place_Index', false); - // address computation tables - update only - @define('CONST_Tablespace_Address_Data', false); - @define('CONST_Tablespace_Address_Index', false); - // search tables - needed for lookups - @define('CONST_Tablespace_Search_Data', false); - @define('CONST_Tablespace_Search_Index', false); - // additional data, e.g. TIGER data, type searches - needed for lookups - @define('CONST_Tablespace_Aux_Data', false); - @define('CONST_Tablespace_Aux_Index', false); - - // Replication settings - @define('CONST_Replication_Url', 'http://planet.openstreetmap.org/replication/minute'); - @define('CONST_Replication_MaxInterval', '3600'); - @define('CONST_Replication_Update_Interval', '60'); // How often upstream publishes diffs - @define('CONST_Replication_Recheck_Interval', '60'); // How long to sleep if no update found yet - - // Website settings - @define('CONST_NoAccessControl', true); - - @define('CONST_Website_BaseURL', 'http://'.php_uname('n').'/'); - // Language to assume when none is supplied with the query. - // When set to false, the local language (i.e. the name tag without suffix) - // will be used. - @define('CONST_Default_Language', false); - // Appearance of the map in the debug interface. - @define('CONST_Default_Lat', 20.0); - @define('CONST_Default_Lon', 0.0); - @define('CONST_Default_Zoom', 2); - @define('CONST_Map_Tile_URL', 'http://{s}.tile.osm.org/{z}/{x}/{y}.png'); - @define('CONST_Map_Tile_Attribution', ''); // Set if tile source isn't osm.org - - @define('CONST_Search_AreaPolygons', true); - - @define('CONST_Search_BatchMode', false); - - @define('CONST_Search_TryDroppedAddressTerms', false); - @define('CONST_Search_NameOnlySearchFrequencyThreshold', 500); - // If set to true, then reverse order of queries will be tried by default. - // When set to false only selected languages alloow reverse search. - @define('CONST_Search_ReversePlanForAll', true); - - // Maximum number of OSM ids that may be queried at once - // for the places endpoint. - @define('CONST_Places_Max_ID_count', 50); - - // Number of different geometry formats that may be queried in parallel. - // Set to zero to disable polygon output. - @define('CONST_PolygonOutput_MaximumTypes', 1); - - // Log settings - // Set to true to log into new_query_log table. - // You should set up a cron job that regularly clears out this table. - @define('CONST_Log_DB', false); - // Set to a file name to enable logging to a file. - @define('CONST_Log_File', false); - + echo "ERROR: Scripts must be run from build directory.\n"; + exit; diff --git a/tests/features/api/regression.feature b/tests/features/api/regression.feature index 8a436fc3..c50ab7df 100644 --- a/tests/features/api/regression.feature +++ b/tests/features/api/regression.feature @@ -108,13 +108,13 @@ Feature: API regression tests | 0 | Philippstraße | Düren Scenario: trac #2830 - When sending json search query "528, Merkley Drive, K4A 1N5,CA" with address + When sending json search query "207, Boardman Street, S0J 1L0, CA" with address Then result addresses contain - | ID | house_number | road | postcode | country - | 0 | 528 | Merkley Drive | K4A 1N5 | Canada + | ID | house_number | road | postcode | country + | 0 | 207 | Boardman Street | S0J 1L0 | Canada Scenario: trac #2830 - When sending json search query "K4A 1N5,CA" + When sending json search query "S0J 1L0,CA" Then results contain | ID | class | type | display_name | 0 | place | postcode | .*, Canada @@ -134,17 +134,8 @@ Feature: API regression tests Scenario: trac #2871 When looking up coordinates -33.906895553,150.99609375 Then result addresses contain - | ID | city | postcode | country - | 0 | [^0-9]* | 2197 | Australia - - Scenario: trac #2974 - When sending json search query "Azadi Square, Faruj" with address - Then result addresses contain - | ID | road | city - | 0 | ميدان آزادي | فاروج - And results contain - | ID | latlon - | 0 | 37.2323,58.2193 +-1km + | ID | city | country + | 0 | [^0-9]*$ | Australia Scenario: trac #2981 When sending json search query "Ohmstraße 7, Berlin" with address @@ -202,7 +193,7 @@ Feature: API regression tests When sending json search query "" with address Then result addresses contain | ID | road | city - | 0 | Seegasse | Wieselburg-Land + | 0 | Seegasse | .*Wieselburg-Land Examples: | query diff --git a/tests/features/api/search.feature b/tests/features/api/search.feature index 656bfb29..08b2653c 100644 --- a/tests/features/api/search.feature +++ b/tests/features/api/search.feature @@ -9,7 +9,7 @@ Feature: Search queries | road | Thoresby Road | city | Broxtowe | state | England - | country | United Kingdom + | country | U.*K.* | country_code | gb @@ -31,13 +31,13 @@ Feature: Search queries Scenario: House number interpolation even Given the request parameters | accept-language - | en + | en When sending json search query "140 rue Don Bosco, Saguenay" with address Then address of result 0 contains | type | value | house_number | 140 | road | [Rr]ue Don Bosco - | city | Saguenay + | city | .*Saguenay | state | Quebec | country | Canada | country_code | ca @@ -45,13 +45,13 @@ Feature: Search queries Scenario: House number interpolation odd Given the request parameters | accept-language - | en + | en When sending json search query "141 rue Don Bosco, Saguenay" with address Then address of result 0 contains | type | value | house_number | 141 | road | [rR]ue Don Bosco - | city | Saguenay + | city | .*Saguenay | state | Quebec | country | Canada | country_code | ca @@ -73,7 +73,7 @@ Feature: Search queries Scenario: Expansion of Illinois Given the request parameters | accept-language - | en + | en When sending json search query "il, us" Then results contain | ID | display_name diff --git a/tests/features/api/search_params.feature b/tests/features/api/search_params.feature index 0b21d558..5a1c4f81 100644 --- a/tests/features/api/search_params.feature +++ b/tests/features/api/search_params.feature @@ -31,7 +31,6 @@ Feature: Search queries When sending xml search query "Inuvik" with address Then address of result 0 contains | type | value - | city | Inuvik | state | Northwest Territories | country | Canada | country_code | ca diff --git a/utils/query.php b/utils/query.php index 919486ad..a3f51f74 100755 --- a/utils/query.php +++ b/utils/query.php @@ -4,6 +4,7 @@ require_once(dirname(dirname(__FILE__)).'/settings/settings.php'); require_once(CONST_BasePath.'/lib/init-cmd.php'); require_once(CONST_BasePath.'/lib/Geocode.php'); + require_once(CONST_BasePath.'/lib/ParameterParser.php'); ini_set('memory_limit', '800M'); $aCMDOptions = array( @@ -12,45 +13,43 @@ array('quiet', 'q', 0, 1, 0, 0, 'bool', 'Quiet output'), array('verbose', 'v', 0, 1, 0, 0, 'bool', 'Verbose output'), - array('search', '', 0, 1, 1, 1, 'string', 'Search for given term or coordinate'), - - array('accept-language', '', 0, 1, 1, 1, 'string', 'Preferred language order for showing search results'), - array('bounded', '', 0, 1, 0, 0, 'bool', 'Restrict results to given viewbox'), - array('nodedupe', '', 0, 1, 0, 0, 'bool', 'Do not remove duplicate results'), - array('limit', '', 0, 1, 1, 1, 'int', 'Maximum number of results returned (default: 10)'), - array('exclude_place_ids', '', 0, 1, 1, 1, 'string', 'Comma-separated list of place ids to exclude from results'), - array('featureType', '', 0, 1, 1, 1, 'string', 'Restrict results to certain features (country, state,city,settlement)'), - array('countrycodes', '', 0, 1, 1, 1, 'string', 'Comma-separated list of countries to restrict search to'), - array('viewbox', '', 0, 1, 1, 1, 'string', 'Prefer results in given view box') - ); - getCmdOpt($_SERVER['argv'], $aCMDOptions, $aCMDResult, true, true); - - $oDB =& getDB(); - - if (isset($aCMDResult['search']) && $aCMDResult['search']) - { - if (isset($aCMDResult['bounded'])) $aCMDResult['bounded'] = 'true'; - if (isset($aCMDResult['nodedupe'])) $aCMDResult['dedupe'] = 'false'; - - $oGeocode = new Geocode($oDB); - if (isset($aCMDResult['accept-language']) && $aCMDResult['accept-language']) - $oGeocode->setLanguagePreference(getPreferredLanguages($aCMDResult['accept-language'])); - else - $oGeocode->setLanguagePreference(getPreferredLanguages()); - $oGeocode->loadParamArray($aCMDResult); - $oGeocode->setQuery($aCMDResult['search']); - - $aSearchResults = $oGeocode->lookup(); - - if (version_compare(phpversion(), "5.4.0", '<')) - echo json_encode($aSearchResults); - else - echo json_encode($aSearchResults, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)."\n"; - } - else - { - showUsage($aCMDOptions, true); - } - + array('search', '', 0, 1, 1, 1, 'string', 'Search for given term or coordinate'), + + array('accept-language', '', 0, 1, 1, 1, 'string', 'Preferred language order for showing search results'), + array('bounded', '', 0, 1, 0, 0, 'bool', 'Restrict results to given viewbox'), + array('nodedupe', '', 0, 1, 0, 0, 'bool', 'Do not remove duplicate results'), + array('limit', '', 0, 1, 1, 1, 'int', 'Maximum number of results returned (default: 10)'), + array('exclude_place_ids', '', 0, 1, 1, 1, 'string', 'Comma-separated list of place ids to exclude from results'), + array('featureType', '', 0, 1, 1, 1, 'string', 'Restrict results to certain features (country, state,city,settlement)'), + array('countrycodes', '', 0, 1, 1, 1, 'string', 'Comma-separated list of countries to restrict search to'), + array('viewbox', '', 0, 1, 1, 1, 'string', 'Prefer results in given view box') + ); + getCmdOpt($_SERVER['argv'], $aCMDOptions, $aCMDResult, true, true); + + $oDB =& getDB(); + $oParams = new ParameterParser($aCMDResult); + + if ($oParams->getBool('search')) + { + if (isset($aCMDResult['nodedupe'])) $aCMDResult['dedupe'] = 'false'; + + $oGeocode = new Geocode($oDB); + + $oGeocode->setLanguagePreference($oParams->getPreferredLanguages(false)); + $oGeocode->loadParamArray($oParams); + $oGeocode->setQuery($aCMDResult['search']); + + $aSearchResults = $oGeocode->lookup(); + + if (version_compare(phpversion(), "5.4.0", '<')) + echo json_encode($aSearchResults); + else + echo json_encode($aSearchResults, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)."\n"; + } + else + { + showUsage($aCMDOptions, true); + } + diff --git a/vagrant/install-on-centos-7.sh b/vagrant/install-on-centos-7.sh index 7e023cbe..52ae5d0c 100755 --- a/vagrant/install-on-centos-7.sh +++ b/vagrant/install-on-centos-7.sh @@ -28,7 +28,7 @@ # additional packages: sudo yum install -y python-pip python-Levenshtein python-psycopg2 \ - php-phpunit-PHPUnit + python-numpy php-phpunit-PHPUnit pip install --user --upgrade pip setuptools lettuce==0.2.18 six==1.9 \ haversine Shapely pytidylib diff --git a/vagrant/install-on-travis-ci.sh b/vagrant/install-on-travis-ci.sh new file mode 100755 index 00000000..fdaec162 --- /dev/null +++ b/vagrant/install-on-travis-ci.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# This script runs in a travis-ci.org (or .com) virtual machine +# https://docs.travis-ci.com/user/trusty-ci-environment/ +# Ubuntu 14 (trusty) +# user 'travis' +# $TRAVIS_BUILD_DIR is /home/travis/build/twain47/Nominatim/, for more see +# https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables +# Postgres 9.2 installed and started. role 'travis' already superuser +# Python 2.7.10, pip 7.1.2 + +# Travis has a 4 MB, 10000 line output limit, so where possible we supress +# output from installation scripts +# Travis strips color from the output + +sudo service postgresql stop + +sudo apt-get update -qq +sudo apt-get install -y -qq libboost-dev libboost-system-dev \ + libboost-filesystem-dev libexpat1-dev zlib1g-dev libxml2-dev\ + libbz2-dev libpq-dev libgeos-c1 libgeos++-dev libproj-dev \ + postgresql-server-dev-9.3 postgresql-9.3-postgis-2.1 postgresql-contrib-9.3 \ + apache2 php5 php5-pgsql php-pear php-db + +sudo apt-get install -y -qq python-Levenshtein python-shapely \ + python-psycopg2 tidy python-nose python-tidylib \ + python-numpy phpunit + +sudo -H pip install --quiet 'setuptools>=23.0.0' lettuce==0.2.18 'six>=1.9' haversine + +sudo service postgresql restart +sudo -u postgres createuser -S www-data + +# Make sure that system servers can read from the home directory: +chmod a+x $HOME +chmod a+x $TRAVIS_BUILD_DIR + + +sudo tee /etc/apache2/conf-available/nominatim.conf << EOFAPACHECONF > /dev/null + + Options FollowSymLinks MultiViews + AddType text/html .php + Require all granted + + + Alias /nominatim $TRAVIS_BUILD_DIR/build/website +EOFAPACHECONF + + +sudo a2enconf nominatim +sudo service apache2 restart + + +mkdir build +cd build +cmake $TRAVIS_BUILD_DIR +make + + +tee settings/local.php << EOF +getPreferredLanguages(); + $sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted",$aLangPrefOrder))."]"; - ini_set('memory_limit', '200M'); + $sPlaceId = $oParams->getString('place_id'); + $sOsmType = $oParams->getSet('osmtype', array('N', 'W', 'R')); + $iOsmId = $oParams->getInt('osmid', -1); $oDB =& getDB(); - $aLangPrefOrder = getPreferredLanguages(); - $sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted",$aLangPrefOrder))."]"; - - $sPlaceId = getParamString('place_id'); - $sOsmType = getParamSet('osmtype', array('N', 'W', 'R')); - $iOsmId = getParamInt('osmid', -1); if ($sOsmType && $iOsmId > 0) { $sPlaceId = chksql($oDB->getOne("select place_id from placex where osm_type = '".$sOsmType."' and osm_id = ".$iOsmId." order by type = 'postcode' asc")); @@ -125,7 +126,7 @@ $aPlaceSearchNameKeywords = false; $aPlaceSearchAddressKeywords = false; - if (getParamBool('keywords')) + if ($oParams->getBool('keywords')) { $sSQL = "select * from search_name where place_id = $iPlaceID"; $aPlaceSearchName = $oDB->getRow($sSQL); diff --git a/website/hierarchy.php b/website/hierarchy.php index 28a56f00..60d77d6a 100755 --- a/website/hierarchy.php +++ b/website/hierarchy.php @@ -8,16 +8,18 @@ require_once(CONST_BasePath.'/lib/output.php'); ini_set('memory_limit', '200M'); - $oDB =& getDB(); - - $sOutputFormat = getParamSet('format', array('html', 'json'), 'html'); + $oParams = new ParameterParser(); - $aLangPrefOrder = getPreferredLanguages(); + $sOutputFormat = $oParams->getSet('format', array('html', 'json'), 'html'); + $aLangPrefOrder = $oParams->getPreferredLanguages(); $sLanguagePrefArraySQL = "ARRAY[".join(',',array_map("getDBQuoted",$aLangPrefOrder))."]"; - $sPlaceId = getParamString('place_id'); - $sOsmType = getParamSet('osmtype', array('N', 'W', 'R')); - $iOsmId = getParamInt('osmid', -1); + $sPlaceId = $oParams->getString('place_id'); + $sOsmType = $oParams->getSet('osmtype', array('N', 'W', 'R')); + $iOsmId = $oParams->getInt('osmid', -1); + + $oDB =& getDB(); + if ($sOsmType && $iOsmId > 0) { $sPlaceId = chksql($oDB->getOne("select place_id from placex where osm_type = '".$sOsmType."' and osm_id = ".$iOsmId." order by type = 'postcode' asc")); diff --git a/website/lookup.php b/website/lookup.php index 5fc6c309..0129f217 100755 --- a/website/lookup.php +++ b/website/lookup.php @@ -6,15 +6,17 @@ require_once(CONST_BasePath.'/lib/log.php'); require_once(CONST_BasePath.'/lib/PlaceLookup.php'); require_once(CONST_BasePath.'/lib/output.php'); - - $oDB =& getDB(); ini_set('memory_limit', '200M'); + $oParams = new ParameterParser(); + // Format for output - $sOutputFormat = getParamSet('format', array('xml', 'json'), 'xml'); + $sOutputFormat = $oParams->getSet('format', array('xml', 'json'), 'xml'); // Preferred language - $aLangPrefOrder = getPreferredLanguages(); + $aLangPrefOrder = $oParams->getPreferredLanguages(); + + $oDB =& getDB(); $hLog = logStart($oDB, 'place', $_SERVER['QUERY_STRING'], $aLangPrefOrder); @@ -23,11 +25,11 @@ $oPlaceLookup = new PlaceLookup($oDB); $oPlaceLookup->setLanguagePreference($aLangPrefOrder); - $oPlaceLookup->setIncludeAddressDetails(getParamBool('addressdetails', true)); - $oPlaceLookup->setIncludeExtraTags(getParamBool('extratags', false)); - $oPlaceLookup->setIncludeNameDetails(getParamBool('namedetails', false)); + $oPlaceLookup->setIncludeAddressDetails($oParams->getBool('addressdetails', true)); + $oPlaceLookup->setIncludeExtraTags($oParams->getBool('extratags', false)); + $oPlaceLookup->setIncludeNameDetails($oParams->getBool('namedetails', false)); - $aOsmIds = explode(',', getParamString('osm_ids', '')); + $aOsmIds = explode(',', $oParams->getString('osm_ids', '')); if (count($aOsmIds) > CONST_Places_Max_ID_count) { diff --git a/website/polygons.php b/website/polygons.php index b855214a..1e0f5f7e 100755 --- a/website/polygons.php +++ b/website/polygons.php @@ -5,12 +5,14 @@ require_once(CONST_BasePath.'/lib/output.php'); ini_set('memory_limit', '200M'); - $oDB =& getDB(); + $oParams = new ParameterParser(); $sOutputFormat = 'html'; - $iDays = getParamInt('days', 1); - $bReduced = getParamBool('reduced', false); - $sClass = getParamString('class', false); + $iDays = $oParams->getInt('days', 1); + $bReduced = $oParams->getBool('reduced', false); + $sClass = $oParams->getString('class', false); + + $oDB =& getDB(); $iTotalBroken = (int) chksql($oDB->getOne('select count(*) from import_polygon_error')); diff --git a/website/reverse.php b/website/reverse.php index f7c01860..50ce4787 100755 --- a/website/reverse.php +++ b/website/reverse.php @@ -7,11 +7,14 @@ require_once(CONST_BasePath.'/lib/PlaceLookup.php'); require_once(CONST_BasePath.'/lib/ReverseGeocode.php'); require_once(CONST_BasePath.'/lib/output.php'); + ini_set('memory_limit', '200M'); + + $oParams = new ParameterParser(); - $bAsGeoJSON = getParamBool('polygon_geojson'); - $bAsKML = getParamBool('polygon_kml'); - $bAsSVG = getParamBool('polygon_svg'); - $bAsText = getParamBool('polygon_text'); + $bAsGeoJSON = $oParams->getBool('polygon_geojson'); + $bAsKML = $oParams->getBool('polygon_kml'); + $bAsSVG = $oParams->getBool('polygon_svg'); + $bAsText = $oParams->getBool('polygon_text'); if ((($bAsGeoJSON?1:0) + ($bAsKML?1:0) + ($bAsSVG?1:0) + ($bAsText?1:0)) > CONST_PolygonOutput_MaximumTypes) { @@ -23,36 +26,32 @@ { userError("Polygon output is disabled"); } - exit; } - // Polygon simplification threshold (optional) - $fThreshold = getParamFloat('polygon_threshold', 0.0); - - - $oDB =& getDB(); - ini_set('memory_limit', '200M'); + $fThreshold = $oParams->getFloat('polygon_threshold', 0.0); // Format for output - $sOutputFormat = getParamSet('format', array('html', 'xml', 'json', 'jsonv2'), 'xml'); + $sOutputFormat = $oParams->getSet('format', array('html', 'xml', 'json', 'jsonv2'), 'xml'); // Preferred language - $aLangPrefOrder = getPreferredLanguages(); + $aLangPrefOrder = $oParams->getPreferredLanguages(); + + $oDB =& getDB(); $hLog = logStart($oDB, 'reverse', $_SERVER['QUERY_STRING'], $aLangPrefOrder); $oPlaceLookup = new PlaceLookup($oDB); $oPlaceLookup->setLanguagePreference($aLangPrefOrder); - $oPlaceLookup->setIncludeAddressDetails(getParamBool('addressdetails', true)); - $oPlaceLookup->setIncludeExtraTags(getParamBool('extratags', false)); - $oPlaceLookup->setIncludeNameDetails(getParamBool('namedetails', false)); - - $sOsmType = getParamSet('osm_type', array('N', 'W', 'R')); - $iOsmId = getParamInt('osm_id', -1); - $fLat = getParamFloat('lat'); - $fLon = getParamFloat('lon'); + $oPlaceLookup->setIncludeAddressDetails($oParams->getBool('addressdetails', true)); + $oPlaceLookup->setIncludeExtraTags($oParams->getBool('extratags', false)); + $oPlaceLookup->setIncludeNameDetails($oParams->getBool('namedetails', false)); + + $sOsmType = $oParams->getSet('osm_type', array('N', 'W', 'R')); + $iOsmId = $oParams->getInt('osm_id', -1); + $fLat = $oParams->getFloat('lat'); + $fLon = $oParams->getFloat('lon'); if ($sOsmType && $iOsmId > 0) { $aPlace = $oPlaceLookup->lookupOSMID($sOsmType, $iOsmId); @@ -60,7 +59,7 @@ else if ($fLat !== false && $fLon !== false) { $oReverseGeocode = new ReverseGeocode($oDB); - $oReverseGeocode->setZoom(getParamInt('zoom', 18)); + $oReverseGeocode->setZoom($oParams->getInt('zoom', 18)); $aLookup = $oReverseGeocode->lookup($fLat, $fLon); if (CONST_Debug) var_dump($aLookup); diff --git a/website/search.php b/website/search.php index 4c283d1a..cff9bb37 100755 --- a/website/search.php +++ b/website/search.php @@ -6,14 +6,14 @@ require_once(CONST_BasePath.'/lib/log.php'); require_once(CONST_BasePath.'/lib/Geocode.php'); require_once(CONST_BasePath.'/lib/output.php'); - ini_set('memory_limit', '200M'); $oDB =& getDB(); + $oParams = new ParameterParser(); $oGeocode = new Geocode($oDB); - $aLangPrefOrder = getPreferredLanguages(); + $aLangPrefOrder = $oParams->getPreferredLanguages(); $oGeocode->setLanguagePreference($aLangPrefOrder); if (CONST_Search_ReversePlanForAll @@ -26,21 +26,21 @@ } // Format for output - $sOutputFormat = getParamSet('format', array('html', 'xml', 'json', 'jsonv2'), 'html'); + $sOutputFormat = $oParams->getSet('format', array('html', 'xml', 'json', 'jsonv2'), 'html'); // Show / use polygons if ($sOutputFormat == 'html') { - $oGeocode->setIncludePolygonAsText(getParamBool('polygon')); + $oGeocode->setIncludePolygonAsText($oParams->getBool('polygon')); $bAsText = false; } else { - $bAsPoints = getParamBool('polygon'); - $bAsGeoJSON = getParamBool('polygon_geojson'); - $bAsKML = getParamBool('polygon_kml'); - $bAsSVG = getParamBool('polygon_svg'); - $bAsText = getParamBool('polygon_text'); + $bAsPoints = $oParams->getBool('polygon'); + $bAsGeoJSON = $oParams->getBool('polygon_geojson'); + $bAsKML = $oParams->getBool('polygon_kml'); + $bAsSVG = $oParams->getBool('polygon_svg'); + $bAsText = $oParams->getBool('polygon_text'); if ( ( ($bAsGeoJSON?1:0) + ($bAsKML?1:0) + ($bAsSVG?1:0) @@ -66,9 +66,9 @@ } // Polygon simplification threshold (optional) - $oGeocode->setPolygonSimplificationThreshold(getParamFloat('polygon_threshold', 0.0)); + $oGeocode->setPolygonSimplificationThreshold($oParams->getFloat('polygon_threshold', 0.0)); - $oGeocode->loadParamArray($_GET); + $oGeocode->loadParamArray($oParams); if (CONST_Search_BatchMode && isset($_GET['batch'])) { @@ -77,8 +77,9 @@ foreach($aBatch as $aBatchParams) { $oBatchGeocode = clone $oGeocode; - $oBatchGeocode->loadParamArray($aBatchParams); - $oBatchGeocode->setQueryFromParams($aBatchParams); + $oBatchParams = new ParameterParser($aBatchParams); + $oBatchGeocode->loadParamArray($oBatchParams); + $oBatchGeocode->setQueryFromParams($oBatchParams); $aSearchResults = $oBatchGeocode->lookup(); $aBatchResults[] = $aSearchResults; } @@ -86,7 +87,10 @@ exit; } - if (!getParamString('q') && isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'][0] == '/') + $oGeocode->setQueryFromParams($oParams); + + if (!$oGeocode->getQueryString() + && isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'][0] == '/') { $sQuery = substr(rawurldecode($_SERVER['PATH_INFO']), 1); @@ -96,10 +100,6 @@ $sQuery = join(', ',$aPhrases); $oGeocode->setQuery($sQuery); } - else - { - $oGeocode->setQueryFromParams($_GET); - } $hLog = logStart($oDB, 'search', $oGeocode->getQueryString(), $aLangPrefOrder);