diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 7ba18706510..097a0e9a18a 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1962,6 +1962,7 @@ function dol_escape_htmltag($stringtoescape, $keepb = 0, $keepn = 0, $noescapeta $tmparrayoftags = explode(',', $noescapetags); } if (count($tmparrayoftags)) { + $reg = array(); $tmp = str_ireplace('__DOUBLEQUOTE', '', $tmp); // The keyword DOUBLEQUOTE is forbidden. Reserved, so we removed it if we find it. foreach ($tmparrayoftags as $tagtoreplace) { @@ -1970,30 +1971,37 @@ function dol_escape_htmltag($stringtoescape, $keepb = 0, $keepn = 0, $noescapeta $tmp = preg_replace('/<'.preg_quote($tagtoreplace, '/').' \/>/', '__BEGINENDTAGTOREPLACE'.$tagtoreplace.'__', $tmp); // For case of tag with attribute - $reg = array(); - if (preg_match('/<'.preg_quote($tagtoreplace, '/').'\s+([^>]+)>/', $tmp, $reg)) { - $tmpattributes = str_ireplace(array('[', ']'), '_', $reg[1]); // We must never have [ ] inside the attribute string - $tmpattributes = str_ireplace('href="http:', '__HREFHTTPA', $tmpattributes); - $tmpattributes = str_ireplace('href="https:', '__HREFHTTPSA', $tmpattributes); - $tmpattributes = str_ireplace('src="http:', '__SRCHTTPIMG', $tmpattributes); - $tmpattributes = str_ireplace('src="https:', '__SRCHTTPSIMG', $tmpattributes); - $tmpattributes = str_ireplace('"', '__DOUBLEQUOTE', $tmpattributes); - $tmpattributes = preg_replace('/[^a-z0-9_\/\?\;:\s=&\.-]/i', '', $tmpattributes); - //$tmpattributes = preg_replace("/float:\s*(left|right)/", "", $tmpattributes); // Disabled: we must avoid escaping but not remove content - $tmp = preg_replace('/<'.preg_quote($tagtoreplace, '/').'\s+([^>]+)>/', '__BEGINTAGTOREPLACE'.$tagtoreplace.'['.$tmpattributes.']__', $tmp); - } - if (preg_match('/<'.preg_quote($tagtoreplace, '/').'\s+([^>]+)> \/>/', $tmp, $reg)) { - $tmpattributes = str_ireplace(array('[', ']'), '_', $reg[1]); // We must not have [ ] inside the attribute string - $tmpattributes = str_ireplace('"', '__DOUBLEQUOTE', $tmpattributes); - $tmpattributes = preg_replace('/[^a-z0-9_\/\?\;:\s=&]/i', '', $tmpattributes); - //$tmpattributes = preg_replace("/float:\s*(left|right)/", "", $tmpattributes); // Disabled: we must avoid escaping but not remove content - $tmp = preg_replace('/<'.preg_quote($tagtoreplace, '/').'\s+([^>]+) \/>/', '__BEGINENDTAGTOREPLACE'.$tagtoreplace.'['.$tmpattributes.']__', $tmp); - } + do { + $tmpold = $tmp; + + if (preg_match('/<'.preg_quote($tagtoreplace, '/').'\s+([^>]+)>/', $tmp, $reg)) { + $tmpattributes = str_ireplace(array('[', ']'), '_', $reg[1]); // We must never have [ ] inside the attribute string + $tmpattributes = str_ireplace('href="http:', '__HREFHTTPA', $tmpattributes); + $tmpattributes = str_ireplace('href="https:', '__HREFHTTPSA', $tmpattributes); + $tmpattributes = str_ireplace('src="http:', '__SRCHTTPIMG', $tmpattributes); + $tmpattributes = str_ireplace('src="https:', '__SRCHTTPSIMG', $tmpattributes); + $tmpattributes = str_ireplace('"', '__DOUBLEQUOTE', $tmpattributes); + $tmpattributes = preg_replace('/[^a-z0-9_\/\?\;\s=&\.\-@:\.#\+]/i', '', $tmpattributes); + //$tmpattributes = preg_replace("/float:\s*(left|right)/", "", $tmpattributes); // Disabled: we must not remove content + $tmp = preg_replace('/<'.preg_quote($tagtoreplace, '/').'\s+'.preg_quote($reg[1], '/').'>/', '__BEGINTAGTOREPLACE'.$tagtoreplace.'['.$tmpattributes.']__', $tmp); + } + if (preg_match('/<'.preg_quote($tagtoreplace, '/').'\s+([^>]+)\s+\/>/', $tmp, $reg)) { + $tmpattributes = str_ireplace(array('[', ']'), '_', $reg[1]); // We must not have [ ] inside the attribute string + $tmpattributes = str_ireplace('"', '__DOUBLEQUOTE', $tmpattributes); + $tmpattributes = preg_replace('/[^a-z0-9_\/\?\;\s=&\.\-@:\.#\+]/i', '', $tmpattributes); + //$tmpattributes = preg_replace("/float:\s*(left|right)/", "", $tmpattributes); // Disabled: we must not remove content. + $tmp = preg_replace('/<'.preg_quote($tagtoreplace, '/').'\s+'.preg_quote($reg[1], '/').'\s+\/>/', '__BEGINENDTAGTOREPLACE'.$tagtoreplace.'['.$tmpattributes.']__', $tmp); + } + + $diff = strcmp($tmpold, $tmp); + } while ($diff); } } $result = htmlentities($tmp, ENT_COMPAT, 'UTF-8'); // Convert & into & and more... + //print $result; + if (count($tmparrayoftags)) { foreach ($tmparrayoftags as $tagtoreplace) { $result = str_ireplace('__BEGINTAGTOREPLACE'.$tagtoreplace.'__', '<'.$tagtoreplace.'>', $result); diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index 419db999be2..07c5f1e88f1 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -1106,10 +1106,10 @@ class FunctionsLibTest extends CommonClassTest /** - * testDolEscapeHtmlTag - * - * @return void - */ + * testDolEscapeHtmlTag + * + * @return void + */ public function testDolEscapeHtmlTag() { $input = 'x&#,"'; // & and " are converted into html entities, are removed @@ -1123,6 +1123,18 @@ class FunctionsLibTest extends CommonClassTest $input = ''; // & and " are converted into html entities, are not removed $result = dol_escape_htmltag($input, 1, 1, 'common', 0, 1); $this->assertEquals('', $result); + + + $input = '
+ +
+
A text here and more
+ abc+def@domain.com
+ https://www.another-domain.com
+
'; + + $result = dol_escape_htmltag($input, 1, 1, 'common'); + $this->assertEquals($input, $result); }