From c577d1c51eeb16c3abb33c022502d57b011aae5b Mon Sep 17 00:00:00 2001 From: Ferran Marcet Date: Thu, 13 May 2021 13:35:28 +0200 Subject: [PATCH 01/23] FIX: Impossible to add multiple localtax2 --- htdocs/admin/dict.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index b7f65ddf91f..fbe7d924cbc 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -9,7 +9,7 @@ * Copyright (C) 2012-2015 Marcos García * Copyright (C) 2012 Christophe Battarel * Copyright (C) 2011-2016 Alexandre Spangaro - * Copyright (C) 2015 Ferran Marcet + * Copyright (C) 2015-2021 Ferran Marcet * Copyright (C) 2016 Raphaël Doursenaud * Copyright (C) 2019 Frédéric France * @@ -777,6 +777,9 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) elseif (in_array($keycode, array('joinfile', 'private', 'position', 'scale'))) { $sql .= (int) GETPOST($keycode, 'int'); } + elseif ($keycode == 'localtax2') { + $sql .= "'".GETPOST($keycode, 'alpha')."'"; + } else { $sql .= "'".$db->escape(GETPOST($keycode, 'nohtml'))."'"; } @@ -843,6 +846,9 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) elseif (in_array($keycode, array('private', 'position', 'scale'))) { $sql .= (int) GETPOST($keycode, 'int'); } + elseif ($keycode == 'localtax2') { + $sql .= "'".GETPOST($keycode, 'alpha')."'"; + } else { $sql .= "'".$db->escape(GETPOST($keycode, 'nohtml'))."'"; } From acadef72c1d8bd734573e3afdadff24271f70818 Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Fri, 14 May 2021 18:01:22 +0200 Subject: [PATCH 02/23] Fix use supplier relative discount in replenish order creation --- htdocs/product/stock/replenish.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index dbf07c92d01..5d8e1f4a790 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -211,7 +211,9 @@ if ($action == 'order' && isset($_POST['valid'])) if ($resql && $db->num_rows($resql) > 0) { $obj = $db->fetch_object($resql); $order->fetch($obj->rowid); + $order->fetch_thirdparty(); foreach ($supplier['lines'] as $line) { + if(empty($line->remise_percent)) $line->remise_percent = $order->thirdparty->remise_supplier_percent; $result = $order->addline( $line->desc, $line->subprice, @@ -248,6 +250,7 @@ if ($action == 'order' && isset($_POST['valid'])) //trick to know which orders have been generated this way $order->source = 42; foreach ($supplier['lines'] as $line) { + if(empty($line->remise_percent)) $line->remise_percent = $order->thirdparty->remise_supplier_percent; $order->lines[] = $line; } $order->cond_reglement_id = $order->thirdparty->cond_reglement_supplier_id; From 1fbd53993f45901f5fb3d7e5c6bbf9df884e2b06 Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Sun, 16 May 2021 19:07:36 +0200 Subject: [PATCH 03/23] Fix missing substitutionarray on ticket presend --- htdocs/ticket/card.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 6d14d29202f..a32ec67a11e 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -1297,13 +1297,23 @@ elseif (empty($action) || $action == 'view' || $action == 'addlink' || $action = // add a message if ($action == 'presend' || $action == 'presend_addmessage') { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($_REQUEST['lang_id'])) { + $newlang = $_REQUEST['lang_id']; + } + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + $newlang = $object->thirdparty->default_lang; + } + $arrayoffamiliestoexclude = array('objectamount'); + $action = 'add_message'; // action to use to post the message $modelmail = 'ticket_send'; // Substitution array $morehtmlright = ''; $help = ""; - $substitutionarray = array(); + $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, $arrayoffamiliestoexclude, $object); if ($object->fk_soc > 0) { $object->fetch_thirdparty(); $substitutionarray['__THIRDPARTY_NAME__'] = $object->thirdparty->name; From c36f231f415eb3d6f6eeda42da629eedcb2de27b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 May 2021 07:34:56 +0200 Subject: [PATCH 04/23] Update card.php --- htdocs/ticket/card.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index a32ec67a11e..cb428712913 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -1299,8 +1299,8 @@ elseif (empty($action) || $action == 'view' || $action == 'addlink' || $action = { $outputlangs = $langs; $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($_REQUEST['lang_id'])) { - $newlang = $_REQUEST['lang_id']; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { + $newlang = GETPOST('lang_id', 'aZ09'); } if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { $newlang = $object->thirdparty->default_lang; From dd88f9cd767648860589be45a2a752fdd3e4a910 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 May 2021 07:37:01 +0200 Subject: [PATCH 05/23] Update card.php --- htdocs/ticket/card.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index cb428712913..857365203f8 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -1297,12 +1297,16 @@ elseif (empty($action) || $action == 'view' || $action == 'addlink' || $action = // add a message if ($action == 'presend' || $action == 'presend_addmessage') { + if ($object->fk_soc > 0) { + $object->fetch_thirdparty(); + } + $outputlangs = $langs; $newlang = ''; if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && is_object($object->thirdparty)) { $newlang = $object->thirdparty->default_lang; } $arrayoffamiliestoexclude = array('objectamount'); @@ -1315,7 +1319,6 @@ elseif (empty($action) || $action == 'view' || $action == 'addlink' || $action = $help = ""; $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, $arrayoffamiliestoexclude, $object); if ($object->fk_soc > 0) { - $object->fetch_thirdparty(); $substitutionarray['__THIRDPARTY_NAME__'] = $object->thirdparty->name; } $substitutionarray['__USER_SIGNATURE__'] = $user->signature; From bdf876ead4d36c340c0249c150eecf5f3619d3cb Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 17 May 2021 05:38:46 +0000 Subject: [PATCH 06/23] Fixing style errors. --- htdocs/ticket/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 857365203f8..186a4461bd3 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -1300,7 +1300,7 @@ elseif (empty($action) || $action == 'view' || $action == 'addlink' || $action = if ($object->fk_soc > 0) { $object->fetch_thirdparty(); } - + $outputlangs = $langs; $newlang = ''; if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) { From d4162f3076a34a26dd9ad1d651d58a0083e00d19 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 May 2021 08:00:33 +0200 Subject: [PATCH 07/23] Update card.php --- htdocs/ticket/card.php | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 186a4461bd3..5ed28094e39 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -1317,7 +1317,7 @@ elseif (empty($action) || $action == 'view' || $action == 'addlink' || $action = // Substitution array $morehtmlright = ''; $help = ""; - $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, $arrayoffamiliestoexclude, $object); + $substitutionarray = getCommonSubstitutionArray($newlang, 0, $arrayoffamiliestoexclude, $object); if ($object->fk_soc > 0) { $substitutionarray['__THIRDPARTY_NAME__'] = $object->thirdparty->name; } @@ -1351,16 +1351,6 @@ elseif (empty($action) || $action == 'view' || $action == 'addlink' || $action = print '
'; - // Define output language - $outputlangs = $langs; - $newlang = ''; - if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($_REQUEST['lang_id'])) { - $newlang = $_REQUEST['lang_id']; - } - if ($conf->global->MAIN_MULTILANGS && empty($newlang)) { - $newlang = $object->default_lang; - } - $formticket = new FormTicket($db); $formticket->action = $action; From 7bb71dd89fa1e6552135e2f875cd00cfa174635e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 May 2021 09:25:18 +0200 Subject: [PATCH 08/23] FIX #17602 --- htdocs/admin/dict.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index f00d670d4a1..caa7a9fdc05 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -802,8 +802,8 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) if ($value == 'price' || preg_match('/^amount/i', $value)) { $_POST[$keycode] = price2num(GETPOST($keycode), 'MU'); } - elseif ($value == 'taux' || $value == 'localtax1' || $value == 'localtax2') { - $_POST[$keycode] = price2num(GETPOST($keycode), 8); + elseif ($value == 'taux' || $value == 'localtax1') { + $_POST[$keycode] = price2num(GETPOST($keycode), 8); // Note that localtax2 can be a list of rates separated by coma like X:Y:Z } elseif ($value == 'entity') { $_POST[$keycode] = getEntity($tabname[$id]); @@ -871,8 +871,8 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) if ($field == 'price' || preg_match('/^amount/i', $field)) { $_POST[$keycode] = price2num(GETPOST($keycode), 'MU'); } - elseif ($field == 'taux' || $field == 'localtax1' || $field == 'localtax2') { - $_POST[$keycode] = price2num(GETPOST($keycode), 8); + elseif ($field == 'taux' || $field == 'localtax1') { + $_POST[$keycode] = price2num(GETPOST($keycode), 8); // Note that localtax2 can be a list of rates separated by coma like X:Y:Z } elseif ($field == 'entity') { $_POST[$keycode] = getEntity($tabname[$id]); From 2f9a504dce7e44e16513a712cab815d58585ffb4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 May 2021 09:30:09 +0200 Subject: [PATCH 09/23] Fix label --- htdocs/admin/dict.php | 10 +++++----- htdocs/langs/en_US/main.lang | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index caa7a9fdc05..4bd556c5ac3 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -1076,7 +1076,7 @@ if ($id) $sql = $tabsql[$id]; if (!preg_match('/ WHERE /', $sql)) $sql .= " WHERE 1 = 1"; - if ($search_country_id > 0) $sql .= " AND c.rowid = ".$search_country_id; + if ($search_country_id > 0) $sql .= " AND c.rowid = ".((int) $search_country_id); if ($search_code != '' && $id == 9) $sql .= natural_search("code_iso", $search_code); elseif ($search_code != '' && $id == 28) $sql .= natural_search("h.code", $search_code); elseif ($search_code != '' && $id == 32) $sql .= natural_search("a.code", $search_code); @@ -1150,9 +1150,9 @@ if ($id) $class = 'center'; } if ($fieldlist[$field] == 'localtax1_type') { $valuetoshow = $langs->trans("UseLocalTax")." 2"; $class = "center"; $sortable = 0; } - if ($fieldlist[$field] == 'localtax1') { $valuetoshow = $langs->trans("Rate")." 2"; $class = "center"; } + if ($fieldlist[$field] == 'localtax1') { $valuetoshow = $langs->trans("RateOfTaxN", '2'); $class = "center"; } if ($fieldlist[$field] == 'localtax2_type') { $valuetoshow = $langs->trans("UseLocalTax")." 3"; $class = "center"; $sortable = 0; } - if ($fieldlist[$field] == 'localtax2') { $valuetoshow = $langs->trans("Rate")." 3"; $class = "center"; } + if ($fieldlist[$field] == 'localtax2') { $valuetoshow = $langs->trans("RateOfTaxN", '3'); $class = "center"; } if ($fieldlist[$field] == 'organization') { $valuetoshow = $langs->trans("Organization"); } if ($fieldlist[$field] == 'lang') { $valuetoshow = $langs->trans("Language"); } if ($fieldlist[$field] == 'type') { @@ -1380,9 +1380,9 @@ if ($id) $cssprefix = 'center '; } if ($fieldlist[$field] == 'localtax1_type') { $valuetoshow = $langs->trans("UseLocalTax")." 2"; $cssprefix = "center "; $sortable = 0; } - if ($fieldlist[$field] == 'localtax1') { $valuetoshow = $langs->trans("Rate")." 2"; $cssprefix = "center "; $sortable = 0; } + if ($fieldlist[$field] == 'localtax1') { $valuetoshow = $langs->trans("RateOfTaxN", '2'); $cssprefix = "center "; $sortable = 0; } if ($fieldlist[$field] == 'localtax2_type') { $valuetoshow = $langs->trans("UseLocalTax")." 3"; $cssprefix = "center "; $sortable = 0; } - if ($fieldlist[$field] == 'localtax2') { $valuetoshow = $langs->trans("Rate")." 3"; $cssprefix = "center "; $sortable = 0; } + if ($fieldlist[$field] == 'localtax2') { $valuetoshow = $langs->trans("RateOfTaxN", '3'); $cssprefix = "center "; $sortable = 0; } if ($fieldlist[$field] == 'organization') { $valuetoshow = $langs->trans("Organization"); } if ($fieldlist[$field] == 'lang') { $valuetoshow = $langs->trans("Language"); } if ($fieldlist[$field] == 'type') { $valuetoshow = $langs->trans("Type"); } diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 5594c835ba8..39517ca2e1b 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -427,6 +427,7 @@ LT1IN=CGST LT2IN=SGST LT1GC=Additionnal cents VATRate=Tax Rate +RateOfTaxN=Rate of tax %s VATCode=Tax Rate code VATNPR=Tax Rate NPR DefaultTaxRate=Default tax rate From f923c70f380d4145153b20bcbb8037caf7ea7a4c Mon Sep 17 00:00:00 2001 From: Ferran Marcet Date: Mon, 17 May 2021 10:17:54 +0200 Subject: [PATCH 10/23] Fix: Before there was no mistake --- htdocs/admin/dict.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index fbe7d924cbc..648537ec3f8 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -9,7 +9,7 @@ * Copyright (C) 2012-2015 Marcos García * Copyright (C) 2012 Christophe Battarel * Copyright (C) 2011-2016 Alexandre Spangaro - * Copyright (C) 2015-2021 Ferran Marcet + * Copyright (C) 2015 Ferran Marcet * Copyright (C) 2016 Raphaël Doursenaud * Copyright (C) 2019 Frédéric France * @@ -777,10 +777,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) elseif (in_array($keycode, array('joinfile', 'private', 'position', 'scale'))) { $sql .= (int) GETPOST($keycode, 'int'); } - elseif ($keycode == 'localtax2') { - $sql .= "'".GETPOST($keycode, 'alpha')."'"; - } - else { + else { $sql .= "'".$db->escape(GETPOST($keycode, 'nohtml'))."'"; } @@ -846,9 +843,6 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) elseif (in_array($keycode, array('private', 'position', 'scale'))) { $sql .= (int) GETPOST($keycode, 'int'); } - elseif ($keycode == 'localtax2') { - $sql .= "'".GETPOST($keycode, 'alpha')."'"; - } else { $sql .= "'".$db->escape(GETPOST($keycode, 'nohtml'))."'"; } From 547f1dd3703a625b72ee594b238c211a0a684297 Mon Sep 17 00:00:00 2001 From: Dorian Vabre Date: Mon, 17 May 2021 11:54:53 +0200 Subject: [PATCH 11/23] Fix: user rest api rights --- htdocs/user/class/api_users.class.php | 38 +++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/htdocs/user/class/api_users.class.php b/htdocs/user/class/api_users.class.php index fa139e2c69f..7c1eef84c2c 100644 --- a/htdocs/user/class/api_users.class.php +++ b/htdocs/user/class/api_users.class.php @@ -71,7 +71,7 @@ class Users extends DolibarrApi $obj_ret = array(); - if (!DolibarrApiAccess::$user->rights->user->user->lire) { + if (!DolibarrApiAccess::$user->rights->user->user->lire && !DolibarrApiAccess::$user->admin) { throw new RestException(401, "You are not allowed to read list of users"); } @@ -142,9 +142,9 @@ class Users extends DolibarrApi */ public function get($id, $includepermissions = 0) { - //if (!DolibarrApiAccess::$user->rights->user->user->lire) { - //throw new RestException(401); - //} + if (!DolibarrApiAccess::$user->rights->user->user->lire && !DolibarrApiAccess::$user->admin) { + throw new RestException(401); + } $result = $this->useraccount->fetch($id); if (!$result) @@ -208,9 +208,9 @@ class Users extends DolibarrApi public function post($request_data = null) { // check user authorization - //if(! DolibarrApiAccess::$user->rights->user->creer) { - // throw new RestException(401, "User creation not allowed"); - //} + if(! DolibarrApiAccess::$user->rights->user->creer && !DolibarrApiAccess::$user->admin) { + throw new RestException(401, "User creation not allowed"); + } // check mandatory fields /*if (!isset($request_data["login"])) throw new RestException(400, "login field missing"); @@ -242,9 +242,9 @@ class Users extends DolibarrApi */ public function put($id, $request_data = null) { - //if (!DolibarrApiAccess::$user->rights->user->user->creer) { - //throw new RestException(401); - //} + if (!DolibarrApiAccess::$user->rights->user->user->creer && !DolibarrApiAccess::$user->admin) { + throw new RestException(401); + } $result = $this->useraccount->fetch($id); if (!$result) @@ -299,7 +299,7 @@ class Users extends DolibarrApi { $obj_ret = array(); - if (!DolibarrApiAccess::$user->rights->user->user->lire) { + if (!DolibarrApiAccess::$user->rights->user->user->lire && !DolibarrApiAccess::$user->admin) { throw new RestException(401); } @@ -334,9 +334,9 @@ class Users extends DolibarrApi global $conf; - //if (!DolibarrApiAccess::$user->rights->user->user->supprimer) { - //throw new RestException(401); - //} + if (!DolibarrApiAccess::$user->rights->user->user->supprimer && !DolibarrApiAccess::$user->admin) { + throw new RestException(401); + } $result = $this->useraccount->fetch($id); if (!$result) { @@ -389,7 +389,7 @@ class Users extends DolibarrApi $obj_ret = array(); - if (!DolibarrApiAccess::$user->rights->user->group_advance->read) { + if (!DolibarrApiAccess::$user->rights->user->group_advance->read && !DolibarrApiAccess::$user->admin) { throw new RestException(401, "You are not allowed to read list of groups"); } @@ -463,7 +463,7 @@ class Users extends DolibarrApi { global $db, $conf; - if (!DolibarrApiAccess::$user->rights->user->group_advance->read) { + if (!DolibarrApiAccess::$user->rights->user->group_advance->read && !DolibarrApiAccess::$user->admin) { throw new RestException(401, "You are not allowed to read groups"); } @@ -486,9 +486,9 @@ class Users extends DolibarrApi */ public function delete($id) { - //if (!DolibarrApiAccess::$user->rights->user->user->supprimer) { - //throw new RestException(401); - //} + if (!DolibarrApiAccess::$user->rights->user->user->supprimer && !DolibarrApiAccess::$user->admin) { + throw new RestException(401); + } $result = $this->useraccount->fetch($id); if (!$result) { From a3aba28c95fd41c3db3b390f642b6fd05e873105 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 17 May 2021 10:06:41 +0000 Subject: [PATCH 12/23] Fixing style errors. --- htdocs/user/class/api_users.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/user/class/api_users.class.php b/htdocs/user/class/api_users.class.php index 7c1eef84c2c..39f3b302599 100644 --- a/htdocs/user/class/api_users.class.php +++ b/htdocs/user/class/api_users.class.php @@ -209,7 +209,7 @@ class Users extends DolibarrApi { // check user authorization if(! DolibarrApiAccess::$user->rights->user->creer && !DolibarrApiAccess::$user->admin) { - throw new RestException(401, "User creation not allowed"); + throw new RestException(401, "User creation not allowed"); } // check mandatory fields /*if (!isset($request_data["login"])) From c54e010126fb1cc297f644f5bf045a26a0c0b09c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 May 2021 16:16:45 +0200 Subject: [PATCH 13/23] Fix perms on API user --- htdocs/user/class/api_users.class.php | 30 ++++++++++++++++----------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/htdocs/user/class/api_users.class.php b/htdocs/user/class/api_users.class.php index 39f3b302599..9f5ea935372 100644 --- a/htdocs/user/class/api_users.class.php +++ b/htdocs/user/class/api_users.class.php @@ -71,7 +71,7 @@ class Users extends DolibarrApi $obj_ret = array(); - if (!DolibarrApiAccess::$user->rights->user->user->lire && !DolibarrApiAccess::$user->admin) { + if (!DolibarrApiAccess::$user->rights->user->user->lire && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, "You are not allowed to read list of users"); } @@ -142,7 +142,7 @@ class Users extends DolibarrApi */ public function get($id, $includepermissions = 0) { - if (!DolibarrApiAccess::$user->rights->user->user->lire && !DolibarrApiAccess::$user->admin) { + if (!DolibarrApiAccess::$user->rights->user->user->lire && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401); } @@ -177,7 +177,11 @@ class Users extends DolibarrApi */ public function getInfo() { - $apiUser = DolibarrApiAccess::$user; + if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) { + throw new RestException(401, 'Not allowed'); + } + + $apiUser = DolibarrApiAccess::$user; $result = $this->useraccount->fetch($apiUser->id); if (!$result) { @@ -208,7 +212,7 @@ class Users extends DolibarrApi public function post($request_data = null) { // check user authorization - if(! DolibarrApiAccess::$user->rights->user->creer && !DolibarrApiAccess::$user->admin) { + if (empty(DolibarrApiAccess::$user->rights->user->creer) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, "User creation not allowed"); } // check mandatory fields @@ -242,7 +246,7 @@ class Users extends DolibarrApi */ public function put($id, $request_data = null) { - if (!DolibarrApiAccess::$user->rights->user->user->creer && !DolibarrApiAccess::$user->admin) { + if (empty(DolibarrApiAccess::$user->rights->user->user->creer) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401); } @@ -299,7 +303,7 @@ class Users extends DolibarrApi { $obj_ret = array(); - if (!DolibarrApiAccess::$user->rights->user->user->lire && !DolibarrApiAccess::$user->admin) { + if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401); } @@ -334,7 +338,7 @@ class Users extends DolibarrApi global $conf; - if (!DolibarrApiAccess::$user->rights->user->user->supprimer && !DolibarrApiAccess::$user->admin) { + if (empty(DolibarrApiAccess::$user->rights->user->user->creer) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401); } $result = $this->useraccount->fetch($id); @@ -389,9 +393,10 @@ class Users extends DolibarrApi $obj_ret = array(); - if (!DolibarrApiAccess::$user->rights->user->group_advance->read && !DolibarrApiAccess::$user->admin) { - throw new RestException(401, "You are not allowed to read list of groups"); - } + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) || + !empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->group_advance->read) && empty(DolibarrApiAccess::$user->admin)) { + throw new RestException(401, "You are not allowed to read groups"); + } // case of external user, $societe param is ignored and replaced by user's socid //$socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $societe; @@ -463,7 +468,8 @@ class Users extends DolibarrApi { global $db, $conf; - if (!DolibarrApiAccess::$user->rights->user->group_advance->read && !DolibarrApiAccess::$user->admin) { + if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) || + !empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty(DolibarrApiAccess::$user->rights->user->group_advance->read) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, "You are not allowed to read groups"); } @@ -486,7 +492,7 @@ class Users extends DolibarrApi */ public function delete($id) { - if (!DolibarrApiAccess::$user->rights->user->user->supprimer && !DolibarrApiAccess::$user->admin) { + if (empty(DolibarrApiAccess::$user->rights->user->user->supprimer) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401); } $result = $this->useraccount->fetch($id); From a865f49d72049f7ffbb949da11386ab151fdfd16 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 May 2021 19:19:26 +0200 Subject: [PATCH 14/23] Fix phpcs --- htdocs/user/class/api_users.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/user/class/api_users.class.php b/htdocs/user/class/api_users.class.php index 9f5ea935372..75aedba09bd 100644 --- a/htdocs/user/class/api_users.class.php +++ b/htdocs/user/class/api_users.class.php @@ -180,7 +180,7 @@ class Users extends DolibarrApi if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) { throw new RestException(401, 'Not allowed'); } - + $apiUser = DolibarrApiAccess::$user; $result = $this->useraccount->fetch($apiUser->id); From 4236471a6f0efd9d8269837ddcdb494aeed05ee1 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Mon, 17 May 2021 22:12:01 +0200 Subject: [PATCH 15/23] Fix Title salary card --- htdocs/salaries/card.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/salaries/card.php b/htdocs/salaries/card.php index 8e2188123db..aff3e4cce92 100755 --- a/htdocs/salaries/card.php +++ b/htdocs/salaries/card.php @@ -359,7 +359,9 @@ if ($action == 'confirm_clone' && $confirm == 'yes' && ($user->rights->salaries- * View */ -llxHeader("", $langs->trans("Salary")); +$title = $langs->trans('Salary')." - ".$langs->trans('Card'); +$help_url = ""; +llxHeader("", $title, $help_url); $form = new Form($db); if (!empty($conf->projet->enabled)) $formproject = new FormProjets($db); From c3c760c26915af4ef39671fb0af23c31d1172901 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Mon, 17 May 2021 22:18:46 +0200 Subject: [PATCH 16/23] Fix Title salary document card --- htdocs/salaries/document.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/salaries/document.php b/htdocs/salaries/document.php index 4c88cefb8de..5950fc88798 100644 --- a/htdocs/salaries/document.php +++ b/htdocs/salaries/document.php @@ -91,7 +91,9 @@ include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; $form = new Form($db); -llxHeader("", $langs->trans("SalaryPayment")); +$title = $langs->trans('Salary')." - ".$langs->trans('Documents'); +$help_url = ""; +llxHeader("", $title, $help_url); if ($object->id) { $object->fetch_thirdparty(); From 91b8b6a6003ac730612abb607fc9a0c8b53ccb89 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Mon, 17 May 2021 22:41:00 +0200 Subject: [PATCH 17/23] Fix Title salary info card --- htdocs/salaries/info.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/salaries/info.php b/htdocs/salaries/info.php index 1b81a80189f..0f94f405fa1 100644 --- a/htdocs/salaries/info.php +++ b/htdocs/salaries/info.php @@ -53,7 +53,9 @@ restrictedArea($user, 'salaries', $object->id, 'salary', ''); * View */ -llxHeader("", $langs->trans("SalaryPayment")); +$title = $langs->trans('Salary')." - ".$langs->trans('Info'); +$help_url = ""; +llxHeader("", $title, $help_url); $object = new Salary($db); $object->fetch($id); From 58db723502a58d054ffd45749ab151551026890d Mon Sep 17 00:00:00 2001 From: Anthony Berton <34568357+bb2a@users.noreply.github.com> Date: Mon, 17 May 2021 23:27:33 +0200 Subject: [PATCH 18/23] thirdparty info popup list --- htdocs/comm/propal/list.php | 9 +++++++- htdocs/commande/list.php | 11 ++++++++-- htdocs/compta/facture/list.php | 40 +++++++++++++++++++--------------- htdocs/projet/list.php | 38 ++++++++++++++++++++------------ 4 files changed, 64 insertions(+), 34 deletions(-) diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index e1ec555837f..c8173967770 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -460,9 +460,10 @@ $sql = 'SELECT'; if ($sall || $search_product_category > 0 || $search_user > 0) { $sql = 'SELECT DISTINCT'; } -$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.code_client, '; +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.phone, s.fax , s.address, s.town, s.zip, s.fk_pays, s.client, s.code_client, '; $sql .= " typent.code as typent_code,"; $sql .= " ava.rowid as availability,"; +$sql .= " country.code as country_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= ' p.rowid, p.entity, p.note_private, p.total_ht, p.total_tva, p.total_ttc, p.localtax1, p.localtax2, p.ref, p.ref_client, p.fk_statut as status, p.fk_user_author, p.datep as dp, p.fin_validite as dfv,p.date_livraison as ddelivery,'; $sql .= ' p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc,'; @@ -1335,9 +1336,15 @@ if ($resql) { $companystatic->id = $obj->socid; $companystatic->name = $obj->name; + $companystatic->name_alias = $obj->alias; $companystatic->client = $obj->client; $companystatic->code_client = $obj->code_client; $companystatic->email = $obj->email; + $companystatic->phone = $obj->phone; + $companystatic->address = $obj->address; + $companystatic->zip = $obj->zip; + $companystatic->town = $obj->town; + $companystatic->country_code = $obj->country_code; $projectstatic->id = $obj->project_id; $projectstatic->ref = $obj->project_ref; diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 5bb8e6ccb0c..81b15623adf 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -417,9 +417,10 @@ $sql = 'SELECT'; if ($sall || $search_product_category > 0 || $search_user > 0) { $sql = 'SELECT DISTINCT'; } -$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as name_alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.code_client,'; +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.phone, s.fax, s.address, s.town, s.zip, s.fk_pays, s.client, s.code_client,'; $sql .= " typent.code as typent_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; +$sql .= " country.code as country_code,"; $sql .= ' c.rowid, c.ref, c.total_ht, c.total_tva, c.total_ttc, c.ref_client, c.fk_user_author,'; $sql .= ' c.fk_multicurrency, c.multicurrency_code, c.multicurrency_tx, c.multicurrency_total_ht, c.multicurrency_total_tva as multicurrency_total_vat, c.multicurrency_total_ttc,'; $sql .= ' c.date_valid, c.date_commande, c.note_public, c.note_private, c.date_livraison as date_delivery, c.fk_statut, c.facture as billed,'; @@ -1383,10 +1384,16 @@ if ($resql) { $nbprod = 0; $companystatic->id = $obj->socid; - $companystatic->code_client = $obj->code_client; $companystatic->name = $obj->name; + $companystatic->name_alias = $obj->alias; $companystatic->client = $obj->client; + $companystatic->code_client = $obj->code_client; $companystatic->email = $obj->email; + $companystatic->phone = $obj->phone; + $companystatic->address = $obj->address; + $companystatic->zip = $obj->zip; + $companystatic->town = $obj->town; + $companystatic->country_code = $obj->country_code; if (!isset($getNomUrl_cache[$obj->socid])) { $getNomUrl_cache[$obj->socid] = $companystatic->getNomUrl(1, 'customer'); } diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 1ac8765171d..2a474d00fae 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -467,7 +467,7 @@ if (!empty($conf->margin->enabled)) { $bankaccountstatic = new Account($db); $facturestatic = new Facture($db); $formcompany = new FormCompany($db); -$thirdpartystatic = new Societe($db); +$companystatic = new Societe($db); $sql = 'SELECT'; if ($sall || $search_product_category > 0 || $search_user > 0) { @@ -481,7 +481,7 @@ $sql .= ' f.datef, f.date_valid, f.date_lim_reglement as datelimite, f.module_so $sql .= ' f.paye as paye, f.fk_statut, f.close_code,'; $sql .= ' f.datec as date_creation, f.tms as date_update, f.date_closing as date_closing,'; $sql .= ' f.retained_warranty, f.retained_warranty_date_limit, f.situation_final, f.situation_cycle_ref, f.situation_counter,'; -$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as name_alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,'; +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.phone, s.fax, s.address, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,'; $sql .= " typent.code as typent_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= " country.code as country_code,"; @@ -714,7 +714,7 @@ if (!$sall) { $sql .= ' f.retained_warranty, f.retained_warranty_date_limit, f.situation_final, f.situation_cycle_ref, f.situation_counter,'; $sql .= ' f.fk_user_author, f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva,'; $sql .= ' f.multicurrency_total_tva, f.multicurrency_total_ttc,'; - $sql .= ' s.rowid, s.nom, s.name_alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,'; + $sql .= ' s.rowid, s.nom, s.name_alias, s.email, s.phone, s.fax, s.address, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,'; $sql .= ' typent.code,'; $sql .= ' state.code_departement, state.nom,'; $sql .= ' country.code,'; @@ -1539,16 +1539,22 @@ if ($resql) { $facturestatic->situation_cycle_ref = $obj->situation_cycle_ref; $facturestatic->situation_counter = $obj->situation_counter; } - $thirdpartystatic->id = $obj->socid; - $thirdpartystatic->name = $obj->name; - $thirdpartystatic->client = $obj->client; - $thirdpartystatic->fournisseur = $obj->fournisseur; - $thirdpartystatic->code_client = $obj->code_client; - $thirdpartystatic->code_compta_client = $obj->code_compta_client; - $thirdpartystatic->code_fournisseur = $obj->code_fournisseur; - $thirdpartystatic->code_compta_fournisseur = $obj->code_compta_fournisseur; - $thirdpartystatic->email = $obj->email; - $thirdpartystatic->country_code = $obj->country_code; + $companystatic->id = $obj->socid; + $companystatic->name = $obj->name; + $companystatic->name_alias = $obj->alias; + $companystatic->client = $obj->client; + $companystatic->fournisseur = $obj->fournisseur; + $companystatic->code_client = $obj->code_client; + $companystatic->code_compta_client = $obj->code_compta_client; + $companystatic->code_fournisseur = $obj->code_fournisseur; + $companystatic->code_compta_fournisseur = $obj->code_compta_fournisseur; + $companystatic->email = $obj->email; + $companystatic->phone = $obj->phone; + $companystatic->fax = $obj->fax; + $companystatic->address = $obj->address; + $companystatic->zip = $obj->zip; + $companystatic->town = $obj->town; + $companystatic->country_code = $obj->country_code; $projectstatic->id = $obj->project_id; $projectstatic->ref = $obj->project_ref; @@ -1570,10 +1576,10 @@ if ($resql) { $multicurrency_remaintopay = 0; } if ($facturestatic->type == Facture::TYPE_CREDIT_NOTE && $obj->paye == 1) { // If credit note closed, we take into account the amount not yet consummed - $remaincreditnote = $discount->getAvailableDiscounts($thirdpartystatic, '', 'rc.fk_facture_source='.$facturestatic->id); + $remaincreditnote = $discount->getAvailableDiscounts($companystatic, '', 'rc.fk_facture_source='.$facturestatic->id); $remaintopay = -$remaincreditnote; $totalpay = price2num($facturestatic->total_ttc - $remaintopay); - $multicurrency_remaincreditnote = $discount->getAvailableDiscounts($thirdpartystatic, '', 'rc.fk_facture_source='.$facturestatic->id, 0, 0, 1); + $multicurrency_remaincreditnote = $discount->getAvailableDiscounts($companystatic, '', 'rc.fk_facture_source='.$facturestatic->id, 0, 0, 1); $multicurrency_remaintopay = -$multicurrency_remaincreditnote; $multicurrency_totalpay = price2num($facturestatic->multicurrency_total_ttc - $multicurrency_remaintopay); } @@ -1704,9 +1710,9 @@ if ($resql) { if (!empty($arrayfields['s.nom']['checked'])) { print ''; if ($contextpage == 'poslist') { - print $thirdpartystatic->name; + print $companystatic->name; } else { - print $thirdpartystatic->getNomUrl(1, 'customer'); + print $companystatic->getNomUrl(1, 'customer'); } print ''; if (!$i) { diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index a9f17f5439b..7edc94a0a8c 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -297,7 +297,7 @@ if (empty($reshook)) { * View */ -$socstatic = new Societe($db); +$companystatic = new Societe($db); $form = new Form($db); $formother = new FormOther($db); $formproject = new FormProjets($db); @@ -330,12 +330,13 @@ if (count($listofprojectcontacttype) == 0) { } $distinct = 'DISTINCT'; // We add distinct until we are added a protection to be sure a contact of a project and task is only once. -$sql = "SELECT ".$distinct." p.rowid as id, p.ref, p.title, p.fk_statut as status, p.fk_opp_status, p.public, p.fk_user_creat"; -$sql .= ", p.datec as date_creation, p.dateo as date_start, p.datee as date_end, p.opp_amount, p.opp_percent, (p.opp_amount*p.opp_percent/100) as opp_weighted_amount, p.tms as date_update, p.budget_amount "; -$sql .= ", p.usage_opportunity, p.usage_task, p.usage_bill_time, p.usage_organize_event"; -$sql .= ", accept_conference_suggestions, accept_booth_suggestions, price_registration, price_booth"; -$sql .= ", s.rowid as socid, s.nom as name, s.email"; -$sql .= ", cls.code as opp_status_code"; +$sql = "SELECT ".$distinct." p.rowid as id, p.ref, p.title, p.fk_statut as status, p.fk_opp_status, p.public, p.fk_user_creat,"; +$sql .= " p.datec as date_creation, p.dateo as date_start, p.datee as date_end, p.opp_amount, p.opp_percent, (p.opp_amount*p.opp_percent/100) as opp_weighted_amount, p.tms as date_update, p.budget_amount,"; +$sql .= " p.usage_opportunity, p.usage_task, p.usage_bill_time, p.usage_organize_event,"; +$sql .= " accept_conference_suggestions, accept_booth_suggestions, price_registration, price_booth,"; +$sql .= " s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.email, s.phone, s.fax, s.address, s.town, s.zip, s.fk_pays, s.client, s.code_client,"; +$sql .= " country.code as country_code,"; +$sql .= " cls.code as opp_status_code"; // Add fields from extrafields if (!empty($extrafields->attributes[$object->table_element]['label'])) { foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { @@ -355,6 +356,7 @@ if (is_array($extrafields->attributes[$object->table_element]['label']) && count $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (p.rowid = ef.fk_object)"; } $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid"; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as country on (country.rowid = s.fk_pays)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_lead_status as cls on p.fk_opp_status = cls.rowid"; // We'll need this table joined to the select in order to filter by sale // No check is done on company permission because readability is managed by public status of project and assignement. @@ -978,9 +980,17 @@ while ($i < min($num, $limit)) { $userAccess = $object->restrictedProjectArea($user); // why this ? if ($userAccess >= 0) { - $socstatic->id = $obj->socid; - $socstatic->name = $obj->name; - $socstatic->email = $obj->email; + $companystatic->id = $obj->socid; + $companystatic->name = $obj->name; + $companystatic->name_alias = $obj->alias; + $companystatic->client = $obj->client; + $companystatic->code_client = $obj->code_client; + $companystatic->email = $obj->email; + $companystatic->phone = $obj->phone; + $companystatic->address = $obj->address; + $companystatic->zip = $obj->zip; + $companystatic->town = $obj->town; + $companystatic->country_code = $obj->country_code; print ''; @@ -1009,7 +1019,7 @@ while ($i < min($num, $limit)) { if (!empty($arrayfields['s.nom']['checked'])) { print ''; if ($obj->socid) { - print $socstatic->getNomUrl(1); + print $companystatic->getNomUrl(1); } else { print ' '; } @@ -1022,9 +1032,9 @@ while ($i < min($num, $limit)) { if (!empty($arrayfields['commercial']['checked'])) { print ''; if ($obj->socid) { - $socstatic->id = $obj->socid; - $socstatic->name = $obj->name; - $listsalesrepresentatives = $socstatic->getSalesRepresentatives($user); + $companystatic->id = $obj->socid; + $companystatic->name = $obj->name; + $listsalesrepresentatives = $companystatic->getSalesRepresentatives($user); $nbofsalesrepresentative = count($listsalesrepresentatives); if ($nbofsalesrepresentative > 6) { // We print only number From ba0e95a4ff6ffa6b085628d1477c838e480597b5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 May 2021 23:47:16 +0200 Subject: [PATCH 19/23] FIX huntr CWE-79 --- htdocs/core/lib/functions.lib.php | 22 ++++++---- htdocs/main.inc.php | 29 ++++++++++++- test/phpunit/SecurityTest.php | 68 +++++++++++++++++++++---------- 3 files changed, 86 insertions(+), 33 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 8251c850ddf..a987cf03e4c 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -634,17 +634,17 @@ function GETPOST($paramname, $check = 'alphanohtml', $method = 0, $filter = null $out = checkVal($out, $check, $filter, $options); } - // Sanitizing for special parameters. There is no reason to allow the backtopage, backtolist or backtourl parameter to contains an external URL. + // Sanitizing for special parameters. + // Note: There is no reason to allow the backtopage, backtolist or backtourl parameter to contains an external URL. if ($paramname == 'backtopage' || $paramname == 'backtolist' || $paramname == 'backtourl') { - $out = str_replace('\\', '/', $out); - $out = str_replace(array(':', ';', '@'), '', $out); - + $out = str_replace('\\', '/', $out); // Can be before the loop because only 1 char is replaced. No risk to get it after other replacements. + $out = str_replace(array(':', ';', '@'), '', $out); // Can be before the loop because only 1 char is replaced. No risk to get it after other replacements. do { $oldstringtoclean = $out; $out = str_ireplace(array('javascript', 'vbscript', '&colon', '&#'), '', $out); } while ($oldstringtoclean != $out); - $out = preg_replace(array('/^[a-z]*\/\/+/i'), '', $out); + $out = preg_replace(array('/^[a-z]*\/\/+/i'), '', $out); // We remove schema*// to remove external URL } // Code for search criteria persistence. @@ -684,7 +684,7 @@ function GETPOSTINT($paramname, $method = 0, $filter = null, $options = null, $n } /** - * Return a value after checking on a rule. + * Return a value after checking on a rule. A sanitization may also have been done. * * @param string $out Value to check/clear. * @param string $check Type of check/sanitizing @@ -777,6 +777,11 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = case 'restricthtml': // Recommended for most html textarea do { $oldstringtoclean = $out; + + // We replace chars encoded with numeric HTML entities with real char (to avoid to have numeric entities used for obfuscation of injections) + $out = preg_replace_callback('/&#(x?[0-9][0-9a-f]+);/i', 'realCharForNumericEntities', $out); + $out = preg_replace('/&#x?[0-9]+/i', '', $out); // For example if we have javascript with an entities without the ; to hide the 'a' of 'javascript'. + $out = dol_string_onlythesehtmltags($out, 0, 1, 1); // We should also exclude non expected attributes @@ -797,7 +802,6 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = } - if (!function_exists('dol_getprefix')) { /** * Return a prefix to use for this Dolibarr instance, for session/cookie names or email id. @@ -9738,8 +9742,8 @@ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = /** * Add space between dolGetButtonTitle * - * @param string $moreClass more css class label - * @return string html of title separator + * @param string $moreClass more css class label + * @return string html of title separator */ function dolGetButtonTitleSeparator($moreClass = "") { diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index c9a7dd21ccc..7b40647ebcb 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -50,9 +50,33 @@ if (!empty($_SERVER['MAIN_SHOW_TUNING_INFO'])) { } } + +/** + * Return the real char for a numeric entities. + * This function is required by testSqlAndScriptInject(). + * + * @param string $matches String of numeric entity + * @return string New value + */ +function realCharForNumericEntities($matches) +{ + $newstringnumentity = $matches[1]; + + if (preg_match('/^x/i', $newstringnumentity)) { + $newstringnumentity = hexdec(preg_replace('/^x/i', '', $newstringnumentity)); + } + + // The numeric value we don't want as entities + if (($newstringnumentity >= 65 && $newstringnumentity <= 90) || ($newstringnumentity >= 97 && $newstringnumentity <= 122)) { + return chr((int) $newstringnumentity); + } + + return '&#'.$matches[1]; +} + /** * Security: WAF layer for SQL Injection and XSS Injection (scripts) protection (Filters on GET, POST, PHP_SELF). - * Warning: Such a protection can't be enough. It is not reliable as it will alwyas be possible to bypass this. Good protection can + * Warning: Such a protection can't be enough. It is not reliable as it will always be possible to bypass this. Good protection can * only be guaranted by escaping data during output. * * @param string $val Value brut found int $_GET, $_POST or PHP_SELF @@ -61,7 +85,7 @@ if (!empty($_SERVER['MAIN_SHOW_TUNING_INFO'])) { */ function testSqlAndScriptInject($val, $type) { - // Decode string first bcause a lot of things are obfuscated by encoding or multiple encoding. + // Decode string first because a lot of things are obfuscated by encoding or multiple encoding. // So assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject expected 0b'); - // Should detect XSS + + // Should detect attack $expectedresult=1; $_SERVER["PHP_SELF"]='/DIR WITH SPACE/htdocs/admin/index.php/'; $result=testSqlAndScriptInject($_SERVER["PHP_SELF"], 2); $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject for PHP_SELF that should detect XSS'); + $test = 'javascript:'; + $result=testSqlAndScriptInject($test, 0); + $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject for javascript1. Should find an attack and did not.'); + + $test = 'javascript:'; + $result=testSqlAndScriptInject($test, 0); + $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject for javascript2. Should find an attack and did not.'); + $test = 'javascript&colon;alert(1)'; $result=testSqlAndScriptInject($test, 0); - $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject expected 1a'); + $this->assertEquals($expectedresult, $result, 'Error on testSqlAndScriptInject for javascript2'); $test=""; $result=testSqlAndScriptInject($test, 0); - $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject aaa'); + $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject aaa1'); $test=""; $result=testSqlAndScriptInject($test, 2); @@ -328,9 +337,12 @@ class SecurityTest extends PHPUnit\Framework\TestCase $_POST["param10"]='is_object($object) ? ($object->id < 10 ? round($object->id / 2, 2) : (2 * $user->id) * (int) substr($mysoc->zip, 1, 2)) : \'objnotdefined\''; $_POST["param11"]=' Name '; $_POST["param12"]='aaa'; + $_POST["param13"]='n n > < " XSS'; + $_POST["param13b"]='n n > < " XSS'; //$_POST["param13"]='javascript%26colon%26%23x3B%3Balert(1)'; //$_POST["param14"]='javascripT&javascript#x3a alert(1)'; + $result=GETPOST('id', 'int'); // Must return nothing print __METHOD__." result=".$result."\n"; $this->assertEquals($result, ''); @@ -343,7 +355,7 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals($result, 333, 'Test on param1 with 3rd param = 2'); - // Test alpha + // Test with alpha $result=GETPOST("param2", 'alpha'); print __METHOD__." result=".$result."\n"; @@ -357,7 +369,7 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals($result, 'dir'); - // Test aZ09 + // Test with aZ09 $result=GETPOST("param1", 'aZ09'); print __METHOD__." result=".$result."\n"; @@ -379,25 +391,22 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals($_GET["param5"], $result); - $result=GETPOST("param6", 'alpha'); - print __METHOD__." result=".$result."\n"; - $this->assertEquals('>', $result); + // Test with nohtml $result=GETPOST("param6", 'nohtml'); print __METHOD__." result=".$result."\n"; $this->assertEquals('">', $result); - $result=GETPOST("param6b"); + // Test with alpha = alphanohtml. We must convert the html entities like n and disable all entities + + $result=GETPOST("param6", 'alphanohtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('>', $result); + + $result=GETPOST("param6b", 'alphanohtml'); print __METHOD__." result=".$result."\n"; $this->assertEquals('abc', $result); - // With restricthtml we must remove html open/close tag and content but not htmlentities like n - - $result=GETPOST("param7", 'restricthtml'); - print __METHOD__." result=".$result."\n"; - $this->assertEquals('"c:\this is a path~1\aaan" abcdef', $result); - - // With alphanohtml, we must convert the html entities like n and disable all entities $result=GETPOST("param8a", 'alphanohtml'); print __METHOD__." result=".$result."\n"; $this->assertEquals("Hackersvg onload='console.log(123)'", $result); @@ -434,24 +443,39 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals("Name", $result, 'Test an email string with alphanohtml'); + $result=GETPOST("param13", 'alphanohtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('n n > < XSS', $result, 'Test that html entities are decoded with alpha'); + + // Test with alphawithlgt + $result=GETPOST("param11", 'alphawithlgt'); print __METHOD__." result=".$result."\n"; $this->assertEquals(trim($_POST["param11"]), $result, 'Test an email string with alphawithlgt'); + // Test with restricthtml we must remove html open/close tag and content but not htmlentities (we can decode html entities for ascii chars like n) + + $result=GETPOST("param6", 'restricthtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('">', $result); + + $result=GETPOST("param7", 'restricthtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('"c:\this is a path~1\aaan" abcdef', $result); + $result=GETPOST("param12", 'restricthtml'); print __METHOD__." result=".$result."\n"; $this->assertEquals(trim($_POST["param12"]), $result, 'Test a string with DOCTYPE and restricthtml'); - /*$result=GETPOST("param13", 'alphanohtml'); + $result=GETPOST("param13", 'restricthtml'); print __METHOD__." result=".$result."\n"; - $this->assertEquals(trim($_POST["param13"]), $result, 'Test a string and alphanohtml'); + $this->assertEquals('n n > < " XSS', $result, 'Test that HTML entities are decoded with restricthtml, but only for common alpha chars'); - $result=GETPOST("param14", 'alphanohtml'); + $result=GETPOST("param13b", 'restricthtml'); print __METHOD__." result=".$result."\n"; - $this->assertEquals(trim($_POST["param14"]), $result, 'Test a string and alphanohtml'); - */ + $this->assertEquals('n n > < " XSS', $result, 'Test that HTML entities are decoded with restricthtml, but only for common alpha chars'); - // Special test for GETPOST of backtopage or backtolist parameter + // Special test for GETPOST of backtopage, backtolist or backtourl parameter $_POST["backtopage"]='//www.google.com'; $result=GETPOST("backtopage"); From b6dbe45242a1b1e9303b6103bf68e53535b85ad5 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 18 May 2021 01:58:54 +0200 Subject: [PATCH 20/23] Fix permissions on page to move position of file --- htdocs/adherents/document.php | 2 ++ htdocs/asset/document.php | 14 ++++++----- htdocs/bom/bom_document.php | 2 ++ htdocs/comm/action/document.php | 2 ++ htdocs/comm/propal/document.php | 2 ++ htdocs/commande/document.php | 14 ++++++----- htdocs/compta/facture/document.php | 2 ++ htdocs/core/actions_linkedfiles.inc.php | 11 +++++---- htdocs/core/ajax/row.php | 24 +++++++++++++------ htdocs/core/lib/security.lib.php | 2 +- .../template/myobject_document.php | 2 +- htdocs/product/document.php | 4 ++-- htdocs/projet/document.php | 10 ++++---- htdocs/societe/document.php | 1 + htdocs/ticket/agenda.php | 5 +--- htdocs/ticket/card.php | 4 ++-- htdocs/ticket/contact.php | 23 ++++++++++++++---- htdocs/ticket/document.php | 20 ++++++++++++---- htdocs/ticket/messaging.php | 9 +++---- 19 files changed, 98 insertions(+), 55 deletions(-) diff --git a/htdocs/adherents/document.php b/htdocs/adherents/document.php index 5150bea861e..f2a7c6f3f55 100644 --- a/htdocs/adherents/document.php +++ b/htdocs/adherents/document.php @@ -93,6 +93,8 @@ if ($id) { $caneditfieldmember = $user->rights->adherent->creer; } +$permissiontoadd = $canaddmember; + // Security check $result = restrictedArea($user, 'adherent', $object->id, '', '', 'socid', 'rowid', 0); diff --git a/htdocs/asset/document.php b/htdocs/asset/document.php index e6f5ed9b353..91e46269994 100644 --- a/htdocs/asset/document.php +++ b/htdocs/asset/document.php @@ -40,12 +40,6 @@ $socid = GETPOST('socid', 'int'); $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); -// Security check -if ($user->socid) { - $socid = $user->socid; -} -$result=restrictedArea($user, 'asset', $id, ''); - // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST("sortfield", 'alpha'); @@ -69,6 +63,14 @@ if ($object->fetch($id)) { $upload_dir = $conf->asset->dir_output."/".dol_sanitizeFileName($object->ref); } +$permissiontoadd = $user->rights->asset->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php + +// Security check +if ($user->socid) { + $socid = $user->socid; +} +$result=restrictedArea($user, 'asset', $id, ''); + /* * Actions diff --git a/htdocs/bom/bom_document.php b/htdocs/bom/bom_document.php index c0196670cfb..e59b22c45b2 100644 --- a/htdocs/bom/bom_document.php +++ b/htdocs/bom/bom_document.php @@ -85,6 +85,8 @@ if ($id > 0 || !empty($ref)) { $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft); +$permissiontoadd = $user->rights->bom->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php + /* * Actions diff --git a/htdocs/comm/action/document.php b/htdocs/comm/action/document.php index f521fa2ab59..c55d4e114cc 100644 --- a/htdocs/comm/action/document.php +++ b/htdocs/comm/action/document.php @@ -88,6 +88,8 @@ if ($user->socid && $socid) { $result = restrictedArea($user, 'societe', $socid); } +$permissiontoadd = $user->rights->agenda->myactions->read; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php + /* * Actions diff --git a/htdocs/comm/propal/document.php b/htdocs/comm/propal/document.php index 4e592c8371e..2b21c545c63 100644 --- a/htdocs/comm/propal/document.php +++ b/htdocs/comm/propal/document.php @@ -80,6 +80,8 @@ if (!$sortfield) { $object = new Propal($db); $object->fetch($id, $ref); +$permissiontoadd = $user->rights->propale->creer; + // Security check if (!empty($user->socid)) { $socid = $user->socid; diff --git a/htdocs/commande/document.php b/htdocs/commande/document.php index b4dddc9a1bf..c289112ee9f 100644 --- a/htdocs/commande/document.php +++ b/htdocs/commande/document.php @@ -44,12 +44,6 @@ $confirm = GETPOST('confirm'); $id = GETPOST('id', 'int'); $ref = GETPOST('ref'); -// Security check -if ($user->socid) { - $socid = $user->socid; -} -$result = restrictedArea($user, 'commande', $id, ''); - // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST("sortfield", 'alpha'); @@ -78,6 +72,14 @@ if (!$sortfield) { $object = new Commande($db); +$permissiontoadd = $user->rights->commande->creer; + +// Security check +if ($user->socid) { + $socid = $user->socid; +} +$result = restrictedArea($user, 'commande', $id, ''); + /* * Actions diff --git a/htdocs/compta/facture/document.php b/htdocs/compta/facture/document.php index 664b84d4444..16cdee4ac53 100644 --- a/htdocs/compta/facture/document.php +++ b/htdocs/compta/facture/document.php @@ -72,6 +72,8 @@ if ($object->fetch($id, $ref)) { $upload_dir = $conf->facture->dir_output."/".dol_sanitizeFileName($object->ref); } +$permissiontoadd = $user->rights->facture->creer; + // Security check if ($user->socid) { $socid = $user->socid; diff --git a/htdocs/core/actions_linkedfiles.inc.php b/htdocs/core/actions_linkedfiles.inc.php index 13814511297..750ed2b2d9a 100644 --- a/htdocs/core/actions_linkedfiles.inc.php +++ b/htdocs/core/actions_linkedfiles.inc.php @@ -21,13 +21,14 @@ // Variable $upload_dir must be defined when entering here. // Variable $upload_dirold may also exists. // Variable $confirm must be defined. +// If variable $permissiontoadd is defined, we check it is true. Note: A test on permission should already have been done into the restrictedArea() method called by parent page. //var_dump($upload_dir); //var_dump($upload_dirold); // Submit file/link -if (GETPOST('sendit', 'alpha') && !empty($conf->global->MAIN_UPLOAD_DOC)) { +if (GETPOST('sendit', 'alpha') && !empty($conf->global->MAIN_UPLOAD_DOC) && (!isset($permissiontoadd) || $permissiontoadd)) { if (!empty($_FILES)) { if (is_array($_FILES['userfile']['tmp_name'])) { $userfiles = $_FILES['userfile']['tmp_name']; @@ -65,7 +66,7 @@ if (GETPOST('sendit', 'alpha') && !empty($conf->global->MAIN_UPLOAD_DOC)) { } } } -} elseif (GETPOST('linkit', 'restricthtml') && !empty($conf->global->MAIN_UPLOAD_DOC)) { +} elseif (GETPOST('linkit', 'restricthtml') && !empty($conf->global->MAIN_UPLOAD_DOC) && (!isset($permissiontoadd) || $permissiontoadd)) { $link = GETPOST('link', 'alpha'); if ($link) { if (substr($link, 0, 7) != 'http://' && substr($link, 0, 8) != 'https://' && substr($link, 0, 7) != 'file://' && substr($link, 0, 7) != 'davs://') { @@ -77,7 +78,7 @@ if (GETPOST('sendit', 'alpha') && !empty($conf->global->MAIN_UPLOAD_DOC)) { // Delete file/link -if ($action == 'confirm_deletefile' && $confirm == 'yes') { +if ($action == 'confirm_deletefile' && $confirm == 'yes' && (!isset($permissiontoadd) || $permissiontoadd)) { $urlfile = GETPOST('urlfile', 'alpha', 0, null, null, 1); // Do not use urldecode here ($_GET and $_REQUEST are already decoded by PHP). if (GETPOST('section', 'alpha')) { // For a delete from the ECM module, upload_dir is ECM root dir and urlfile contains relative path from upload_dir @@ -149,7 +150,7 @@ if ($action == 'confirm_deletefile' && $confirm == 'yes') { exit; } } -} elseif ($action == 'confirm_updateline' && GETPOST('save', 'alpha') && GETPOST('link', 'alpha')) { +} elseif ($action == 'confirm_updateline' && GETPOST('save', 'alpha') && GETPOST('link', 'alpha') && (!isset($permissiontoadd) || $permissiontoadd)) { require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; $langs->load('link'); $link = new Link($db); @@ -167,7 +168,7 @@ if ($action == 'confirm_deletefile' && $confirm == 'yes') { } else { //error fetching } -} elseif ($action == 'renamefile' && GETPOST('renamefilesave', 'alpha')) { +} elseif ($action == 'renamefile' && GETPOST('renamefilesave', 'alpha') && (!isset($permissiontoadd) || $permissiontoadd)) { // For documents pages, upload_dir contains already path to file from module dir, so we clean path into urlfile. if (!empty($upload_dir)) { $filenamefrom = dol_sanitizeFileName(GETPOST('renamefilefrom', 'alpha'), '_', 0); // Do not remove accents diff --git a/htdocs/core/ajax/row.php b/htdocs/core/ajax/row.php index 4662c3a1406..96dc792938f 100644 --- a/htdocs/core/ajax/row.php +++ b/htdocs/core/ajax/row.php @@ -49,6 +49,9 @@ if (!defined('NOREQUIRETRAN')) { require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/genericobject.class.php'; +// Security check +// This is done later into view. + /* * View @@ -59,16 +62,16 @@ top_httphead(); print ''."\n"; // Registering the location of boxes -if (GETPOST('roworder', 'alpha', 2) && GETPOST('table_element_line', 'aZ09', 2) - && GETPOST('fk_element', 'aZ09', 2) && GETPOST('element_id', 'int', 2)) { - $roworder = GETPOST('roworder', 'alpha', 2); - $table_element_line = GETPOST('table_element_line', 'aZ09', 2); - $fk_element = GETPOST('fk_element', 'aZ09', 2); - $element_id = GETPOST('element_id', 'int', 2); +if (GETPOST('roworder', 'alpha', 3) && GETPOST('table_element_line', 'aZ09', 3) + && GETPOST('fk_element', 'aZ09', 3) && GETPOST('element_id', 'int', 3)) { + $roworder = GETPOST('roworder', 'alpha', 3); + $table_element_line = GETPOST('table_element_line', 'aZ09', 3); + $fk_element = GETPOST('fk_element', 'aZ09', 3); + $element_id = GETPOST('element_id', 'int', 3); dol_syslog("AjaxRow roworder=".$roworder." table_element_line=".$table_element_line." fk_element=".$fk_element." element_id=".$element_id, LOG_DEBUG); - // Make test on pemrission + // Make test on permission $perm = 0; if ($table_element_line == 'propaldet' && $user->rights->propal->creer) { $perm = 1; @@ -92,6 +95,10 @@ if (GETPOST('roworder', 'alpha', 2) && GETPOST('table_element_line', 'aZ09', 2) $perm = 1; } elseif ($table_element_line == 'facture_fourn_det' && $user->rights->fourn->facture->creer) { $perm = 1; + } elseif ($table_element_line == 'ecm_files' && $fk_element == 'fk_product' && (!empty($user->rights->produit->creer) || !empty($user->rights->service->creer))) { + $perm = 1; + } elseif ($table_element_line == 'ecm_files' && $fk_element == 'fk_ticket' && !empty($user->rights->ticket->write)) { + $perm = 1; } else { $tmparray = explode('_', $table_element_line); $tmpmodule = $tmparray[0]; $tmpobject = preg_replace('/line$/', '', $tmparray[1]); @@ -101,7 +108,10 @@ if (GETPOST('roworder', 'alpha', 2) && GETPOST('table_element_line', 'aZ09', 2) } if (! $perm) { + // We should not be here. If we are not allowed to reorder rows, feature should not be visible on script. + // If we are here, it is a hack attempt, so we report a warning. print 'Bad permission to modify position of lines for object in table '.$table_element_line; + dol_syslog('Bad permission to modify position of lines for object in table '.$table_element_line.', fk_element '.$fk_element, LOG_WARNING); accessforbidden('Bad permission to modify position of lines for object in table '.$table_element_line); } diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 1440a02983f..de4d67b1647 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -350,7 +350,7 @@ function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $f // Check write permission from module (we need to know write permission to create but also to delete drafts record or to upload files) $createok = 1; $nbko = 0; - $wemustcheckpermissionforcreate = (GETPOST('sendit', 'alpha') || GETPOST('linkit', 'alpha') || GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update'); + $wemustcheckpermissionforcreate = (GETPOST('sendit', 'alpha') || GETPOST('linkit', 'alpha') || GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update') || GETPOST('roworder', 'alpha', 2); $wemustcheckpermissionfordeletedraft = ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete'); if ($wemustcheckpermissionforcreate || $wemustcheckpermissionfordeletedraft) { diff --git a/htdocs/modulebuilder/template/myobject_document.php b/htdocs/modulebuilder/template/myobject_document.php index 8598cc3dd18..e3fa6390e93 100644 --- a/htdocs/modulebuilder/template/myobject_document.php +++ b/htdocs/modulebuilder/template/myobject_document.php @@ -124,7 +124,7 @@ if ($id > 0 || !empty($ref)) { $upload_dir = $conf->mymodule->multidir_output[$object->entity ? $object->entity : $conf->entity]."/myobject/".get_exdir(0, 0, 0, 1, $object); } -$permissiontoadd = $user->rights->mymodule->myobject->write; // Used by the include of actions_addupdatedelete.inc.php +$permissiontoadd = $user->rights->mymodule->myobject->write; // Used by the include of actions_addupdatedelete.inc.php and actions_linkedfiles.inc.php // Security check (enable the most restrictive one) //if ($user->socid > 0) accessforbidden(); diff --git a/htdocs/product/document.php b/htdocs/product/document.php index af44521dc05..372e3c19bdc 100644 --- a/htdocs/product/document.php +++ b/htdocs/product/document.php @@ -113,7 +113,7 @@ if ($reshook < 0) { if (empty($reshook)) { // Delete line if product propal merge is linked to a file if (!empty($conf->global->PRODUIT_PDF_MERGE_PROPAL)) { - if ($action == 'confirm_deletefile' && $confirm == 'yes') { + if ($action == 'confirm_deletefile' && $confirm == 'yes' && $permissiontoadd) { //extract file name $urlfile = GETPOST('urlfile', 'alpha'); $filename = basename($urlfile); @@ -131,7 +131,7 @@ if (empty($reshook)) { include DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; } -if ($action == 'filemerge') { +if ($action == 'filemerge' && $permissiontoadd) { $is_refresh = GETPOST('refresh'); if (empty($is_refresh)) { $filetomerge_file_array = GETPOST('filetoadd'); diff --git a/htdocs/projet/document.php b/htdocs/projet/document.php index 3f9ec04d437..6bb905d6696 100644 --- a/htdocs/projet/document.php +++ b/htdocs/projet/document.php @@ -40,11 +40,6 @@ $ref = GETPOST('ref', 'alpha'); $mine = (GETPOST('mode', 'alpha') == 'mine' ? 1 : 0); //if (! $user->rights->projet->all->lire) $mine=1; // Special for projects -// Security check -$socid = 0; -//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement. -$result = restrictedArea($user, 'projet', $id, 'projet&project'); - $object = new Project($db); include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once @@ -82,6 +77,11 @@ if (!$sortfield) { $sortfield = "name"; } +// Security check +$socid = 0; +//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement. +$result = restrictedArea($user, 'projet', $id, 'projet&project'); + /* diff --git a/htdocs/societe/document.php b/htdocs/societe/document.php index 4ed26f67018..653069882e0 100644 --- a/htdocs/societe/document.php +++ b/htdocs/societe/document.php @@ -76,6 +76,7 @@ if ($id > 0 || !empty($ref)) { // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('thirdpartydocument', 'globalcard')); +$permissiontoadd = $user->rights->societe->creer; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php // Security check if ($user->socid > 0) { diff --git a/htdocs/ticket/agenda.php b/htdocs/ticket/agenda.php index 9bf6cbc13c4..fee91e959aa 100644 --- a/htdocs/ticket/agenda.php +++ b/htdocs/ticket/agenda.php @@ -81,12 +81,9 @@ if (!$action) { // Security check $id = GETPOST("id", 'int'); $socid = 0; -//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement. +if ($user->socid > 0) $socid = $user->socid; $result = restrictedArea($user, 'ticket', $id, ''); -if (!$user->rights->ticket->read) { - accessforbidden(); -} // restrict access for externals users if ($user->socid > 0 && ($object->fk_soc != $user->socid)) { accessforbidden(); diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index c4c637754b4..5e2ef1e804b 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -112,8 +112,8 @@ if ($id || $track_id || $ref) { $url_page_current = DOL_URL_ROOT.'/ticket/card.php'; // Security check - Protection if external user -//if ($user->socid > 0) accessforbidden(); -//if ($user->socid > 0) $socid = $user->socid; +$socid = 0; +if ($user->socid > 0) $socid = $user->socid; $result = restrictedArea($user, 'ticket', $object->id); $triggermodname = 'TICKET_MODIFY'; diff --git a/htdocs/ticket/contact.php b/htdocs/ticket/contact.php index 7e04dd12104..8d450ffb44b 100644 --- a/htdocs/ticket/contact.php +++ b/htdocs/ticket/contact.php @@ -50,11 +50,6 @@ $source = GETPOST('source', 'alpha'); $ligne = GETPOST('ligne', 'int'); $lineid = GETPOST('lineid', 'int'); -// Protection if external user -if ($user->socid > 0) { - $socid = $user->socid; - accessforbidden(); -} // Store current page url $url_page_current = dol_buildpath('/ticket/contact.php', 1); @@ -62,6 +57,24 @@ $url_page_current = dol_buildpath('/ticket/contact.php', 1); $object = new Ticket($db); +$permissiontoadd = $user->rights->ticket->write; + +// Security check +$id = GETPOST("id", 'int'); +$socid = 0; +if ($user->socid > 0) $socid = $user->socid; +$result = restrictedArea($user, 'ticket', $object->id, ''); + +// restrict access for externals users +if ($user->socid > 0 && ($object->fk_soc != $user->socid)) { + accessforbidden(); +} +// or for unauthorized internals users +if (!$user->socid && (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { + accessforbidden(); +} + + /* * Actions */ diff --git a/htdocs/ticket/document.php b/htdocs/ticket/document.php index 5e4d80cd8be..8edd2787c44 100644 --- a/htdocs/ticket/document.php +++ b/htdocs/ticket/document.php @@ -43,11 +43,6 @@ $track_id = GETPOST('track_id', 'alpha'); $action = GETPOST('action', 'alpha'); $confirm = GETPOST('confirm', 'alpha'); -// Security check -if (!$user->rights->ticket->read) { - accessforbidden(); -} - // Get parameters $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; $sortfield = GETPOST("sortfield", 'alpha'); @@ -75,6 +70,21 @@ if ($result < 0) { $upload_dir = $conf->ticket->dir_output."/".dol_sanitizeFileName($object->ref); } +$permissiontoadd = $user->rights->ticket->write; + +// Security check - Protection if external user +$result = restrictedArea($user, 'ticket', $object->id); + +// restrict access for externals users +if ($user->socid > 0 && ($object->fk_soc != $user->socid)) { + accessforbidden(); +} +// or for unauthorized internals users +if (!$user->socid && ($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY && $object->fk_user_assign != $user->id) && !$user->rights->ticket->manage) { + accessforbidden(); +} + + /* * Actions diff --git a/htdocs/ticket/messaging.php b/htdocs/ticket/messaging.php index c3e70def7da..68615424abf 100644 --- a/htdocs/ticket/messaging.php +++ b/htdocs/ticket/messaging.php @@ -76,16 +76,14 @@ if (!$action) { $action = 'view'; } +$permissiontoadd = $user->rights->ticket->write; // Security check $id = GETPOST("id", 'int'); $socid = 0; -//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignement. -$result = restrictedArea($user, 'ticket', $id, ''); +if ($user->socid > 0) $socid = $user->socid; +$result = restrictedArea($user, 'ticket', $object->id, ''); -if (!$user->rights->ticket->read) { - accessforbidden(); -} // restrict access for externals users if ($user->socid > 0 && ($object->fk_soc != $user->socid)) { accessforbidden(); @@ -96,7 +94,6 @@ if (!$user->socid && (!empty($conf->global->TICKET_LIMIT_VIEW_ASSIGNED_ONLY) && } - /* * Actions */ From f51e892a97a70c224fe37061ef46a4921ca660e8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 18 May 2021 02:06:35 +0200 Subject: [PATCH 21/23] Fix phpcs --- htdocs/admin/dict.php | 28 +++++++++++++-------------- htdocs/user/class/api_users.class.php | 6 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 2004ccf86b9..d03574d473b 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -869,13 +869,13 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { $keycode = $value; } - if ($value == 'price' || preg_match('/^amount/i', $value)) { - $_POST[$keycode] = price2num(GETPOST($keycode), 'MU'); - } elseif ($value == 'taux' || $value == 'localtax1') { - $_POST[$keycode] = price2num(GETPOST($keycode), 8); // Note that localtax2 can be a list of rates separated by coma like X:Y:Z - } elseif ($value == 'entity') { - $_POST[$keycode] = getEntity($tabname[$id]); - } + if ($value == 'price' || preg_match('/^amount/i', $value)) { + $_POST[$keycode] = price2num(GETPOST($keycode), 'MU'); + } elseif ($value == 'taux' || $value == 'localtax1') { + $_POST[$keycode] = price2num(GETPOST($keycode), 8); // Note that localtax2 can be a list of rates separated by coma like X:Y:Z + } elseif ($value == 'entity') { + $_POST[$keycode] = getEntity($tabname[$id]); + } if ($i) { $sql .= ","; @@ -938,13 +938,13 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) { $keycode = $field; } - if ($field == 'price' || preg_match('/^amount/i', $field)) { - $_POST[$keycode] = price2num(GETPOST($keycode), 'MU'); - } elseif ($field == 'taux' || $field == 'localtax1') { - $_POST[$keycode] = price2num(GETPOST($keycode), 8); // Note that localtax2 can be a list of rates separated by coma like X:Y:Z - } elseif ($field == 'entity') { - $_POST[$keycode] = getEntity($tabname[$id]); - } + if ($field == 'price' || preg_match('/^amount/i', $field)) { + $_POST[$keycode] = price2num(GETPOST($keycode), 'MU'); + } elseif ($field == 'taux' || $field == 'localtax1') { + $_POST[$keycode] = price2num(GETPOST($keycode), 8); // Note that localtax2 can be a list of rates separated by coma like X:Y:Z + } elseif ($field == 'entity') { + $_POST[$keycode] = getEntity($tabname[$id]); + } if ($i) { $sql .= ","; diff --git a/htdocs/user/class/api_users.class.php b/htdocs/user/class/api_users.class.php index a21db2b521b..e760997f3c8 100644 --- a/htdocs/user/class/api_users.class.php +++ b/htdocs/user/class/api_users.class.php @@ -48,7 +48,7 @@ class Users extends DolibarrApi public function __construct() { global $db, $conf; - + $this->db = $db; $this->useraccount = new User($this->db); } @@ -73,8 +73,8 @@ class Users extends DolibarrApi global $conf; if (empty(DolibarrApiAccess::$user->rights->user->user->lire) && empty(DolibarrApiAccess::$user->admin)) { - throw new RestException(401, "You are not allowed to read list of users"); - } + throw new RestException(401, "You are not allowed to read list of users"); + } $obj_ret = array(); From 9b0988e7bed846e947a0ff48abc016ee091445dc Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 18 May 2021 08:40:28 +0200 Subject: [PATCH 22/23] FIX Social contrib. - Missing language file --- htdocs/compta/sociales/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/sociales/list.php b/htdocs/compta/sociales/list.php index 2b0c3961759..db754390e5e 100644 --- a/htdocs/compta/sociales/list.php +++ b/htdocs/compta/sociales/list.php @@ -38,7 +38,7 @@ if (!empty($conf->projet->enabled)) { } // Load translation files required by the page -$langs->loadLangs(array('compta', 'banks', 'bills', 'hrm')); +$langs->loadLangs(array('compta', 'banks', 'bills', 'hrm', 'projects')); $action = GETPOST('action', 'aZ09'); $massaction = GETPOST('massaction', 'alpha'); From 2771d50ffec7712f3b4977363d433905e9a4c190 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 18 May 2021 11:55:56 +0200 Subject: [PATCH 23/23] code comment --- htdocs/product/stock/replenish.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index fe16aca2783..48d8bf2033d 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -66,7 +66,7 @@ $fourn_id = GETPOST('fourn_id', 'int'); $fk_supplier = GETPOST('fk_supplier', 'int'); $fk_entrepot = GETPOST('fk_entrepot', 'int'); -//List all visible warehouses +// List all visible warehouses $resWar = $db->query("SELECT rowid FROM " . MAIN_DB_PREFIX . "entrepot WHERE entity IN (" . $db->sanitize(getEntity('stock')) .")"); $listofqualifiedwarehousesid = ""; $count = 0; @@ -103,6 +103,7 @@ if (!$sortorder) { $sortorder = 'ASC'; } +// Define virtualdiffersfromphysical $virtualdiffersfromphysical = 0; if (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)