From de7dd4b64f8779b020e1d1e5d1e6b2f48f6b1f95 Mon Sep 17 00:00:00 2001 From: Peter Knut Date: Wed, 14 Aug 2024 00:33:16 +0200 Subject: [PATCH] Improve URL and email detection --- adminer/include/adminer.inc.php | 2 +- adminer/include/editing.inc.php | 4 ++-- adminer/include/functions.inc.php | 32 +++++++++++++++++++++---------- changes.txt | 1 + editor/include/adminer.inc.php | 2 +- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/adminer/include/adminer.inc.php b/adminer/include/adminer.inc.php index 2e2c41f9..82315054 100644 --- a/adminer/include/adminer.inc.php +++ b/adminer/include/adminer.inc.php @@ -293,7 +293,7 @@ class Adminer { if (preg_match('~json~', $field["type"])) { $return = "$return"; } - return ($link ? "$return" : $return); + return ($link ? "$return" : $return); } /** Value conversion used in select and edit diff --git a/adminer/include/editing.inc.php b/adminer/include/editing.inc.php index 5e12d44b..34617afa 100644 --- a/adminer/include/editing.inc.php +++ b/adminer/include/editing.inc.php @@ -72,7 +72,7 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0) $link .= "&where" . urlencode("[" . bracket_escape($col) . "]") . "=" . urlencode($row[$j]); } } - } elseif (is_url($val)) { + } elseif (is_web_url($val)) { $link = $val; } if ($val === null) { @@ -86,7 +86,7 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0) } } if ($link) { - $val = "$val"; + $val = "$val"; } echo "$val"; } diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index aa3b3678..d259f761 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -1250,7 +1250,7 @@ function select_value($val, $link, $field, $text_length) { if (is_mail($val)) { $link = "mailto:$val"; } - if (is_url($val)) { + if (is_web_url($val)) { $link = $val; // IE 11 and all modern browsers hide referrer } } @@ -1271,20 +1271,32 @@ function select_value($val, $link, $field, $text_length) { * @param string * @return bool */ -function is_mail($email) { - $atom = '[-a-z0-9!#$%&\'*+/=?^_`{|}~]'; // characters of local-name - $domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component - $pattern = "$atom+(\\.$atom+)*@($domain?\\.)+$domain"; - return is_string($email) && preg_match("(^$pattern(,\\s*$pattern)*\$)i", $email); +function is_mail($value) { + return is_string($value) && filter_var($value, FILTER_VALIDATE_EMAIL); } -/** Check whether the string is URL address +/** Check whether the string is web URL address * @param string * @return bool */ -function is_url($string) { - $domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component //! IDN - return preg_match("~^(https?)://($domain?\\.)+$domain(:\\d+)?(/.*)?(\\?.*)?(#.*)?\$~i", $string); //! restrict path, query and fragment characters +function is_web_url($value) { + if (!is_string($value) || !preg_match('~^https?://~i', $value)) { + return false; + } + + $components = parse_url($value); + if (!$components) { + return false; + } + + // Encode URL path. If path was encoded already, it will be encoded twice, but we are OK with that. + $encodedParts = array_map('urlencode', explode('/', $components['path'])); + $url = str_replace($components['path'], implode('/', $encodedParts), $value); + + parse_str($components['query'], $params); + $url = str_replace($components['query'], http_build_query($params), $url); + + return (bool)filter_var($url, FILTER_VALIDATE_URL); } /** Check if field should be shortened diff --git a/changes.txt b/changes.txt index 5bdfc672..997fd102 100644 --- a/changes.txt +++ b/changes.txt @@ -6,6 +6,7 @@ Adminer 4.9.0-dev: - Elasticsearch 5: Make unusable driver usable again, move it to plugins. - Add new Elasticsearch 7 driver. - Set saving to file as a default export option. +- Improve URL and email detection. - Update composer.json. Adminer 4.8.2 (released 2024-03-16): diff --git a/editor/include/adminer.inc.php b/editor/include/adminer.inc.php index e8fed7ac..1198f2f0 100644 --- a/editor/include/adminer.inc.php +++ b/editor/include/adminer.inc.php @@ -202,7 +202,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5 $return = (preg_match('~^(1|t|true|y|yes|on)$~i', $val) ? lang('yes') : lang('no')); } if ($link) { - $return = "$return"; + $return = "$return"; } if (!$link && !like_bool($field) && preg_match(number_type(), $field["type"])) { $return = "
$return
"; // Firefox doesn't support