From 2029bb3ca9708fc1d73bf7b560ae656dca6d2f5d Mon Sep 17 00:00:00 2001 From: e-dschungel Date: Sat, 24 Aug 2024 07:46:20 +0200 Subject: [PATCH] make parsing of numeric parameters more robust (#39) * make parsing of numeric parameters more robust accepts now spaces between parameter name and =|:, between =|: and number and integers instead of floats * fix copy paste error * require php 8.0 minimum * fix formatting + style * make parsing of numeric parameters more robust accepts now spaces between parameter name and =|:, between =|: and number and integers instead of floats * fix copy paste error * require php 8.0 minimum * fix formatting + style * Update plugin.info.txt * Update geotag.php * fix return type --------- Co-authored-by: Mark Prins <1165786+mprins@users.noreply.github.com> --- composer.json | 2 +- plugin.info.txt | 2 +- syntax/geotag.php | 70 +++++++++++++++++++++++++++++++++-------------- 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/composer.json b/composer.json index 17d592b..59c90d8 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ } ], "require": { - "php": ">=7.4" + "php": ">=8.0" }, "config": { "platform": { diff --git a/plugin.info.txt b/plugin.info.txt index 1c340b5..3ad55b3 100644 --- a/plugin.info.txt +++ b/plugin.info.txt @@ -1,7 +1,7 @@ base geotag author Mark C. Prins email mprins@users.sf.net -date 2023-07-14 +date 2024-08-24 name geotag plugin desc Allow a user to annotate pages with a geotag url https://www.dokuwiki.org/plugin:geotag diff --git a/syntax/geotag.php b/syntax/geotag.php index 9d24369..918b1bf 100644 --- a/syntax/geotag.php +++ b/syntax/geotag.php @@ -15,6 +15,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + use dokuwiki\Extension\SyntaxPlugin; use geoPHP\Geometry\Point; @@ -72,9 +73,9 @@ final public function handle($match, $state, $pos, Doku_Handler $handler): array { $tags = trim(substr($match, 9, -2)); // parse geotag content - preg_match("(lat[:|=]-?\d*\.\d*)", $tags, $lat); - preg_match("(lon[:|=]-?\d*\.\d*)", $tags, $lon); - preg_match("(alt[:|=]-?\d*\.?\d*)", $tags, $alt); + $lat = $this->parseNumericParameter("lat", $tags); + $lon = $this->parseNumericParameter("lon", $tags); + $alt = $this->parseNumericParameter("alt", $tags); preg_match("/(region[:|=][\p{L}\s\w'-]*)/u", $tags, $region); preg_match("/(placename[:|=][\p{L}\s\w'-]*)/u", $tags, $placename); preg_match("/(country[:|=][\p{L}\s\w'-]*)/u", $tags, $country); @@ -98,9 +99,33 @@ final public function handle($match, $state, $pos, Doku_Handler $handler): array } elseif (array_key_exists(0, $hide) && trim($hide [0]) === 'unhide') { $style = ''; } + return [ + hsc($lat), + hsc($lon), + hsc($alt), + $this->geohash($lat, $lon), + hsc(trim(substr(($region[0] ?? ''), 7))), + hsc(trim(substr(($placename[0] ?? ''), 10))), + hsc(trim(substr(($country [0] ?? ''), 8))), + hsc($showlocation), $style + ]; + } - $data = [hsc(trim(substr($lat [0], 4))), hsc(trim(substr($lon [0], 4))), hsc(trim(substr(($alt[0] ?? ''), 4))), $this->geohash(substr($lat [0], 4), substr($lon [0], 4)), hsc(trim(substr(($region[0] ?? ''), 7))), hsc(trim(substr(($placename[0] ?? ''), 10))), hsc(trim(substr(($country [0] ?? ''), 8))), hsc($showlocation), $style]; - return $data; + /** + * parses numeric parameter with given name + * + * @param string $name name of the parameter + * @param string $input text to consume + * @return string parameter values as numeric string or empty string if nothing is found + */ + private function parseNumericParameter(string $name, string $input): string + { + $output = ''; + $pattern = "/" . $name . "\s*[:=]\s*(-?\d*\.?\d*)/"; + if (preg_match($pattern, $input, $matches)) { + $output = $matches[1]; + } + return $output; } /** @@ -108,10 +133,12 @@ final public function handle($match, $state, $pos, Doku_Handler $handler): array * * @param float $lat * @param float $lon + * @return string + * @throws Exception */ - private function geohash(float $lat, float $lon) + private function geohash(float $lat, float $lon): string { - if (($geophp = plugin_load('helper', 'geophp')) === null) { + if ((plugin_load('helper', 'geophp')) === null) { return ""; } @@ -142,16 +169,16 @@ final public function render($format, Doku_Renderer $renderer, $data): bool if ($this->getConf('geotag_prevent_microformat_render')) { return true; } - $searchPre = ''; + $searchPre = ''; $searchPost = ''; if ($this->getConf('geotag_showsearch')) { if (($spHelper = plugin_load('helper', 'spatialhelper_search')) !== null) { - $title = $this->getLang('findnearby') . ' ' . $placename; - $url = wl( + $title = $this->getLang('findnearby') . ' ' . $placename; + $url = wl( getID(), - ['do' => 'findnearby', 'lat' => $ddlat, 'lon' => $ddlon] + ['do' => 'findnearby', 'lat' => $ddlat, 'lon' => $ddlon] ); - $searchPre = ''; + $searchPre = ''; $searchPost = '' . $title . ''; } } @@ -174,12 +201,12 @@ final public function render($format, Doku_Renderer $renderer, $data): bool return true; } elseif ($format === 'metadata') { // render metadata (our action plugin will put it in the page head) - $renderer->meta ['geo'] ['lat'] = $ddlat; - $renderer->meta ['geo'] ['lon'] = $ddlon; + $renderer->meta ['geo'] ['lat'] = $ddlat; + $renderer->meta ['geo'] ['lon'] = $ddlon; $renderer->meta ['geo'] ['placename'] = $placename; - $renderer->meta ['geo'] ['region'] = $region; - $renderer->meta ['geo'] ['country'] = $country; - $renderer->meta ['geo'] ['geohash'] = $geohash; + $renderer->meta ['geo'] ['region'] = $region; + $renderer->meta ['geo'] ['country'] = $country; + $renderer->meta ['geo'] ['geohash'] = $geohash; if (!empty($alt)) { $renderer->meta ['geo'] ['alt'] = $alt; } @@ -205,6 +232,7 @@ final public function render($format, Doku_Renderer $renderer, $data): bool * convert latitude in decimal degrees to DMS+hemisphere. * * @param float $decimaldegrees + * @return string * @todo move this into a shared library */ private function convertLat(float $decimaldegrees): string @@ -227,11 +255,11 @@ private function convertLat(float $decimaldegrees): string */ private function convertDDtoDMS(float $decimaldegrees): string { - $dms = floor($decimaldegrees); + $dms = floor($decimaldegrees); $secs = ($decimaldegrees - $dms) * 3600; - $min = floor($secs / 60); - $sec = round($secs - ($min * 60), 3); - $dms .= 'º' . $min . '\'' . $sec . '"'; + $min = floor($secs / 60); + $sec = round($secs - ($min * 60), 3); + $dms .= 'º' . $min . '\'' . $sec . '"'; return $dms; }