- trans('TotalTTC'); ?>: total_ttc, 1, '', 1, -1, -1, $invoice->multicurrency_code); ?>
+ trans('TotalTTC'); ?>: total_ttc, 1, '', 1, -1, -1, $conf->currency);
+ if ($showothercurrency) {
+ print ' (' . price($invoice->total_ht * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')';
+ }
+ ?>
total_ttc) { ?>
- trans('RemainToPay'); ?>: multicurrency_code); ?>
+ trans('RemainToPay'); ?>: multicurrency_code);
+ if ($showothercurrency) {
+ print ' (' . price($remaintopay * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')';
+ }
+ ?>
- trans("Received"); ?>: multicurrency_code); ?>
+ trans("Received"); ?>: multicurrency_code);
+ if ($showothercurrency) {
+ print ' (' . price(0 * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')';
+ }
+ ?>
- trans("Change"); ?>: multicurrency_code); ?>
+ trans("Change"); ?>: multicurrency_code);
+ if ($showothercurrency) {
+ print ' (' . price(0 * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')';
+ }
+ ?>
global->TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT)) {
From 4b2fb64b51f6329119d15013a1f9b941cf2157a4 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Sat, 2 Mar 2024 18:34:40 +0100
Subject: [PATCH 051/117] css
---
htdocs/fourn/facture/list.php | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php
index b61ec85ab9745..bdbc1777acd17 100644
--- a/htdocs/fourn/facture/list.php
+++ b/htdocs/fourn/facture/list.php
@@ -1273,7 +1273,7 @@
}
// Status
if (!empty($arrayfields['f.fk_statut']['checked'])) {
- print '';
+ print ' | ';
$liststatus = array('0'=>$langs->trans("Draft"), '1'=>$langs->trans("Unpaid"), '2'=>$langs->trans("Paid"));
print $form->selectarray('search_status', $liststatus, $search_status, 1, 0, 0, '', 0, 0, 0, '', 'center search_status width100 onrightofpage', 1);
print ' | ';
@@ -1492,6 +1492,7 @@
$userstatic->firstname = $obj->firstname;
$userstatic->email = $obj->user_email;
$userstatic->statut = $obj->user_statut;
+ $userstatic->status = $obj->user_statut;
$userstatic->entity = $obj->entity;
$userstatic->photo = $obj->photo;
$userstatic->office_phone = $obj->office_phone;
From f875201b4687c9e860c80333a95c3b7409dbd2e5 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Sat, 2 Mar 2024 18:59:57 +0100
Subject: [PATCH 052/117] Fix #19404 FIX #22721
---
htdocs/fourn/class/fournisseur.facture.class.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php
index 65a00f8affc7d..94db1f445acfd 100644
--- a/htdocs/fourn/class/fournisseur.facture.class.php
+++ b/htdocs/fourn/class/fournisseur.facture.class.php
@@ -2691,7 +2691,7 @@ public function load_board($user)
$sql .= " JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ff.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
}
$sql .= ' WHERE ff.paye = 0';
- $sql .= ' AND ff.fk_statut > 0';
+ $sql .= " AND ff.fk_statut IN (".self::STATUS_VALIDATED.")";
$sql .= " AND ff.entity = ".$conf->entity;
if ($user->socid) {
$sql .= ' AND ff.fk_soc = '.((int) $user->socid);
From 21feee3bc8b2ebe8a87b8fa56f023faa5835ba44 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Sun, 3 Mar 2024 13:11:54 +0100
Subject: [PATCH 053/117] FIX Better test on validity of compute field syntax
with parenthesis
---
htdocs/core/lib/functions.lib.php | 42 +++++++++++++++++++------------
test/phpunit/SecurityTest.php | 15 +++++++++--
2 files changed, 39 insertions(+), 18 deletions(-)
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 1fe4661236e6d..c0ecd6acefc7f 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -9641,18 +9641,23 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1'
return '';
}
}
- $scheck = preg_replace('/->[a-zA-Z0-9_]+\(/', '->__METHOD__', $s); // accept parenthesis in '...->method(...'
- $scheck = preg_replace('/^\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '(...'. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
- $scheck = preg_replace('/\s\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '... ('. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
- $scheck = preg_replace('/^!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in 'function(' and '!function('
- $scheck = preg_replace('/\s!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in '... function(' and '... !function('
- $scheck = preg_replace('/(\^|\')\(/', '__REGEXSTART__', $scheck); // To allow preg_match('/^(aaa|bbb)/'... or isStringVarMatching('leftmenu', '(aaa|bbb)')
+ $savescheck = '';
+ $scheck = $s;
+ while ($scheck && $savescheck != $scheck) {
+ $savescheck = $scheck;
+ $scheck = preg_replace('/->[a-zA-Z0-9_]+\(/', '->__METHOD__', $scheck); // accept parenthesis in '...->method(...'
+ $scheck = preg_replace('/^\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '(...'. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
+ $scheck = preg_replace('/\s\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '... ('. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
+ $scheck = preg_replace('/^!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in 'function(' and '!function('
+ $scheck = preg_replace('/\s!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in '... function(' and '... !function('
+ $scheck = preg_replace('/(\^|\')\(/', '__REGEXSTART__', $scheck); // To allow preg_match('/^(aaa|bbb)/'... or isStringVarMatching('leftmenu', '(aaa|bbb)')
+ }
//print 'scheck='.$scheck." : ".strpos($scheck, '(')."
\n";
if (strpos($scheck, '(') !== false) {
if ($returnvalue) {
- return 'Bad string syntax to evaluate (found call of a function or method without using direct name): '.$s;
+ return 'Bad string syntax to evaluate (mode 1, found call of a function or method without using the direct name of the function): '.$s;
} else {
- dol_syslog('Bad string syntax to evaluate (found call of a function or method without using direct name): '.$s);
+ dol_syslog('Bad string syntax to evaluate (mode 1, found call of a function or method without using the direct name of the function): '.$s);
return '';
}
}
@@ -9672,18 +9677,23 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1'
return '';
}
}
- $scheck = preg_replace('/->[a-zA-Z0-9_]+\(/', '->__METHOD__', $s); // accept parenthesis in '...->method(...'
- $scheck = preg_replace('/^\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '(...'. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
- $scheck = preg_replace('/\s\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '... ('. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
- $scheck = preg_replace('/^!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in 'function(' and '!function('
- $scheck = preg_replace('/\s!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in '... function(' and '... !function('
- $scheck = preg_replace('/(\^|\')\(/', '__REGEXSTART__', $scheck); // To allow preg_match('/^(aaa|bbb)/'... or isStringVarMatching('leftmenu', '(aaa|bbb)')
+ $savescheck = '';
+ $scheck = $s;
+ while ($scheck && $savescheck != $scheck) {
+ $savescheck = $scheck;
+ $scheck = preg_replace('/->[a-zA-Z0-9_]+\(/', '->__METHOD__', $scheck); // accept parenthesis in '...->method(...'
+ $scheck = preg_replace('/^\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '(...'. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
+ $scheck = preg_replace('/\s\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '... ('. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
+ $scheck = preg_replace('/^!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in 'function(' and '!function('
+ $scheck = preg_replace('/\s!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in '... function(' and '... !function('
+ $scheck = preg_replace('/(\^|\')\(/', '__REGEXSTART__', $scheck); // To allow preg_match('/^(aaa|bbb)/'... or isStringVarMatching('leftmenu', '(aaa|bbb)')
+ }
//print 'scheck='.$scheck." : ".strpos($scheck, '(')."
\n";
if (strpos($scheck, '(') !== false) {
if ($returnvalue) {
- return 'Bad string syntax to evaluate (found call of a function or method without using direct name): '.$s;
+ return 'Bad string syntax to evaluate (mode 2, found call of a function or method without using the direct name of the function): '.$s;
} else {
- dol_syslog('Bad string syntax to evaluate (found call of a function or method without using direct name): '.$s);
+ dol_syslog('Bad string syntax to evaluate (mode 2, found call of a function or method without using the direct name of the function): '.$s);
return '';
}
}
diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php
index 4615efe8c229f..66a40206bb322 100644
--- a/test/phpunit/SecurityTest.php
+++ b/test/phpunit/SecurityTest.php
@@ -1061,6 +1061,10 @@ public function testDolEval()
$langs=$this->savlangs;
$db=$this->savdb;
+ // Declare classes found into string to evaluate
+ include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
+ include_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
+
$result=dol_eval('1==1', 1, 0);
print "result1 = ".$result."\n";
$this->assertTrue($result);
@@ -1069,8 +1073,15 @@ public function testDolEval()
print "result2 = ".$result."\n";
$this->assertFalse($result);
- include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
- include_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
+ $s = '((($reloadedobj = new ClassThatDoesNotExists($db)) && ($reloadedobj->fetchNoCompute($objectoffield->fk_product) > 0)) ? \'1\' : \'0\')';
+ $result3a = dol_eval($s, 1, 1, '2');
+ print "result3a = ".$result."\n";
+ $this->assertTrue(is_null($result3a));
+
+ $s = '((($reloadedobj = new Project($db)) && ($reloadedobj->fetchNoCompute($objectoffield->fk_product) > 0)) ? \'1\' : \'0\')';
+ $result3b = dol_eval($s, 1, 1, '2');
+ print "result3b = ".$result."\n";
+ $this->assertEquals('0', $result3b);
$s = '(($reloadedobj = new Task($db)) && ($reloadedobj->fetchNoCompute($object->id) > 0) && ($secondloadedobj = new Project($db)) && ($secondloadedobj->fetchNoCompute($reloadedobj->fk_project) > 0)) ? $secondloadedobj->ref : "Parent project not found"';
$result=dol_eval($s, 1, 1, '2');
From 16319e5103baf93a142eb12ec7b2bffdb5466b2a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?=
Date: Sun, 3 Mar 2024 15:48:36 +0100
Subject: [PATCH 054/117] fix codespell (#28594)
---
htdocs/mrp/class/mo.class.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php
index e3438cad7e001..b8e2ec9e94017 100644
--- a/htdocs/mrp/class/mo.class.php
+++ b/htdocs/mrp/class/mo.class.php
@@ -900,7 +900,7 @@ public function deleteLine(User $user, $idline, $notrigger = false)
}
$productstatic = new Product($this->db);
$fk_movement = GETPOST('fk_movement', 'int');
- $arrayoflines = $this->fetchLinesLinked('consumed', $idline); // Get lines consummed under the one to delete
+ $arrayoflines = $this->fetchLinesLinked('consumed', $idline); // Get lines consumed under the one to delete
$result = 0;
From 41bdcff4da175afe13d4bb1e8d51bb38eb139723 Mon Sep 17 00:00:00 2001
From: PsyCrow <93346975+PsyCrow-code@users.noreply.github.com>
Date: Sun, 3 Mar 2024 09:58:52 -0600
Subject: [PATCH 055/117] Update facture.class.php (#28591)
* Update facture.class.php
FIX #22948
* Update facture.class.php
---
htdocs/compta/facture/class/facture.class.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php
index 41daf8bd39c3a..73a184c96c01f 100644
--- a/htdocs/compta/facture/class/facture.class.php
+++ b/htdocs/compta/facture/class/facture.class.php
@@ -4167,8 +4167,8 @@ public function updateline($rowid, $desc, $pu, $qty, $remise_percent, $date_star
$price = $pu;
$remise = 0;
if ($remise_percent > 0) {
- $remise = round(($pu * $remise_percent / 100), 2);
- $price = ($pu - $remise);
+ $remise = round(((float) $pu * (float) $remise_percent / 100), 2);
+ $price = ((float) $pu - $remise);
}
$price = price2num($price);
From d199b042b4260c47f102369db1ca2df216f05858 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Sun, 3 Mar 2024 18:50:28 +0100
Subject: [PATCH 056/117] Prepare 19.0.1
---
ChangeLog | 47 +++++++++++++++++++++++++++++++++++++++++
htdocs/filefunc.inc.php | 2 +-
2 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/ChangeLog b/ChangeLog
index afb30c7d89980..56ebe50a7f62a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,53 @@ English Dolibarr ChangeLog
--------------------------------------------------------------
+***** ChangeLog for 19.0.1 compared to 19.0.0 *****
+
+FIX: 16.0 - parent company gets emptied when updating a third party from the card in edit mode (#28269)
+FIX: #22948
+FIX: #28205
+FIX: 28251 Fixing subpermission name on api_multicurrencies.class.php (#28252)
+FIX: #28369
+FIX: #28429
+FIX: #28491 (#28522)
+FIX: #28518 (#28520)
+FIX: #28533 Mo::deleteLine removes the "main" MoLine if consumed line is delete (#28535)
+FIX: #28564
+FIX: Adding the dependencies list feature for extrafields "select" (#28549)
+FIX: Add new hidden conf "DISABLE_QTY_OVERWRITTEN" (#28523)
+FIX: avoid error "Column 'entity' in where clause is ambiguous" (#28270)
+FIX: avoid Unknown column 'pfp.ref_fourn' (#28145)
+FIX: avoid warning "error parsing attribute name in Entity" (#28543)
+FIX: Bad column for total in bom list
+FIX: Bad condition on button back to draft on recruitment job.
+FIX: Bad CRLF when sending text only content. Fix dol_htmlwithnojs()
+FIX: Bad picto on list of permission of a user when user not admin
+FIX: bad timzeone for the start/end date of an event
+FIX: Better test on validity of compute field syntax with parenthesis
+FIX: close #28279
+FIX: disabled pito of menu must be greyed.
+FIX: Don't display column when it's out of date (#28271)
+FIX: duplicate with lines: 414-416 (#28358)
+FIX: Error When cloning fourn price no default value for tva_tx (#28368)
+FIX: migration missing 2 columns in llx_resource and 1 in llx_user
+FIX: missing trans
+FIX: notification module: for supplier orders (any of the 3 triggers), user can choose an e-mail template in conf, but the conf is not used when sending the notification (#28216)
+FIX: Not trancate the multicurrency rate shown on cards (even if the global MAIN_MAX_DECIMALS_SHOWN is set to 0) (#28211)
+FIX: Payment on customer invoice - Remove accountid in url if empty for apply default value (#28156)
+FIX: Pb in redirect of a website page in USEDOLIBARRSERVER mode
+FIX: PHP Warning: Undefined variable $lib (#28342)
+FIX: Picto for mime
+FIX: position of field in list of field in shipment list
+FIX: postgresql error (#28542)
+FIX: quote in sql request
+FIX: Responsive on admin project
+FIX: Shipment closing action has wrong value (#28174)
+FIX: some tooltips has disappeared on invoice action button
+FIX: Special code is now transmitted by args only in order supplier (#28546)
+FIX: subscription must be editable when accounting isn't reconciled (#28469)
+FIX: Value of field int = 0 from modulebuilder must nto be set to null
+
+
***** ChangeLog for 19.0.0 compared to 18.0.0 *****
For users:
diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php
index 948381bd82805..4c4df29af5092 100644
--- a/htdocs/filefunc.inc.php
+++ b/htdocs/filefunc.inc.php
@@ -34,7 +34,7 @@
define('DOL_APPLICATION_TITLE', 'Dolibarr');
}
if (!defined('DOL_VERSION')) {
- define('DOL_VERSION', '19.0.0'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c
+ define('DOL_VERSION', '19.0.1'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c
}
if (!defined('EURO')) {
From af6a091ab2e6915325ad5c849247ca2a7854a163 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Sun, 3 Mar 2024 18:55:10 +0100
Subject: [PATCH 057/117] Fix 19.0.1
---
ChangeLog | 2 +-
htdocs/comm/card.php | 2 +-
htdocs/core/class/commoninvoice.class.php | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 56ebe50a7f62a..de0cb66b9686a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -34,7 +34,7 @@ FIX: Error When cloning fourn price no default value for tva_tx (#28368)
FIX: migration missing 2 columns in llx_resource and 1 in llx_user
FIX: missing trans
FIX: notification module: for supplier orders (any of the 3 triggers), user can choose an e-mail template in conf, but the conf is not used when sending the notification (#28216)
-FIX: Not trancate the multicurrency rate shown on cards (even if the global MAIN_MAX_DECIMALS_SHOWN is set to 0) (#28211)
+FIX: Not truncate the multicurrency rate shown on cards (even if the global MAIN_MAX_DECIMALS_SHOWN is set to 0) (#28211)
FIX: Payment on customer invoice - Remove accountid in url if empty for apply default value (#28156)
FIX: Pb in redirect of a website page in USEDOLIBARRSERVER mode
FIX: PHP Warning: Undefined variable $lib (#28342)
diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php
index 39e9267cd161e..38fa513937683 100644
--- a/htdocs/comm/card.php
+++ b/htdocs/comm/card.php
@@ -219,7 +219,7 @@
if ($action == 'setassujtva' && $user->hasRight('societe', 'creer')) {
$object->fetch($id);
$object->tva_assuj = GETPOST('assujtva_value');
- $result = $object->update($object->id);
+ $result = $object->update($object->id, $user);
if ($result < 0) {
setEventMessages($object->error, $object->errors, 'errors');
}
diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php
index 5c9d90b11cc3a..a7c5788aee39c 100644
--- a/htdocs/core/class/commoninvoice.class.php
+++ b/htdocs/core/class/commoninvoice.class.php
@@ -1146,7 +1146,7 @@ public function makeStripeSepaRequest($fuser, $did, $type = 'direct-debit', $sou
$sql .= " AND fk_facture = ".((int) $this->id); // Add a protection to not pay another invoice than current one
}
if ($type != 'direct-debit') {
- if ($$sourcetype == 'salary') {
+ if ($sourcetype == 'salary') {
$sql .= " AND fk_salary = ".((int) $this->id); // Add a protection to not pay another salary than current one
} else {
$sql .= " AND fk_facture_fourn = ".((int) $this->id); // Add a protection to not pay another invoice than current one
From 17ff0972ab407eb7c55cce6ffa72553c1e001696 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Sun, 3 Mar 2024 19:35:37 +0100
Subject: [PATCH 058/117] Fix use of invoke into computed fields
---
htdocs/core/lib/functions.lib.php | 9 +++++++--
test/phpunit/SecurityTest.php | 10 ++++++++++
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index cf8bb9b324e83..cbf8fee96e042 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -9289,22 +9289,27 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1'
// We block use of php exec or php file functions
$forbiddenphpstrings = array('$$');
- $forbiddenphpstrings = array_merge($forbiddenphpstrings, array('_ENV', '_SESSION', '_COOKIE', '_GET', '_POST', '_REQUEST'));
+ $forbiddenphpstrings = array_merge($forbiddenphpstrings, array('_ENV', '_SESSION', '_COOKIE', '_GET', '_POST', '_REQUEST', 'ReflectionFunction'));
$forbiddenphpfunctions = array("exec", "passthru", "shell_exec", "system", "proc_open", "popen");
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("dol_eval", "executeCLI", "verifCond")); // native dolibarr functions
- $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("base64_decode", "rawurldecode", "urldecode")); // decode string functions
+ $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("base64_decode", "rawurldecode", "urldecode", "str_rot13", "hex2bin")); // decode string functions used to obfuscated function name
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "require", "include", "mkdir", "rmdir", "symlink", "touch", "unlink", "umask"));
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("get_defined_functions", "get_defined_vars", "get_defined_constants", "get_declared_classes"));
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("function", "call_user_func"));
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("eval", "create_function", "assert", "mb_ereg_replace")); // function with eval capabilities
+ $forbiddenphpmethods = array('invoke', 'invokeArgs'); // Method of ReflectionFunction to execute a function
+
$forbiddenphpregex = 'global\s+\$|\b('.implode('|', $forbiddenphpfunctions).')\b';
+ $forbiddenphpmethodsregex = '->('.implode('|', $forbiddenphpmethods).')';
+
do {
$oldstringtoclean = $s;
$s = str_ireplace($forbiddenphpstrings, '__forbiddenstring__', $s);
$s = preg_replace('/'.$forbiddenphpregex.'/i', '__forbiddenstring__', $s);
+ $s = preg_replace('/'.$forbiddenphpmethodsregex.'/i', '__forbiddenstring__', $s);
//$s = preg_replace('/\$[a-zA-Z0-9_\->\$]+\(/i', '', $s); // Remove $function( call and $mycall->mymethod(
} while ($oldstringtoclean != $s);
diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php
index 545306f57344e..fb3132a17ff55 100644
--- a/test/phpunit/SecurityTest.php
+++ b/test/phpunit/SecurityTest.php
@@ -960,6 +960,16 @@ public function testDolEval()
print "result = ".$result."\n";
$this->assertEquals('Parent project not found', $result);
+ $s = 'new abc->invoke(\'whoami\')';
+ $result=dol_eval($s, 1, 1, '2');
+ print "result = ".$result."\n";
+ $this->assertEquals('Bad string syntax to evaluate: new abc__forbiddenstring__(\'whoami\')', $result);
+
+ $s = 'new ReflectionFunction(\'abc\')';
+ $result=dol_eval($s, 1, 1, '2');
+ print "result = ".$result."\n";
+ $this->assertEquals('Bad string syntax to evaluate: new __forbiddenstring__(\'abc\')', $result);
+
$result=dol_eval('$a=function() { }; $a;', 1, 1, '');
print "result = ".$result."\n";
$this->assertContains('Bad string syntax to evaluate', $result);
From e82c6af5bcc7dad4c68d4d11e57965e56c653844 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Mon, 4 Mar 2024 14:02:49 +0100
Subject: [PATCH 059/117] FIX permission on payment file of a tax
---
htdocs/core/lib/security.lib.php | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php
index 7eb552fac92b4..32a53dde33ddd 100644
--- a/htdocs/core/lib/security.lib.php
+++ b/htdocs/core/lib/security.lib.php
@@ -889,7 +889,10 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
$feature = 'agenda';
$dbtablename = 'actioncomm';
}
- if ($feature == 'payment_sc') {
+ if ($feature == 'payment_sc' && empty($parenttableforentity)) {
+ // If we check perm on payment page but $parenttableforentity not defined, we force value on parent table
+ $parenttableforentity = '';
+ $dbtablename = "chargesociales";
$feature = "chargesociales";
$objectid = $object->fk_charge;
}
@@ -897,7 +900,7 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
$checkonentitydone = 0;
// Array to define rules of checks to do
- $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website', 'recruitment', 'chargesociales'); // Test on entity only (Objects with no link to company)
+ $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'payment_sc', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website', 'recruitment', 'chargesociales'); // Test on entity only (Objects with no link to company)
$checksoc = array('societe'); // Test for object Societe
$checkparentsoc = array('agenda', 'contact', 'contrat'); // Test on entity + link to third party on field $dbt_keyfield. Allowed if link is empty (Ex: contacts...).
$checkproject = array('projet', 'project'); // Test for project object
From 0c86f6456590a5a1eb72eb21f001141c082f1006 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Mon, 4 Mar 2024 14:02:49 +0100
Subject: [PATCH 060/117] FIX permission on payment file of a tax
---
htdocs/core/lib/security.lib.php | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php
index 2f4d4fe2f839a..7cd07b3edcd54 100644
--- a/htdocs/core/lib/security.lib.php
+++ b/htdocs/core/lib/security.lib.php
@@ -884,7 +884,10 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
$feature = 'agenda';
$dbtablename = 'actioncomm';
}
- if ($feature == 'payment_sc') {
+ if ($feature == 'payment_sc' && empty($parenttableforentity)) {
+ // If we check perm on payment page but $parenttableforentity not defined, we force value on parent table
+ $parenttableforentity = '';
+ $dbtablename = "chargesociales";
$feature = "chargesociales";
$objectid = $object->fk_charge;
}
@@ -892,7 +895,7 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
$checkonentitydone = 0;
// Array to define rules of checks to do
- $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website', 'recruitment', 'chargesociales'); // Test on entity only (Objects with no link to company)
+ $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'payment_sc', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website', 'recruitment', 'chargesociales'); // Test on entity only (Objects with no link to company)
$checksoc = array('societe'); // Test for object Societe
$checkparentsoc = array('agenda', 'contact', 'contrat'); // Test on entity + link to third party on field $dbt_keyfield. Allowed if link is empty (Ex: contacts...).
$checkproject = array('projet', 'project'); // Test for project object
From db7a62f644ffcb1068535b2f56d5a6a5c10bd4aa Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Mon, 4 Mar 2024 14:46:33 +0100
Subject: [PATCH 061/117] FIX fatal error Unsupported operand types when
recording load payment
---
htdocs/loan/payment/payment.php | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/htdocs/loan/payment/payment.php b/htdocs/loan/payment/payment.php
index 6a136f8ba2e3d..d65f48665a384 100644
--- a/htdocs/loan/payment/payment.php
+++ b/htdocs/loan/payment/payment.php
@@ -114,16 +114,16 @@
if (!$error) {
$paymentid = 0;
- $pay_amount_capital = price2num(GETPOST('amount_capital'));
- $pay_amount_insurance = price2num(GETPOST('amount_insurance'));
+ $pay_amount_capital = (float) price2num(GETPOST('amount_capital'));
+ $pay_amount_insurance = (float) price2num(GETPOST('amount_insurance'));
// User can't set interest him self if schedule is set (else value in schedule can be incoherent)
if (!empty($line)) {
$pay_amount_interest = $line->amount_interest;
} else {
- $pay_amount_interest = price2num(GETPOST('amount_interest'));
+ $pay_amount_interest = (float) price2num(GETPOST('amount_interest'));
}
- $remaindertopay = price2num(GETPOST('remaindertopay'));
- $amount = $pay_amount_capital + $pay_amount_insurance + $pay_amount_interest;
+ $remaindertopay = (float) price2num(GETPOST('remaindertopay'));
+ $amount = (float) price2num($pay_amount_capital + $pay_amount_insurance + $pay_amount_interest, 'MT');
// This term is allready paid
if (!empty($line) && !empty($line->fk_bank)) {
From a0444ef55d379a633554dfd32f1d914e2df07abc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?=
Date: Mon, 4 Mar 2024 17:58:43 +0100
Subject: [PATCH 062/117] fix can't delete pdf if ref is not encoded (#28630)
---
htdocs/compta/facture/card.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php
index ea9b87b1de6e7..c156eccb5f38d 100644
--- a/htdocs/compta/facture/card.php
+++ b/htdocs/compta/facture/card.php
@@ -4477,7 +4477,7 @@ function setRadioForTypeOfInvoice() {
$file = GETPOST('file', 'alpha');
$formconfirm = $form->formconfirm(
- $_SERVER["PHP_SELF"].'?facid='.$object->id.'&file='.$file,
+ $_SERVER["PHP_SELF"].'?facid='.$object->id.'&file='.urlencode($file),
$langs->trans('DeleteFileHeader'),
$langs->trans('DeleteFileText')."
".$file,
'remove_file',
From f166f15f7d8dfd15ae2e53fec92935e4b815c6ab Mon Sep 17 00:00:00 2001
From: MDW
Date: Mon, 4 Mar 2024 18:21:32 +0100
Subject: [PATCH 063/117] Qual: Backport/pre commit / log annotation
simplification (#28614)
* Qual: ci: Run pre-commit/php-cs with cache (#28079)
This adds a hook to .pre-commit-config.yaml and updates the workflow
to run php-cs with cache when it is run for all files.
When running on changed files only, the cache is not useful.
The php-codesniffer ruleset.xml was cleaned up (duplicates removal/formatted)
* Fix: Make all 'relative paths' absolute (#28196)
# Fix: Make all 'relative paths' absolute
The phpcs ruleset xml file's relative exclude patterns are relative to
the filename(s) provided on the command line.
Hence with partial verifications, the path exclusion does not function
as we would like.
Removing the relative-path attribute from the patterns the exclusion
works.
At the same time, the patterns were optimized and a comment was added.
* Qual: Optimize workflow (#28386)
# Qual: Optimize workflow
The log annotation based on the pre-commit logs is now simplified.
---
.github/logToCs.py | 588 -------------------------------
.github/workflows/pre-commit.yml | 18 +-
2 files changed, 5 insertions(+), 601 deletions(-)
delete mode 100755 .github/logToCs.py
diff --git a/.github/logToCs.py b/.github/logToCs.py
deleted file mode 100755
index 7befd310a0a76..0000000000000
--- a/.github/logToCs.py
+++ /dev/null
@@ -1,588 +0,0 @@
-#!/usr/bin/env python3
-# pylint: disable=invalid-name
-"""
-Convert a log to CheckStyle format.
-
-Url: https://github.com/mdeweerd/LogToCheckStyle
-
-The log can then be used for generating annotations in a github action.
-
-Note: this script is very young and "quick and dirty".
- Patterns can be added to "PATTERNS" to match more messages.
-
-# Examples
-
-Assumes that logToCs.py is available as .github/logToCs.py.
-
-## Example 1:
-
-
-```yaml
- - run: |
- pre-commit run -all-files | tee pre-commit.log
- .github/logToCs.py pre-commit.log pre-commit.xml
- - uses: staabm/annotate-pull-request-from-checkstyle-action@v1
- with:
- files: pre-commit.xml
- notices-as-warnings: true # optional
-```
-
-## Example 2:
-
-
-```yaml
- - run: |
- pre-commit run --all-files | tee pre-commit.log
- - name: Add results to PR
- if: ${{ always() }}
- run: |
- .github/logToCs.py pre-commit.log | cs2pr
-```
-
-Author(s):
- - https://github.com/mdeweerd
-
-License: MIT License
-
-"""
-
-import argparse
-import datetime as dt
-import json
-import os
-import re
-import sys
-import xml.etree.ElementTree as ET # nosec
-
-
-def remove_prefix(string, prefix):
- """
- Remove prefix from string
-
- Provided for backward compatibility.
- """
- if prefix and string.startswith(prefix):
- return string[len(prefix) :]
- return string
-
-
-def convert_notices_to_checkstyle(notices, root_path=None):
- """
- Convert annotation list to CheckStyle xml string
- """
- root = ET.Element("checkstyle")
- for fields in notices:
- add_error_entry(root, **fields, root_path=root_path)
- return ET.tostring(root, encoding="utf_8").decode("utf_8")
-
-
-def convert_lines_to_notices(lines):
- """
- Convert provided message to CheckStyle format.
- """
- notices = []
- for line in lines:
- fields = parse_message(line)
- if fields:
- notices.append(fields)
- return notices
-
-
-def convert_text_to_notices(text):
- """
- Convert provided message to CheckStyle format.
- """
- return parse_file(text)
-
-
-# Initial version for Checkrun from:
-# https://github.com/tayfun/flake8-your-pr/blob/50a175cde4dd26a656734c5b64ba1e5bb27151cb/src/main.py#L7C1-L123C36
-# MIT Licence
-class CheckRun:
- """
- Represents the check run
- """
-
- GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", None)
- GITHUB_EVENT_PATH = os.environ.get("GITHUB_EVENT_PATH", None)
-
- URI = "https://api.github.com"
- API_VERSION = "2022-11-28"
- ACCEPT_HEADER_VALUE = "application/vnd.github+json"
- AUTH_HEADER_VALUE = f"Bearer {GITHUB_TOKEN}"
- # This is the max annotations Github API accepts in one go.
- MAX_ANNOTATIONS = 50
-
- def __init__(self):
- """
- Initialise Check Run object with information from checkrun
- """
- self.read_event_file()
- self.read_meta_data()
-
- def read_event_file(self):
- """
- Read the event file to get the event information later.
- """
- if self.GITHUB_EVENT_PATH is None:
- raise ValueError("Not running in github workflow")
- with open(self.GITHUB_EVENT_PATH, encoding="utf_8") as event_file:
- self.event = json.loads(event_file.read())
-
- def read_meta_data(self):
- """
- Get meta data from event information
- """
- self.repo_full_name = self.event["repository"]["full_name"]
- pull_request = self.event.get("pull_request")
- print("%r", self.event)
- if pull_request:
- self.head_sha = pull_request["head"]["sha"]
- else:
- print("%r", self.event)
- check_suite = self.event.get("check_suite", None)
- if check_suite is not None:
- self.head_sha = check_suite["pull_requests"][0]["base"]["sha"]
- else:
- self.head_sha = None # Can't annotate?
-
- def submit( # pylint: disable=too-many-arguments
- self,
- notices,
- title=None,
- summary=None,
- text=None,
- conclusion=None,
- ):
- """
- Submit annotations to github
-
- See:
- https://docs.github.com/en/rest/checks/runs?apiVersion=2022-11-28
- #update-a-check-run
-
- :param conclusion: success, failure
- """
- # pylint: disable=import-outside-toplevel
- import requests # Import here to not impose presence of module
-
- if self.head_sha is None:
- return
-
- output = {
- "annotations": notices[: CheckRun.MAX_ANNOTATIONS],
- }
- if title is not None:
- output["title"] = title
- if summary is not None:
- output["summary"] = summary
- if text is not None:
- output["text"] = text
- if conclusion is None:
- # action_required, cancelled, failure, neutral, success
- # skipped, stale, timed_out
- if bool(notices):
- conclusion = "failure"
- else:
- conclusion = "success"
-
- payload = {
- "name": "log-to-pr-annotation",
- "head_sha": self.head_sha,
- "status": "completed", # queued, in_progress, completed
- "conclusion": conclusion,
- # "started_at": dt.datetime.now(dt.timezone.utc).isoformat(),
- "completed_at": dt.datetime.now(dt.timezone.utc).isoformat(),
- "output": output,
- }
-
- # Create the check-run
- response = requests.post(
- f"{self.URI}/repos/{self.repo_full_name}/check-runs",
- headers={
- "Accept": self.ACCEPT_HEADER_VALUE,
- "Authorization": self.AUTH_HEADER_VALUE,
- "X-GitHub-Api-Version": self.API_VERSION,
- },
- json=payload,
- timeout=30,
- )
- print(response.content)
- response.raise_for_status()
-
-
-ANY_REGEX = r".*?"
-FILE_REGEX = r"\s*(?P\S.*?)\s*?"
-FILEGROUP_REGEX = r"\s*(?P\S.*?)\s*?"
-EOL_REGEX = r"[\r\n]"
-LINE_REGEX = r"\s*(?P\d+?)\s*?"
-COLUMN_REGEX = r"\s*(?P\d+?)\s*?"
-SEVERITY_REGEX = r"\s*(?Perror|warning|notice|style|info)\s*?"
-MSG_REGEX = r"\s*(?P.+?)\s*?"
-MULTILINE_MSG_REGEX = r"\s*(?P(?:.|.[\r\n])+)"
-# cpplint confidence index
-CONFIDENCE_REGEX = r"\s*\[(?P\d+)\]\s*?"
-
-
-# List of message patterns, add more specific patterns earlier in the list
-# Creating patterns by using constants makes them easier to define and read.
-PATTERNS = [
- # beautysh
- # File ftp.sh: error: "esac" before "case" in line 90.
- re.compile(
- f"^File {FILE_REGEX}:{SEVERITY_REGEX}:"
- f" {MSG_REGEX} in line {LINE_REGEX}.$"
- ),
- # beautysh
- # File socks4echo.sh: error: indent/outdent mismatch: -2.
- re.compile(f"^File {FILE_REGEX}:{SEVERITY_REGEX}: {MSG_REGEX}$"),
- # yamllint
- # ##[group].pre-commit-config.yaml
- # ##[error]97:14 [trailing-spaces] trailing spaces
- # ##[endgroup]
- re.compile(rf"^##\[group\]{FILEGROUP_REGEX}$"), # Start file group
- re.compile(
- rf"^##\[{SEVERITY_REGEX}\]{LINE_REGEX}:{COLUMN_REGEX}{MSG_REGEX}$"
- ), # Msg
- re.compile(r"^##(?P\[endgroup\])$"), # End file group
- # File socks4echo.sh: error: indent/outdent mismatch: -2.
- re.compile(f"^File {FILE_REGEX}:{SEVERITY_REGEX}: {MSG_REGEX}$"),
- # Emacs style
- # path/to/file:845:5: error - Expected 1 space after closing brace
- re.compile(
- rf"^{FILE_REGEX}:{LINE_REGEX}:{COLUMN_REGEX}:{SEVERITY_REGEX}"
- rf"-?\s{MSG_REGEX}$"
- ),
- # ESLint (JavaScript Linter), RoboCop, shellcheck
- # path/to/file.js:10:2: Some linting issue
- # path/to/file.rb:10:5: Style/Indentation: Incorrect indentation detected
- # path/to/script.sh:10:1: SC2034: Some shell script issue
- re.compile(f"^{FILE_REGEX}:{LINE_REGEX}:{COLUMN_REGEX}: {MSG_REGEX}$"),
- # Cpplint default output:
- # '%s:%s: %s [%s] [%d]\n'
- # % (filename, linenum, message, category, confidence)
- re.compile(f"^{FILE_REGEX}:{LINE_REGEX}:{MSG_REGEX}{CONFIDENCE_REGEX}$"),
- # MSVC
- # file.cpp(10): error C1234: Some error message
- re.compile(
- f"^{FILE_REGEX}\\({LINE_REGEX}\\):{SEVERITY_REGEX}{MSG_REGEX}$"
- ),
- # Java compiler
- # File.java:10: error: Some error message
- re.compile(f"^{FILE_REGEX}:{LINE_REGEX}:{SEVERITY_REGEX}:{MSG_REGEX}$"),
- # Python
- # File ".../logToCs.py", line 90 (note: code line follows)
- re.compile(f'^File "{FILE_REGEX}", line {LINE_REGEX}$'),
- # Pylint, others
- # path/to/file.py:10: [C0111] Missing docstring
- # others
- re.compile(f"^{FILE_REGEX}:{LINE_REGEX}: {MSG_REGEX}$"),
- # Shellcheck:
- # In script.sh line 76:
- re.compile(
- f"^In {FILE_REGEX} line {LINE_REGEX}:{EOL_REGEX}?"
- f"({MULTILINE_MSG_REGEX})?{EOL_REGEX}{EOL_REGEX}"
- ),
- # eslint:
- # /path/to/filename
- # 14:5 error Unexpected trailing comma comma-dangle
- re.compile(
- f"^{FILE_REGEX}{EOL_REGEX}"
- rf"\s+{LINE_REGEX}:{COLUMN_REGEX}\s+{SEVERITY_REGEX}\s+{MSG_REGEX}$"
- ),
-]
-
-# Exceptionnaly some regexes match messages that are not error.
-# This pattern matches those exceptions
-EXCLUDE_MSG_PATTERN = re.compile(
- r"^("
- r"Placeholder pattern" # To remove on first message pattern
- r")"
-)
-
-# Exceptionnaly some regexes match messages that are not error.
-# This pattern matches those exceptions
-EXCLUDE_FILE_PATTERN = re.compile(
- r"^("
- # Codespell: (appears as a file name):
- r"Used config files\b"
- r")"
-)
-
-# Severities available in CodeSniffer report format
-SEVERITY_NOTICE = "notice"
-SEVERITY_WARNING = "warning"
-SEVERITY_ERROR = "error"
-
-
-def strip_ansi(text: str):
- """
- Strip ANSI escape sequences from string (colors, etc)
- """
- return re.sub(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])", "", text)
-
-
-def parse_file(text):
- """
- Parse all messages in a file
-
- Returns the fields in a dict.
- """
- # pylint: disable=too-many-branches,too-many-statements
- # regex required to allow same group names
- try:
- import regex # pylint: disable=import-outside-toplevel
- except ImportError as exc:
- raise ImportError(
- "The 'parsefile' method requires 'python -m pip install regex'"
- ) from exc
-
- patterns = [pattern.pattern for pattern in PATTERNS]
- # patterns = [PATTERNS[0].pattern]
-
- file_group = None # The file name for the group (if any)
- full_regex = "(?:(?:" + (")|(?:".join(patterns)) + "))"
- results = []
-
- for fields in regex.finditer(
- full_regex, strip_ansi(text), regex.MULTILINE | regex.IGNORECASE
- ):
- if not fields:
- continue
- result = fields.groupdict()
-
- if len(result) == 0:
- continue
-
- severity = result.get("severity", None)
- file_name = result.get("file_name", None)
- confidence = result.pop("confidence", None)
- new_file_group = result.pop("file_group", None)
- file_endgroup = result.pop("file_endgroup", None)
- message = result.get("message", None)
-
- if new_file_group is not None:
- # Start of file_group, just store file
- file_group = new_file_group
- continue
-
- if file_endgroup is not None:
- file_group = None
- continue
-
- if file_name is None:
- if file_group is not None:
- file_name = file_group
- result["file_name"] = file_name
- else:
- # No filename, skip
- continue
- else:
- if EXCLUDE_FILE_PATTERN.search(file_name):
- # This file_name is excluded
- continue
-
- if message is not None:
- if EXCLUDE_MSG_PATTERN.search(message):
- # This message is excluded
- continue
-
- if confidence is not None:
- # Convert confidence level of cpplint
- # to warning, etc.
- confidence = int(confidence)
-
- if confidence <= 1:
- severity = SEVERITY_NOTICE
- elif confidence >= 5:
- severity = SEVERITY_ERROR
- else:
- severity = SEVERITY_WARNING
-
- if severity is None:
- severity = SEVERITY_ERROR
- else:
- severity = severity.lower()
-
- if severity in ["info", "style"]:
- severity = SEVERITY_NOTICE
-
- result["severity"] = severity
-
- results.append(result)
-
- return results
-
-
-def parse_message(message):
- """
- Parse message until it matches a pattern.
-
- Returns the fields in a dict.
- """
- for pattern in PATTERNS:
- fields = pattern.match(message, re.IGNORECASE)
- if not fields:
- continue
- result = fields.groupdict()
- if len(result) == 0:
- continue
-
- if "confidence" in result:
- # Convert confidence level of cpplint
- # to warning, etc.
- confidence = int(result["confidence"])
- del result["confidence"]
-
- if confidence <= 1:
- severity = SEVERITY_NOTICE
- elif confidence >= 5:
- severity = SEVERITY_ERROR
- else:
- severity = SEVERITY_WARNING
- result["severity"] = severity
-
- if "severity" not in result:
- result["severity"] = SEVERITY_ERROR
- else:
- result["severity"] = result["severity"].lower()
-
- if result["severity"] in ["info", "style"]:
- result["severity"] = SEVERITY_NOTICE
-
- return result
-
- # Nothing matched
- return None
-
-
-def add_error_entry( # pylint: disable=too-many-arguments
- root,
- severity,
- file_name,
- line=None,
- column=None,
- message=None,
- source=None,
- root_path=None,
-):
- """
- Add error information to the CheckStyle output being created.
- """
- file_element = find_or_create_file_element(
- root, file_name, root_path=root_path
- )
- error_element = ET.SubElement(file_element, "error")
- error_element.set("severity", severity)
- if line:
- error_element.set("line", line)
- if column:
- error_element.set("column", column)
- if message:
- error_element.set("message", message)
- if source:
- # To verify if this is a valid attribute
- error_element.set("source", source)
-
-
-def find_or_create_file_element(root, file_name: str, root_path=None):
- """
- Find/create file element in XML document tree.
- """
-
- if root_path is not None:
- file_name = remove_prefix(file_name, root_path)
- for file_element in root.findall("file"):
- if file_element.get("name") == file_name:
- return file_element
- file_element = ET.SubElement(root, "file")
- file_element.set("name", file_name)
- return file_element
-
-
-def main():
- """
- Parse the script arguments and get the conversion done.
- """
- parser = argparse.ArgumentParser(
- description="Convert messages to Checkstyle XML format."
- )
- parser.add_argument(
- "input", help="Input file. Use '-' for stdin.", nargs="?", default="-"
- )
- parser.add_argument(
- "output",
- help="Output file. Use '-' for stdout.",
- nargs="?",
- default="-",
- )
- parser.add_argument(
- "-i",
- "--in",
- dest="input_named",
- help="Input filename. Overrides positional input.",
- )
- parser.add_argument(
- "-o",
- "--out",
- dest="output_named",
- help="Output filename. Overrides positional output.",
- )
- parser.add_argument(
- "--root",
- metavar="ROOT_PATH",
- help="Root directory to remove from file paths."
- " Defaults to working directory.",
- default=os.getcwd(),
- )
- parser.add_argument(
- "--github-annotate",
- action=argparse.BooleanOptionalAction,
- help="Annotate when in Github workflow.",
- # Currently disabled,
- # Future: (os.environ.get("GITHUB_EVENT_PATH", None) is not None),
- default=False,
- )
-
- args = parser.parse_args()
-
- if args.input == "-" and args.input_named:
- with open(
- args.input_named, encoding="utf_8", errors="surrogateescape"
- ) as input_file:
- text = input_file.read()
- elif args.input != "-":
- with open(
- args.input, encoding="utf_8", errors="surrogateescape"
- ) as input_file:
- text = input_file.read()
- else:
- text = sys.stdin.read()
-
- root_path = os.path.join(args.root, "")
-
- try:
- notices = convert_text_to_notices(text)
- except ImportError:
- notices = convert_lines_to_notices(re.split(r"[\r\n]+", text))
-
- checkstyle_xml = convert_notices_to_checkstyle(
- notices, root_path=root_path
- )
-
- if args.output == "-" and args.output_named:
- with open(args.output_named, "w", encoding="utf_8") as output_file:
- output_file.write(checkstyle_xml)
- elif args.output != "-":
- with open(args.output, "w", encoding="utf_8") as output_file:
- output_file.write(checkstyle_xml)
- else:
- print(checkstyle_xml)
-
- if args.github_annotate:
- checkrun = CheckRun()
- checkrun.submit(notices)
-
-
-if __name__ == "__main__":
- main()
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
index d0cdcb90ef38a..1ae4d3387f8fe 100644
--- a/.github/workflows/pre-commit.yml
+++ b/.github/workflows/pre-commit.yml
@@ -7,7 +7,6 @@ jobs:
pre-commit:
runs-on: ubuntu-latest
env:
- LOG_TO_CS: .github/logToCs.py
RAW_LOG: pre-commit.log
CS_XML: pre-commit.xml
steps:
@@ -37,7 +36,7 @@ jobs:
with:
cache: pip
python-version: "3.11"
- - run: python -m pip install pre-commit regex
+ - run: python -m pip install pre-commit
# Restore previous cache of precommit
- uses: actions/cache/restore@v4
with:
@@ -102,19 +101,12 @@ jobs:
pre-commit run --hook-stage manual -a php-cs-with-cache | tee -a ${RAW_LOG}
ls -l ~/.cache/pre-commit/
- # If error, we convert log in the checkstyle format
- - name: Convert Raw Log to CheckStyle format
- if: ${{ failure() }}
- run: |
- python ${LOG_TO_CS} ${RAW_LOG} ${CS_XML}
- # Annotate the git sources with the log messages
- - name: Annotate Source Code with Messages
- uses: staabm/annotate-pull-request-from-checkstyle-action@v1
+ - name: Convert Raw Log to Annotations
+ uses: mdeweerd/logToCheckStyle@v2024.2.9
if: ${{ failure() }}
with:
- files: ${{ env.CS_XML }}
- notices-as-warnings: true # optional
- prepend-filename: true # optional
+ in: ${{ env.RAW_LOG }}
+
# Save the precommit cache
- uses: actions/cache/save@v4
if: ${{ ! cancelled() }}
From d0c0dee616968d13f14385d975266c9857ba97a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?=
Date: Mon, 4 Mar 2024 18:23:03 +0100
Subject: [PATCH 064/117] fix typo in ChangeLog (#28613)
* fix typo in ChangeLog
* Update ChangeLog
---
ChangeLog | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index de0cb66b9686a..bb3afe1e22edc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -24,7 +24,7 @@ FIX: Bad column for total in bom list
FIX: Bad condition on button back to draft on recruitment job.
FIX: Bad CRLF when sending text only content. Fix dol_htmlwithnojs()
FIX: Bad picto on list of permission of a user when user not admin
-FIX: bad timzeone for the start/end date of an event
+FIX: bad timezone for the start/end date of an event
FIX: Better test on validity of compute field syntax with parenthesis
FIX: close #28279
FIX: disabled pito of menu must be greyed.
@@ -47,7 +47,7 @@ FIX: Shipment closing action has wrong value (#28174)
FIX: some tooltips has disappeared on invoice action button
FIX: Special code is now transmitted by args only in order supplier (#28546)
FIX: subscription must be editable when accounting isn't reconciled (#28469)
-FIX: Value of field int = 0 from modulebuilder must nto be set to null
+FIX: Value of field int = 0 from modulebuilder must not be set to null
***** ChangeLog for 19.0.0 compared to 18.0.0 *****
From 55c0efae3fb5f8d387eec9674fa5c784a3caa9d2 Mon Sep 17 00:00:00 2001
From: noec764 <58433943+noec764@users.noreply.github.com>
Date: Mon, 4 Mar 2024 18:26:38 +0100
Subject: [PATCH 065/117] FIX: Special code is now transmitted by args only in
order supplier (#28619)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Noé
---
htdocs/fourn/commande/card.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php
index 17b99779094b8..4fa93836b767a 100644
--- a/htdocs/fourn/commande/card.php
+++ b/htdocs/fourn/commande/card.php
@@ -1344,8 +1344,6 @@
$tva_tx = get_default_tva($soc, $mysoc, $lines[$i]->fk_product, $product_fourn_price_id);
}
- $object->special_code = $lines[$i]->special_code;
-
$result = $object->addline(
$desc,
$lines[$i]->subprice,
@@ -1368,7 +1366,9 @@
$lines[$i]->fk_unit,
0,
$element,
- !empty($lines[$i]->id) ? $lines[$i]->id : $lines[$i]->rowid
+ !empty($lines[$i]->id) ? $lines[$i]->id : $lines[$i]->rowid,
+ -1,
+ $lines[$i]->special_code
);
if ($result < 0) {
From 6cc9ac55429f37b83f058993875e62181bfec534 Mon Sep 17 00:00:00 2001
From: Christian Humpel <78662388+Humml87@users.noreply.github.com>
Date: Mon, 4 Mar 2024 18:59:37 +0100
Subject: [PATCH 066/117] FIX: Count of virtual stock at Services and MoLine
with disabled stock change (#28580)
* fix the count of virtual stock
* - fix "Found non sanitized string" ?
---------
Co-authored-by: christian.humpel
---
htdocs/product/class/product.class.php | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php
index 5288300c443cc..b959d87063f2d 100644
--- a/htdocs/product/class/product.class.php
+++ b/htdocs/product/class/product.class.php
@@ -3469,6 +3469,8 @@ public function load_stats_inproduction($socid = 0, $filtrestatut = '', $forVirt
// phpcs:enable
global $conf, $user, $hookmanager, $action;
+ $serviceStockIsEnabled = isModEnabled("service") && getDolGlobalString('STOCK_SUPPORTS_SERVICES');
+
$sql = "SELECT COUNT(DISTINCT m.fk_soc) as nb_customers, COUNT(DISTINCT m.rowid) as nb,";
$sql .= " COUNT(mp.rowid) as nb_rows, SUM(mp.qty) as qty, role";
$sql .= " FROM ".$this->db->prefix()."mrp_production as mp";
@@ -3480,6 +3482,7 @@ public function load_stats_inproduction($socid = 0, $filtrestatut = '', $forVirt
$sql .= " WHERE m.rowid = mp.fk_mo";
$sql .= " AND m.entity IN (".getEntity($forVirtualStock && getDolGlobalString('STOCK_CALCULATE_VIRTUAL_STOCK_TRANSVERSE_MODE') ? 'stock' : 'mrp').")";
$sql .= " AND mp.fk_product = ".((int) $this->id);
+ $sql .= " AND mp.disable_stock_change IN (0)";
if (!$user->hasRight('societe', 'client', 'voir') && !$socid && !$forVirtualStock) {
$sql .= " AND m.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
}
@@ -3492,6 +3495,9 @@ public function load_stats_inproduction($socid = 0, $filtrestatut = '', $forVirt
if (!empty($dateofvirtualstock)) {
$sql .= " AND m.date_valid <= '".$this->db->idate($dateofvirtualstock)."'"; // better date to code ? end of production ?
}
+ if (!$serviceStockIsEnabled) {
+ $sql .= "AND EXISTS (SELECT p.rowid FROM ".$this->db->prefix()."product AS p WHERE p.rowid = ".((int) $this->id)." AND p.fk_product_type IN (0))";
+ }
$sql .= " GROUP BY role";
$this->stats_mrptoconsume['customers'] = 0;
From d7f3feba747b9177a80d11384cbb3bae84dc9642 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Tue, 5 Mar 2024 03:57:56 +0100
Subject: [PATCH 067/117] Merge branch '18.0' of
git@github.com:Dolibarr/dolibarr.git into 19.0
---
htdocs/core/lib/functions.lib.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index f21e08e8261ab..6fe032f545666 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -2224,7 +2224,7 @@ function dol_get_fiche_head($links = array(), $active = '', $title = '', $notab
$tabsname = str_replace("@", "", $picto);
}
$out .= '';
- $out .= '
'; // Do not use "reposition" class in the "More".
+ $out .= '
'; // Do not use "reposition" class in the "More".
$out .= '
';
$out .= $outmore;
$out .= '
';
From 26c307c0a422558d6224b9366bd938ccd3b6fb9d Mon Sep 17 00:00:00 2001
From: John BOTELLA
Date: Tue, 5 Mar 2024 17:16:11 +0100
Subject: [PATCH 068/117] Fix extrafield ajax search default on edit (#28631)
---
htdocs/core/class/html.form.class.php | 49 +++++++++++++++++----------
1 file changed, 31 insertions(+), 18 deletions(-)
diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index 29cb68f171d67..40e9391877132 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -8014,22 +8014,22 @@ protected function constructMemberListOption(&$objp, &$opt, &$optJson, $selected
* Can use autocomplete with ajax after x key pressed or a full combo, depending on setup.
* This is the generic method that will replace all specific existing methods.
*
- * @param string $objectdesc 'ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]'. For hard coded custom needs. Try to prefer method using $objectfield instead of $objectdesc.
- * @param string $htmlname Name of HTML select component
- * @param int $preselectedvalue Preselected value (ID of element)
- * @param string $showempty ''=empty values not allowed, 'string'=value show if we allow empty values (for example 'All', ...)
- * @param string $searchkey Search criteria
- * @param string $placeholder Place holder
- * @param string $morecss More CSS
- * @param string $moreparams More params provided to ajax call
- * @param int $forcecombo Force to load all values and output a standard combobox (with no beautification)
- * @param int $disabled 1=Html component is disabled
- * @param string $selected_input_value Value of preselected input text (for use with ajax)
- * @param string $objectfield Object:Field that contains the definition (in table $fields or $extrafields). Example: 'Object:xxx' or 'Module_Object:xxx' or 'Object:options_xxx' or 'Module_Object:options_xxx'
+ * @param string $objectdesc 'ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]'. For hard coded custom needs. Try to prefer method using $objectfield instead of $objectdesc.
+ * @param string $htmlname Name of HTML select component
+ * @param int $preSelectedValue Preselected value (ID of element)
+ * @param string $showempty ''=empty values not allowed, 'string'=value show if we allow empty values (for example 'All', ...)
+ * @param string $searchkey Search criteria
+ * @param string $placeholder Place holder
+ * @param string $morecss More CSS
+ * @param string $moreparams More params provided to ajax call
+ * @param int $forcecombo Force to load all values and output a standard combobox (with no beautification)
+ * @param int $disabled 1=Html component is disabled
+ * @param string $selected_input_value Value of preselected input text (for use with ajax)
+ * @param string $objectfield Object:Field that contains the definition (in table $fields or $extrafields). Example: 'Object:xxx' or 'Module_Object:xxx' or 'Object:options_xxx' or 'Module_Object:options_xxx'
* @return string Return HTML string
* @see selectForFormsList(), select_thirdparty_list()
*/
- public function selectForForms($objectdesc, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $disabled = 0, $selected_input_value = '', $objectfield = '')
+ public function selectForForms($objectdesc, $htmlname, $preSelectedValue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $disabled = 0, $selected_input_value = '', $objectfield = '')
{
global $conf, $extrafields, $user;
@@ -8128,10 +8128,23 @@ public function selectForForms($objectdesc, $htmlname, $preselectedvalue, $showe
if (!empty($conf->use_javascript_ajax) && getDolGlobalString($confkeyforautocompletemode) && !$forcecombo) {
// No immediate load of all database
$placeholder = '';
- if ($preselectedvalue && empty($selected_input_value)) {
- $objecttmp->fetch($preselectedvalue);
+
+ if ($preSelectedValue && empty($selected_input_value)) {
+ $objecttmp->fetch($preSelectedValue);
$selected_input_value = ($prefixforautocompletemode == 'company' ? $objecttmp->name : $objecttmp->ref);
- //unset($objecttmp);
+
+ $oldValueForShowOnCombobox = 0;
+ foreach ($objecttmp->fields as $fieldK => $fielV) {
+ if (!$fielV['showoncombobox'] || empty($objecttmp->$fieldK)) continue;
+
+ if (!$oldValueForShowOnCombobox) {
+ $selected_input_value = '';
+ }
+
+ $selected_input_value .= $oldValueForShowOnCombobox ? ' - ' : '';
+ $selected_input_value .= $objecttmp->$fieldK;
+ $oldValueForShowOnCombobox = empty($fielV['showoncombobox']) ? 0 : $fielV['showoncombobox'];
+ }
}
// Set url and param to call to get json of the search results
@@ -8139,12 +8152,12 @@ public function selectForForms($objectdesc, $htmlname, $preselectedvalue, $showe
$urloption = 'htmlname=' . urlencode($htmlname) . '&outjson=1&objectdesc=' . urlencode($objectdescorig) . '&objectfield='.urlencode($objectfield) . ($sortfield ? '&sortfield=' . urlencode($sortfield) : '');
// Activate the auto complete using ajax call.
- $out .= ajax_autocompleter($preselectedvalue, $htmlname, $urlforajaxcall, $urloption, getDolGlobalString($confkeyforautocompletemode), 0, array());
+ $out .= ajax_autocompleter($preSelectedValue, $htmlname, $urlforajaxcall, $urloption, getDolGlobalString($confkeyforautocompletemode), 0);
$out .= '';
$out .= '';
} else {
// Immediate load of table record.
- $out .= $this->selectForFormsList($objecttmp, $htmlname, $preselectedvalue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, 0, $disabled, $sortfield, $filter);
+ $out .= $this->selectForFormsList($objecttmp, $htmlname, $preSelectedValue, $showempty, $searchkey, $placeholder, $morecss, $moreparams, $forcecombo, 0, $disabled, $sortfield, $filter);
}
return $out;
From 75f1de8f8f5140235b45f80633f65192ab14b847 Mon Sep 17 00:00:00 2001
From: Ferran Marcet
Date: Tue, 5 Mar 2024 18:07:05 +0100
Subject: [PATCH 069/117] Fix: Deposit lines are not created correctly (#28646)
* FIX: The minimum price in proposals is not checked correctly
* Fix: Deposit lines are not created correctly
* Fix: Volver a dejar como estaba
* Fix: Deposit lines are not created correctly
---
htdocs/compta/facture/card.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php
index 0dd1b661b33ca..bb96c2c2f815a 100644
--- a/htdocs/compta/facture/card.php
+++ b/htdocs/compta/facture/card.php
@@ -12,7 +12,7 @@
* Copyright (C) 2013 Jean-Francois FERRY
* Copyright (C) 2013-2014 Florian Henry
* Copyright (C) 2013 Cédric Salvador
- * Copyright (C) 2014-2019 Ferran Marcet
+ * Copyright (C) 2014-2024 Ferran Marcet
* Copyright (C) 2015-2016 Marcos GarcÃa
* Copyright (C) 2018-2021 Frédéric France
* Copyright (C) 2022 Gauthier VERDOL
@@ -1596,7 +1596,7 @@
null,
0,
'',
- 1
+ (!empty($conf->global->MAIN_DEPOSIT_MULTI_TVA)?0:1)
);
}
From 43b1adb4c6551cf26d5cd516f609af80b21301a9 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Wed, 6 Mar 2024 01:40:06 +0100
Subject: [PATCH 070/117] Fix bad var name in security setup page
---
htdocs/admin/system/security.php | 4 ++--
htdocs/langs/en_US/errors.lang | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/htdocs/admin/system/security.php b/htdocs/admin/system/security.php
index 6ad04701a522e..199b715d2ef63 100644
--- a/htdocs/admin/system/security.php
+++ b/htdocs/admin/system/security.php
@@ -272,7 +272,7 @@
if (file_exists($installlock)) { // If install not locked, no need to show this.
if (file_exists($upgradeunlock)) {
print ''.$langs->trans("DolibarrUpgrade").': ';
- print img_warning().' '.$langs->trans("UpgradeHasBeenUnlocked", $upgradeunlock);
+ print img_warning().' '.$langs->trans("WarningUpgradeHasBeenUnlocked", $upgradeunlock);
print '
';
}
}
@@ -756,7 +756,7 @@
print 'WEBSITE_MAIN_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or")." \"strict-origin-when-cross-origin\")
";
print '
';
-print 'WEBSITE_MAIN_SECURITY_FORCESTS = '.getDolGlobalString('>WEBSITE_MAIN_SECURITY_FORCESTS', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Example").": \"max-age=31536000; includeSubDomains\")
";
+print 'WEBSITE_MAIN_SECURITY_FORCESTS = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCESTS', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Example").": \"max-age=31536000; includeSubDomains\")
";
print '
';
print 'WEBSITE_MAIN_SECURITY_FORCEPP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCEPP', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Example").": \"camera: (); microphone: ();\")
";
diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang
index b4883e7f6f49f..625cb2bfc51a6 100644
--- a/htdocs/langs/en_US/errors.lang
+++ b/htdocs/langs/en_US/errors.lang
@@ -343,6 +343,7 @@ WarningConfFileMustBeReadOnly=Warning, your config file (htdocs/conf/conf.php
WarningsOnXLines=Warnings on %s source record(s)
WarningNoDocumentModelActivated=No model, for document generation, has been activated. A model will be chosen by default until you check your module setup.
WarningLockFileDoesNotExists=Warning, once setup is finished, you must disable the installation/migration tools by adding a file install.lock into directory %s. Omitting the creation of this file is a grave security risk.
+WarningUpgradeHasBeenUnlocked=Warning, upgrade process has been unlocked for everybody
WarningUntilDirRemoved=This security warning will remain active as long as the vulnerability is present.
WarningCloseAlways=Warning, closing is done even if amount differs between source and target elements. Enable this feature with caution.
WarningUsingThisBoxSlowDown=Warning, using this box slow down seriously all pages showing the box.
From 1552fac711177f376dee15e39812107619d681db Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Wed, 6 Mar 2024 01:54:41 +0100
Subject: [PATCH 071/117] Fix strict-origin
---
htdocs/admin/system/security.php | 2 +-
htdocs/main.inc.php | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/htdocs/admin/system/security.php b/htdocs/admin/system/security.php
index 199b715d2ef63..fce38310605aa 100644
--- a/htdocs/admin/system/security.php
+++ b/htdocs/admin/system/security.php
@@ -753,7 +753,7 @@
print ' ('.$langs->trans("Example").": \"frame-ancestors 'self'; default-src 'self' 'unsafe-inline'; style-src https://cdnjs.cloudflare.com *.googleapis.com; script-src *.transifex.com *.google-analytics.com *.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src * data:;\")
";
print '
';
-print 'WEBSITE_MAIN_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or")." \"strict-origin-when-cross-origin\")
";
+print 'WEBSITE_MAIN_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").'=\"strict-origin\" '.$langs->trans("or")." \"strict-origin-when-cross-origin\")
";
print '
';
print 'WEBSITE_MAIN_SECURITY_FORCESTS = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCESTS', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Example").": \"max-age=31536000; includeSubDomains\")
";
diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php
index 548d2fb2099df..44b62e8bb8f3a 100644
--- a/htdocs/main.inc.php
+++ b/htdocs/main.inc.php
@@ -1669,9 +1669,9 @@ function top_httphead($contenttype = 'text/html', $forcenocache = 0)
// Referrer-Policy
// Say if we must provide the referrer when we jump onto another web page.
- // Default browser are 'strict-origin-when-cross-origin' (only domain is sent on other domain switching), we want more so we use 'same-origin' so browser doesn't send any referrer when going into another web site domain.
+ // Default browser are 'strict-origin-when-cross-origin' (only domain is sent on other domain switching), we want more so we use 'strict-origin' so browser doesn't send any referrer when going into another web site domain.
if (!defined('MAIN_SECURITY_FORCERP')) {
- $referrerpolicy = getDolGlobalString('MAIN_SECURITY_FORCERP', "same-origin");
+ $referrerpolicy = getDolGlobalString('MAIN_SECURITY_FORCERP', "strict-origin");
header("Referrer-Policy: ".$referrerpolicy);
}
From 1a9fa740a5fbe8301a83851c76cdc7bd166be540 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Wed, 6 Mar 2024 13:32:15 +0100
Subject: [PATCH 072/117] Fix quote
---
htdocs/admin/system/security.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/htdocs/admin/system/security.php b/htdocs/admin/system/security.php
index fce38310605aa..8aee55d46ba4d 100644
--- a/htdocs/admin/system/security.php
+++ b/htdocs/admin/system/security.php
@@ -753,7 +753,7 @@
print ' ('.$langs->trans("Example").": \"frame-ancestors 'self'; default-src 'self' 'unsafe-inline'; style-src https://cdnjs.cloudflare.com *.googleapis.com; script-src *.transifex.com *.google-analytics.com *.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src * data:;\")
";
print '
';
-print 'WEBSITE_MAIN_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").'=\"strict-origin\" '.$langs->trans("or")." \"strict-origin-when-cross-origin\")
";
+print 'WEBSITE_MAIN_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Recommended").': '.$langs->trans("Undefined")."=\"strict-origin\" ".$langs->trans("or")." \"strict-origin-when-cross-origin\")
";
print '
';
print 'WEBSITE_MAIN_SECURITY_FORCESTS = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCESTS', ''.$langs->trans("Undefined").'').' ('.$langs->trans("Example").": \"max-age=31536000; includeSubDomains\")
";
From f1aa29507a62786c8de29fb0afc5c38e477f04bc Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Wed, 6 Mar 2024 15:01:25 +0100
Subject: [PATCH 073/117] Fix sec more complete list of forbidden function
---
htdocs/core/lib/functions.lib.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 6fe032f545666..0298ce0d439fc 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -9738,6 +9738,7 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1'
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "require", "include", "mkdir", "rmdir", "symlink", "touch", "unlink", "umask"));
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("get_defined_functions", "get_defined_vars", "get_defined_constants", "get_declared_classes"));
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("function", "call_user_func"));
+ $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("require", "include", "require_once", "include_once"));
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("eval", "create_function", "assert", "mb_ereg_replace")); // function with eval capabilities
$forbiddenphpmethods = array('invoke', 'invokeArgs'); // Method of ReflectionFunction to execute a function
From 2d9801ffe33c22ea9d6c65a0b5bdd49e487712be Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Wed, 6 Mar 2024 15:01:25 +0100
Subject: [PATCH 074/117] Fix sec more complete list of forbidden function
---
htdocs/core/lib/functions.lib.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index cbf8fee96e042..181825a689e77 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -9297,6 +9297,7 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1'
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "require", "include", "mkdir", "rmdir", "symlink", "touch", "unlink", "umask"));
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("get_defined_functions", "get_defined_vars", "get_defined_constants", "get_declared_classes"));
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("function", "call_user_func"));
+ $forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("require", "include", "require_once", "include_once"));
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("eval", "create_function", "assert", "mb_ereg_replace")); // function with eval capabilities
$forbiddenphpmethods = array('invoke', 'invokeArgs'); // Method of ReflectionFunction to execute a function
From 91b994b89ce6a5263bdedd36dff1c43141f6767a Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Wed, 6 Mar 2024 17:20:44 +0100
Subject: [PATCH 075/117] Prepare 18.0.6
---
htdocs/filefunc.inc.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php
index cba47566c2bac..9e1046d439f94 100644
--- a/htdocs/filefunc.inc.php
+++ b/htdocs/filefunc.inc.php
@@ -34,7 +34,7 @@
define('DOL_APPLICATION_TITLE', 'Dolibarr');
}
if (!defined('DOL_VERSION')) {
- define('DOL_VERSION', '18.0.5'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c
+ define('DOL_VERSION', '18.0.6'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c
}
if (!defined('EURO')) {
From 4dcf98b9f7d5e26dd4c4c62bc4a980e389cc61aa Mon Sep 17 00:00:00 2001
From: ATM-NicolasV <92087862+ATM-NicolasV@users.noreply.github.com>
Date: Thu, 7 Mar 2024 15:55:07 +0100
Subject: [PATCH 076/117] fix entity in sql from RemoveFromGroup (#28682)
---
htdocs/user/class/user.class.php | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php
index 1543d5798393e..0ec4d6fdf5ab4 100644
--- a/htdocs/user/class/user.class.php
+++ b/htdocs/user/class/user.class.php
@@ -2377,7 +2377,11 @@ public function RemoveFromGroup($group, $entity, $notrigger = 0)
$sql = "DELETE FROM ".MAIN_DB_PREFIX."usergroup_user";
$sql .= " WHERE fk_user = ".((int) $this->id);
$sql .= " AND fk_usergroup = ".((int) $group);
- $sql .= " AND entity = ".((int) $entity);
+ if (empty($entity)) {
+ $sql .= " AND entity IN (0, 1)"; // group may be in entity 0 (so $entity=0) and link with user into entity 1.
+ } else {
+ $sql .= " AND entity = ".((int) $entity);
+ }
$result = $this->db->query($sql);
if ($result) {
From 7bb55aa22528cf2ac35303a957113170ebc58af0 Mon Sep 17 00:00:00 2001
From: atm-adrien <67913809+atm-adrien@users.noreply.github.com>
Date: Thu, 7 Mar 2024 15:56:17 +0100
Subject: [PATCH 077/117] FIX : Translation for select (#28677)
* FIX : Adding thez dependencies list feature for select fields
* FIX : Adding some spaces
* FIX : View
* FIX : Translating
---
htdocs/core/class/commonobject.class.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index 47060b949f464..9ef1f4c94f4cd 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -7330,7 +7330,7 @@ public function showInputField($val, $key, $value, $moreparam = '', $keysuffix =
$isDependList = 1;
}
$out .= (!empty($parent) ? ' parent="'.$parent.'"' : '');
- $out .= '>'.$valb.'';
+ $out .= '>'.$langs->trans($valb).'';
}
$out .= '';
} elseif ($type == 'sellist') {
@@ -7954,7 +7954,7 @@ public function showOutputField($val, $key, $value, $moreparam = '', $keysuffix
} elseif ($type == 'select') {
$value = isset($param['options'][$value]) ? $param['options'][$value] : '';
if (strpos($value, "|") !== false) {
- $value = explode('|', $value)[0];
+ $value = $langs->trans(explode('|', $value)[0]);
}
} elseif ($type == 'sellist') {
$param_list = array_keys($param['options']);
From 2d8223eefb5a3e493a71a358626c64e051068034 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur
Date: Thu, 7 Mar 2024 16:16:49 +0100
Subject: [PATCH 078/117] Doc
---
htdocs/admin/system/security.php | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/htdocs/admin/system/security.php b/htdocs/admin/system/security.php
index 6ad04701a522e..e19463934af4b 100644
--- a/htdocs/admin/system/security.php
+++ b/htdocs/admin/system/security.php
@@ -341,12 +341,13 @@
}
print '$dolibarr_main_stream_to_disable: ';
+// $arrayofstreamtodisable is defined into filefunc.inc.php
if (empty($dolibarr_main_stream_to_disable)) {
print ''.$langs->trans("Undefined").' = '.join(', ', $arrayofstreamtodisable).'';
} else {
print join(', ', $dolibarr_main_stream_to_disable);
}
-print ' -> PHP streams allowed = ';
+print ' -> Current PHP streams allowed = ';
$arrayofstreams = stream_get_wrappers();
if (!empty($arrayofstreams)) {
sort($arrayofstreams);
From 8870be3c3d211385f7a7061fb5eef4ee5cb3790d Mon Sep 17 00:00:00 2001
From: Rikard Bosnjakovic
Date: Thu, 7 Mar 2024 16:43:04 +0100
Subject: [PATCH 079/117] Update card.php (#28679)
Fix #25130
Co-authored-by: Laurent Destailleur
---
htdocs/expedition/card.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/htdocs/expedition/card.php b/htdocs/expedition/card.php
index fd83a09ab0e90..45cbba2834420 100644
--- a/htdocs/expedition/card.php
+++ b/htdocs/expedition/card.php
@@ -2762,7 +2762,7 @@
// Presend form
$modelmail = 'shipping_send';
- $defaulttopic = $langs->trans('SendShippingRef');
+ $defaulttopic = 'SendShippingRef';
$diroutput = $conf->expedition->dir_output.'/sending';
$trackid = 'shi'.$object->id;
From cbd331256d937c92a384bf6183b277e4f4bb0678 Mon Sep 17 00:00:00 2001
From: Jon Bendtsen
Date: Thu, 7 Mar 2024 19:01:38 +0100
Subject: [PATCH 080/117] using note_public since note_private is not working
(#28675)
Co-authored-by: Jon Bendtsen
---
htdocs/adherents/subscription/card.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/htdocs/adherents/subscription/card.php b/htdocs/adherents/subscription/card.php
index b2dc0a57a5357..3b59dab63a2f6 100644
--- a/htdocs/adherents/subscription/card.php
+++ b/htdocs/adherents/subscription/card.php
@@ -238,7 +238,7 @@
// Label
print ''.$langs->trans("Label").' | ';
print '';
- print ' |
';
+ print '