diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 9e277fd706b..aa146aebf10 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -1032,21 +1032,19 @@ class Contrat extends CommonObject } // Insert business contacts ('SALESREPFOLL','contrat') - if (!$error) - { + if (!$error) { $result = $this->add_contact($this->commercial_suivi_id, 'SALESREPFOLL', 'internal'); if ($result < 0) $error++; } - if (!$error) - { + if (!$error) { if (!empty($this->linkedObjectsIds) && empty($this->linked_objects)) // To use new linkedObjectsIds instead of old linked_objects { $this->linked_objects = $this->linkedObjectsIds; // TODO Replace linked_objects with linkedObjectsIds } // Add object linked - if (!$error && $this->id && is_array($this->linked_objects) && !empty($this->linked_objects)) + if (!$error && $this->id && !empty($this->linked_objects) && is_array($this->linked_objects)) { foreach ($this->linked_objects as $origin => $tmp_origin_id) { @@ -1144,10 +1142,10 @@ class Contrat extends CommonObject /** - * Supprime l'objet de la base + * Delete object * - * @param User $user Utilisateur qui supprime - * @return int < 0 si erreur, > 0 si ok + * @param User $user User that deletes + * @return int < 0 if KO, > 0 if OK */ public function delete($user) { diff --git a/htdocs/core/actions_extrafields.inc.php b/htdocs/core/actions_extrafields.inc.php index d5936a6dadb..2b5b38441e0 100644 --- a/htdocs/core/actions_extrafields.inc.php +++ b/htdocs/core/actions_extrafields.inc.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2011-2020 Laurent Destailleur * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -356,6 +356,9 @@ if ($action == 'update') $visibility = GETPOST('list', 'alpha'); if ($type == 'separate') $visibility = 3; + // Example: is_object($object) ? ($object->id < 10 ? round($object->id / 2, 2) : (2 * $user->id) * (int) substr($mysoc->zip, 1, 2)) : 'objnotdefined' + $computedvalue = GETPOST('computed_value', 'nohtml'); + $result = $extrafields->update( GETPOST('attrname', 'aZ09'), GETPOST('label', 'alpha'), @@ -371,7 +374,7 @@ if ($action == 'update') $visibility, GETPOST('help', 'alpha'), GETPOST('default_value', 'alpha'), - GETPOST('computed_value', 'alpha'), + $computedvalue, (GETPOST('entitycurrentorall', 'alpha') ? 0 : ''), GETPOST('langfile'), GETPOST('enabled', 'alpha'), diff --git a/htdocs/core/class/translate.class.php b/htdocs/core/class/translate.class.php index 18169c8e5ce..11e67104f9a 100644 --- a/htdocs/core/class/translate.class.php +++ b/htdocs/core/class/translate.class.php @@ -624,7 +624,7 @@ class Translate // we want to keep '"' '' '' '' '' '
' '< ' '' that are reliable HTML tags inside translation strings. $str = str_replace( array('"', '', '', '', '', '', '', '
', '
', '', '', '
', '
', '', '< ', '>'), // We accept '< ' but not '<'. We can accept however '>' - array('__quot__', '__tagb__', '__tagbend__', '__tagu__', '__taguend__', '__tagi__', '__tagiend__', '__tagcenter__', '__tagcenterend__', '__tagb__', '__tagbend__', '__taga__', '__tagaend__', '__tagbr__', '__tagspan__', '__tagspanend__', '__lt__', '__gt__'), + array('__quot__', '__tagb__', '__tagbend__', '__tagu__', '__taguend__', '__tagi__', '__tagiend__', '__tagcenter__', '__tagcenterend__', '__tagb__', '__tagbend__', '__taga__', '__tagaend__', '__tagbr__', '__tagspan__', '__tagspanend__', '__ltspace__', '__gt__'), $str ); @@ -638,8 +638,8 @@ class Translate // Restore reliable HTML tags into original translation string $str = str_replace( - array('__quot__', '__tagb__', '__tagbend__', '__tagu__', '__taguend__', '__tagi__', '__tagiend__', '__tagcenter__', '__tagcenterend__', '__taga__', '__tagaend__', '__tagbr__', '__tagspan__', '__tagspanend__', '__lt__', '__gt__'), - array('"', '', '', '', '', '', '', '
', '
', '
', '
', '', '< ', '> '), + array('__quot__', '__tagb__', '__tagbend__', '__tagu__', '__taguend__', '__tagi__', '__tagiend__', '__tagcenter__', '__tagcenterend__', '__taga__', '__tagaend__', '__tagbr__', '__tagspan__', '__tagspanend__', '__ltspace__', '__gt__'), + array('"', '', '', '', '', '', '', '
', '
', '
', '
', '', '< ', '>'), $str ); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index babf1129e6e..2886b140539 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5701,9 +5701,11 @@ function dol_string_nohtmltag($stringtoclean, $removelinefeed = 1, $pagecodeto = if ($removelinefeed == 2) $stringtoclean = preg_replace('/]*>(\n|\r)+/ims', '
', $stringtoclean); $temp = preg_replace('/]*>/i', "\n", $stringtoclean); - // We remove entities BEFORE stripping (in case of a separator char is encoded and not the other, the strip will fails) + // We remove entities BEFORE stripping (in case of an open separator char that is entity encoded and not the closing other, the strip will fails) $temp = dol_html_entity_decode($temp, ENT_COMPAT | ENT_HTML5, $pagecodeto); + $temp = str_replace('< ', '__ltspace__', $temp); + if ($strip_tags) { $temp = strip_tags($temp); } else { @@ -5727,16 +5729,19 @@ function dol_string_nohtmltag($stringtoclean, $removelinefeed = 1, $pagecodeto = } } + $temp = str_replace('__ltspace__', '< ', $temp); + return trim($temp); } /** * Clean a string to keep only desirable HTML tags. + * WARNING: This also clean HTML comments (used to obfuscate tag name). * * @param string $stringtoclean String to clean * @param int $cleanalsosomestyles Remove absolute/fixed positioning from inline styles * @param int $removeclassattribute Remove the class attribute from tags - * @param int $cleanalsojavascript Remove also occurence of (javascript:' + * @param int $cleanalsojavascript Remove also occurence of 'javascript:'. * @return string String cleaned * * @see dol_escape_htmltag() strip_tags() dol_string_nohtmltag() dol_string_neverthesehtmltags() @@ -5754,16 +5759,21 @@ function dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles = 1, $stringtoclean = dol_string_nounprintableascii($stringtoclean, 0); $stringtoclean = preg_replace('/:/i', ':', $stringtoclean); + $stringtoclean = preg_replace('//', '', $stringtoclean); + $stringtoclean = preg_replace('/:|:|:/i', '', $stringtoclean); // refused string ':' encoded (no reason to have it encoded) to lock 'javascript:...' + $stringtoclean = preg_replace('/javascript\s*:/i', '', $stringtoclean); + $temp = strip_tags($stringtoclean, $allowed_tags_string); if ($cleanalsosomestyles) { // Clean for remaining html tags - $stringtoclean = preg_replace('/position\s*:\s*(absolute|fixed)\s*!\s*important/i', '', $temp); // Note: If hacker try to introduce css comment into string to bypass this regex, the string must also be encoded by the dol_htmlentitiesbr during output so it become harmless + $temp = preg_replace('/position\s*:\s*(absolute|fixed)\s*!\s*important/i', '', $temp); // Note: If hacker try to introduce css comment into string to bypass this regex, the string must also be encoded by the dol_htmlentitiesbr during output so it become harmless } if ($removeclassattribute) { // Clean for remaining html tags - $stringtoclean = preg_replace('/(<[^>]+)\s+class=((["\']).*?\\3|\\w*)/i', '\\1', $temp); + $temp = preg_replace('/(<[^>]+)\s+class=((["\']).*?\\3|\\w*)/i', '\\1', $temp); } // Remove 'javascript:' that we should not find into a text with + // Warning: This is not reliable to fight against obfuscated javascript, there is a lot of other solution to include js into a common html tag (only filtered by the GETPOST). if ($cleanalsojavascript) { $temp = preg_replace('/javascript\s*:/i', '', $temp); } diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index 0677cd2f601..4e1272a8f69 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -1411,7 +1411,7 @@ class Holiday extends CommonObject // Update each user counter foreach ($users as $userCounter) { - $nbDaysToAdd = $typeleaves[$userCounter['type']]['newByMonth']; + $nbDaysToAdd = (isset($typeleaves[$userCounter['type']]['newByMonth']) ? $typeleaves[$userCounter['type']]['newByMonth'] : 0); if (empty($nbDaysToAdd)) continue; dol_syslog("We update leave type id ".$userCounter['type']." for user id ".$userCounter['rowid'], LOG_DEBUG); diff --git a/test/phpunit/FormTest.php b/test/phpunit/FormTest.php index bec23048e9f..76e7c4e69a8 100644 --- a/test/phpunit/FormTest.php +++ b/test/phpunit/FormTest.php @@ -143,14 +143,14 @@ class FormTest extends PHPUnit\Framework\TestCase $result=$localobject->select_produits_list('', 'productid', '', 5, 0, '', 1, 2, 1); $this->assertEquals(count($result), 5); - print __METHOD__." result=".$result."\n"; + print __METHOD__." count result=".count($result)."\n"; $conf->global->ENTREPOT_EXTRA_STATUS = 1; // Exclude stock in warehouseinternal $result=$localobject->select_produits_list('', 'productid', '', 5, 0, '', 1, 2, 1, 0, '1', 0, '', 0, 'warehouseclosed,warehouseopen'); $this->assertEquals(count($result), 5); - print __METHOD__." result=".$result."\n"; + print __METHOD__." count result=".count($result)."\n"; return $result; } diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index f6eb7783c4f..4d642c733b4 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -285,9 +285,10 @@ class SecurityTest extends PHPUnit\Framework\TestCase $_POST["param6"]="">objnotdefined\''; - // Test int - $result=GETPOST('id', 'int'); // Must return nothing + $result=GETPOST('id', 'int'); // Must return nothing print __METHOD__." result=".$result."\n"; $this->assertEquals($result, ''); @@ -347,6 +348,14 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals("HackerassertEquals($_POST["param9"], $result); + + $result=GETPOST("param10", 'alphanohtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals($_POST["param9"], $result, 'We should get param9 after processing param10'); + return $result; }