diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 5bab6588df7..65a5f8269ad 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -7932,14 +7932,14 @@ function dol_string_nohtmltag($stringtoclean, $removelinefeed = 1, $pagecodeto =
* Clean a string to keep only desirable HTML tags.
* WARNING: This also clean HTML comments (because they can be used to obfuscate tag name).
*
- * @param string $stringtoclean String to clean
- * @param int $cleanalsosomestyles Remove absolute/fixed positioning from inline styles
- * @param int $removeclassattribute 1=Remove the class attribute from tags
- * @param int $cleanalsojavascript Remove also occurrence of 'javascript:'.
- * @param int $allowiframe Allow iframe tags.
- * @param string[] $allowed_tags List of allowed tags to replace the default list
- * @param int $allowlink Allow "link" tags.
- * @return string String cleaned
+ * @param string $stringtoclean String to clean
+ * @param int $cleanalsosomestyles Remove absolute/fixed positioning from inline styles
+ * @param int $removeclassattribute 1=Remove the class attribute from tags
+ * @param int $cleanalsojavascript Remove also occurrence of 'javascript:'.
+ * @param int $allowiframe Allow iframe tags.
+ * @param string[] $allowed_tags List of allowed tags to replace the default list
+ * @param int $allowlink Allow "link" tags.
+ * @return string String cleaned
*
* @see dol_htmlwithnojs() dol_escape_htmltag() strip_tags() dol_string_nohtmltag() dol_string_neverthesehtmltags()
*/
@@ -7977,9 +7977,10 @@ function dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles = 1,
$stringtoclean = preg_replace('/:/i', ':', $stringtoclean);
$stringtoclean = preg_replace('/:|+58|:/i', '', $stringtoclean); // refused string ':' encoded (no reason to have a : encoded like this) to disable 'javascript:...'
+ // Remove all HTML tags
$temp = strip_tags($stringtoclean, $allowed_tags_string); // Warning: This remove also undesired >, so may changes string obfuscated with > that pass the injection detection into a harmfull string
- if ($cleanalsosomestyles) { // Clean for remaining html tags
+ if ($cleanalsosomestyles) { // Clean for remaining html tags
$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
@@ -8232,6 +8233,7 @@ function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = '
} else {
$out = $stringtoencode;
+ // First clean HTML content
do {
$oldstringtoclean = $out;
@@ -8343,6 +8345,17 @@ function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = '
// Restore entity ' into ' (restricthtml is for html content so we can use html entity)
$out = preg_replace('/'/i', "'", $out);
+
+ // Now remove js
+ // List of dom events is on https://www.w3schools.com/jsref/dom_obj_event.asp and https://developer.mozilla.org/en-US/docs/Web/Events
+ $out = preg_replace('/on(mouse|drag|key|load|touch|pointer|select|transition)[a-z]*\s*=/i', '', $out); // onmousexxx can be set on img or any html tag like
+ $out = preg_replace('/on(abort|after|animation|auxclick|before|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|copy|cut)[a-z]*\s*=/i', '', $out);
+ $out = preg_replace('/on(dblclick|drop|durationchange|emptied|end|ended|error|focus|focusin|focusout|formdata|gotpointercapture|hashchange|input|invalid)[a-z]*\s*=/i', '', $out);
+ $out = preg_replace('/on(lostpointercapture|offline|online|pagehide|pageshow)[a-z]*\s*=/i', '', $out);
+ $out = preg_replace('/on(paste|pause|play|playing|progress|ratechange|reset|resize|scroll|search|seeked|seeking|show|stalled|start|submit|suspend)[a-z]*\s*=/i', '', $out);
+ $out = preg_replace('/on(timeupdate|toggle|unload|volumechange|waiting|wheel)[a-z]*\s*=/i', '', $out);
+ // More not into the previous list
+ $out = preg_replace('/on(repeat|begin|finish|beforeinput)[a-z]*\s*=/i', '', $out);
} while ($oldstringtoclean != $out);
// Check the limit of external links that are automatically executed in a Rich text content. We count:
diff --git a/htdocs/install/mysql/migration/19.0.0-20.0.0.sql b/htdocs/install/mysql/migration/19.0.0-20.0.0.sql
index 70e5b8bc814..ff150c92c7c 100644
--- a/htdocs/install/mysql/migration/19.0.0-20.0.0.sql
+++ b/htdocs/install/mysql/migration/19.0.0-20.0.0.sql
@@ -32,10 +32,13 @@
-- -- VPGSQL8.2 SELECT dol_util_rebuild_sequences();
--- V18 forgotten
+-- V18 and - forgotten
UPDATE llx_paiement SET ref = rowid WHERE ref IS NULL OR ref = '';
+ALTER TABLE llx_c_holiday_types ADD COLUMN block_if_negative integer NOT NULL DEFAULT 0 AFTER fk_country;
+ALTER TABLE llx_c_holiday_types ADD COLUMN sortorder smallint;
+
-- V19 forgotten
@@ -401,7 +404,10 @@ INSERT INTO llx_c_revenuestamp(rowid,fk_pays,taux,revenuestamp_type,note,active)
ALTER TABLE llx_hrm_evaluation ADD COLUMN entity INTEGER DEFAULT 1 NOT NULL;
+-- Erreur SQL DB_ERROR_1170 BLOB/TEXT column 'url' used in key specification without a key length
+ALTER TABLE llx_menu DROP INDEX idx_menu_uk_menu;
ALTER TABLE llx_menu MODIFY COLUMN url TEXT NOT NULL;
+ALTER TABLE llx_menu ADD UNIQUE INDEX idx_menu_uk_menu (menu_handler, fk_menu, position, entity);
UPDATE llx_c_units SET short_label = 'mn' WHERE short_label = 'i' AND code = 'MI';
diff --git a/htdocs/install/mysql/tables/llx_menu.key.sql b/htdocs/install/mysql/tables/llx_menu.key.sql
index 10746d25b4c..6380a947737 100644
--- a/htdocs/install/mysql/tables/llx_menu.key.sql
+++ b/htdocs/install/mysql/tables/llx_menu.key.sql
@@ -21,5 +21,7 @@
ALTER TABLE llx_menu ADD INDEX idx_menu_menuhandler_type (menu_handler, type);
-ALTER TABLE llx_menu ADD UNIQUE INDEX idx_menu_uk_menu (menu_handler, fk_menu, position, url, entity);
+-- Erreur SQL DB_ERROR_1170 BLOB/TEXT column 'url' used in key specification without a key length
+-- ALTER TABLE llx_menu ADD UNIQUE INDEX idx_menu_uk_menu (menu_handler, fk_menu, position, url, entity);
+ALTER TABLE llx_menu ADD UNIQUE INDEX idx_menu_uk_menu (menu_handler, fk_menu, position, entity);
diff --git a/htdocs/install/step2.php b/htdocs/install/step2.php
index cb18b8a4c91..0686e19acae 100644
--- a/htdocs/install/step2.php
+++ b/htdocs/install/step2.php
@@ -536,6 +536,9 @@ if ($action == "set") {
$buffer = preg_replace('/llx_/i', $dolibarr_main_db_prefix, $buffer);
}
+ // Replace __ENTITY__ tag with 1 (master entity), this is only for dictionaries.
+ $buffer = preg_replace('/__ENTITY__/i', '1', $buffer);
+
//dolibarr_install_syslog("step2: request: " . $buffer);
$resql = $db->query($buffer, 1);
if ($resql) {
diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php
index d2c1981deb7..399cb9030f1 100644
--- a/htdocs/main.inc.php
+++ b/htdocs/main.inc.php
@@ -211,6 +211,7 @@ function testSqlAndScriptInject($val, $type)
}
$inj += preg_match('/base\s+href/si', $val);
$inj += preg_match('/=data:/si', $val);
+
// List of dom events is on https://www.w3schools.com/jsref/dom_obj_event.asp and https://developer.mozilla.org/en-US/docs/Web/Events
$inj += preg_match('/on(mouse|drag|key|load|touch|pointer|select|transition)[a-z]*\s*=/i', $val); // onmousexxx can be set on img or any html tag like
$inj += preg_match('/on(abort|after|animation|auxclick|before|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|copy|cut)[a-z]*\s*=/i', $val);
@@ -219,11 +220,12 @@ function testSqlAndScriptInject($val, $type)
$inj += preg_match('/on(paste|pause|play|playing|progress|ratechange|reset|resize|scroll|search|seeked|seeking|show|stalled|start|submit|suspend)[a-z]*\s*=/i', $val);
$inj += preg_match('/on(timeupdate|toggle|unload|volumechange|waiting|wheel)[a-z]*\s*=/i', $val);
// More not into the previous list
-
$inj += preg_match('/on(repeat|begin|finish|beforeinput)[a-z]*\s*=/i', $val);
- // We refuse html into html because some hacks try to obfuscate evil strings by inserting HTML into HTML. Example:
error=alert(1) to bypass test on onerror
- $tmpval = preg_replace('/<[^<]+>/', '', $val);
+ // We refuse html into html because some hacks try to obfuscate evil strings by inserting HTML into HTML.
+ // Example:
error=alert(1) or
=alert(1) to bypass test on onerror=
+ $tmpval = preg_replace('/<[^<]*>/', '', $val);
+
// List of dom events is on https://www.w3schools.com/jsref/dom_obj_event.asp and https://developer.mozilla.org/en-US/docs/Web/Events
$inj += preg_match('/on(mouse|drag|key|load|touch|pointer|select|transition)[a-z]*\s*=/i', $tmpval); // onmousexxx can be set on img or any html tag like
$inj += preg_match('/on(abort|after|animation|auxclick|before|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|copy|cut)[a-z]*\s*=/i', $tmpval);
diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php
index 9cfc33b8ed2..2b8cb2273b6 100644
--- a/htdocs/ticket/card.php
+++ b/htdocs/ticket/card.php
@@ -890,7 +890,7 @@ if ($action == 'create' || $action == 'presend') {
$morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetTitle'), 0).' ';
}
if ($action != 'editsubject') {
- $morehtmlref .= $object->subject;
+ $morehtmlref .= dolPrintLabel($object->subject);
} else {
$morehtmlref .= '