From 803722e323801bbc4e3d5b79651bd666cb0835ad Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Wed, 4 Aug 2021 14:48:10 +0200 Subject: [PATCH 01/15] Fix : we only want employee users for holidays --- htdocs/holiday/class/holiday.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index 2637f3c0eaa..3cd649e11ac 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -1630,6 +1630,7 @@ class Holiday extends CommonObject $sql .= " WHERE u.entity IN (".getEntity('user').")"; } $sql .= " AND u.statut > 0"; + $sql .= " AND u.employee = 1"; // We only want employee users for holidays if ($filters) $sql .= $filters; $resql = $this->db->query($sql); @@ -1720,6 +1721,7 @@ class Holiday extends CommonObject } $sql .= " AND u.statut > 0"; + $sql .= " AND u.employee = 1"; // We only want employee users for holidays if ($filters) $sql .= $filters; $resql = $this->db->query($sql); From ceaaff0186455528c266caf9b1633b0b314d84da Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 17 Aug 2021 18:05:34 +0200 Subject: [PATCH 02/15] Sellby always before Eatby #18361 --- htdocs/reception/card.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/reception/card.php b/htdocs/reception/card.php index 24144365256..40444faacb7 100644 --- a/htdocs/reception/card.php +++ b/htdocs/reception/card.php @@ -1827,12 +1827,12 @@ if ($action == 'create') { print '
'; if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { - print $langs->trans('EatByDate').' : '; - print $form->selectDate($lines[$i]->eatby, 'dlc'.$line_id, '', '', 1, "").'
'; + print $langs->trans('SellByDate').' : '; + print $form->selectDate($lines[$i]->sellby, 'dlc'.$line_id, '', '', 1, "").'
'; } if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { - print $langs->trans('SellByDate').' : '; - print $form->selectDate($lines[$i]->sellby, 'dluo'.$line_id, '', '', 1, ""); + print $langs->trans('EatByDate').' : '; + print $form->selectDate($lines[$i]->eatby, 'dluo'.$line_id, '', '', 1, ""); } print ''; } From ff3f85b2148b2b97b9ec3cde92d380fea61ff702 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Aug 2021 01:44:52 +0200 Subject: [PATCH 03/15] Fix case sensitive --- htdocs/core/lib/functions.lib.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 9a6a8b9b140..3e6bcd9d5d1 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1320,8 +1320,8 @@ function dol_escape_htmltag($stringtoescape, $keepb = 0, $keepn = 0, $noescapeta if (count($tmparrayoftags)) { foreach ($tmparrayoftags as $tagtoreplace) { - $tmp = str_replace('<'.$tagtoreplace.'>', '__BEGINTAGTOREPLACE'.$tagtoreplace.'__', $tmp); - $tmp = str_replace('', '__ENDTAGTOREPLACE'.$tagtoreplace.'__', $tmp); + $tmp = str_ireplace('<'.$tagtoreplace.'>', '__BEGINTAGTOREPLACE'.$tagtoreplace.'__', $tmp); + $tmp = str_ireplace('', '__ENDTAGTOREPLACE'.$tagtoreplace.'__', $tmp); } } @@ -1329,8 +1329,8 @@ function dol_escape_htmltag($stringtoescape, $keepb = 0, $keepn = 0, $noescapeta if (count($tmparrayoftags)) { foreach ($tmparrayoftags as $tagtoreplace) { - $result = str_replace('__BEGINTAGTOREPLACE'.$tagtoreplace.'__', '<'.$tagtoreplace.'>', $result); - $result = str_replace('__ENDTAGTOREPLACE'.$tagtoreplace.'__', '', $result); + $result = str_ireplace('__BEGINTAGTOREPLACE'.$tagtoreplace.'__', '<'.$tagtoreplace.'>', $result); + $result = str_ireplace('__ENDTAGTOREPLACE'.$tagtoreplace.'__', '', $result); } } From fe17c13a5f20d16cc3958864c477ad855676343c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 22 Aug 2021 19:22:47 +0200 Subject: [PATCH 04/15] FIX an approved holiday can be canceled by an admin. --- htdocs/holiday/card.php | 58 +++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/htdocs/holiday/card.php b/htdocs/holiday/card.php index ffbd3204459..729b4653f64 100644 --- a/htdocs/holiday/card.php +++ b/htdocs/holiday/card.php @@ -49,7 +49,7 @@ $ref = GETPOST('ref', 'alpha'); $fuserid = (GETPOST('fuserid', 'int') ?GETPOST('fuserid', 'int') : $user->id); // Load translation files required by the page -$langs->loadLangs(array("other", "holiday", "mails")); +$langs->loadLangs(array("other", "holiday", "mails", "trips")); $now = dol_now(); @@ -255,6 +255,7 @@ if (empty($reshook)) } } + // If update and we are an approver, we can update with another approver if ($action == 'update' && GETPOSTISSET('savevalidator') && !empty($user->rights->holiday->approve)) { $object->fetch($id); @@ -310,6 +311,8 @@ if (empty($reshook)) if ($cancreate) { $valideur = GETPOST('valideur', 'int'); + // TODO Check this user id has the permission for approval + $description = trim(GETPOST('description', 'restricthtml')); // If no start date @@ -760,7 +763,7 @@ if (empty($reshook)) } } - // Si confirmation of cancellation + // If confirmation of cancellation if ($action == 'confirm_cancel' && GETPOST('confirm') == 'yes') { $error = 0; @@ -768,8 +771,8 @@ if (empty($reshook)) $object->fetch($id); // Si statut en attente de validation et valideur = valideur ou utilisateur, ou droits de faire pour les autres - if (($object->statut == Holiday::STATUS_VALIDATED || $object->statut == Holiday::STATUS_APPROVED) && ($user->id == $object->fk_validator || in_array($object->fk_user, $childids) - || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->holiday->writeall_advance)))) + if (($object->statut == Holiday::STATUS_VALIDATED || $object->statut == Holiday::STATUS_APPROVED) && + (!empty($user->admin) || $user->id == $object->fk_validator || in_array($object->fk_user, $childids) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->holiday->writeall_advance)))) { $db->begin(); @@ -1468,30 +1471,53 @@ if ((empty($id) && empty($ref)) || $action == 'create' || $action == 'add') print '
'; - if ($cancreate && $object->statut == Holiday::STATUS_DRAFT) - { + if ($cancreate && $object->statut == Holiday::STATUS_DRAFT) { print ''.$langs->trans("EditCP").''; } - if ($cancreate && $object->statut == Holiday::STATUS_DRAFT) // If draft - { + + if ($cancreate && $object->statut == Holiday::STATUS_DRAFT) { // If draft print ''.$langs->trans("Validate").''; } - if ($object->statut == Holiday::STATUS_VALIDATED) // If validated - { - if ($user->id == $object->fk_validator) - { + + if ($object->statut == Holiday::STATUS_VALIDATED) { // If validated + // Button Approve / Refuse + if ($user->id == $object->fk_validator) { print ''.$langs->trans("Approve").''; print ''.$langs->trans("ActionRefuseCP").''; } else { print ''.$langs->trans("Approve").''; print ''.$langs->trans("ActionRefuseCP").''; + + // Button Cancel + if (in_array($object->fk_user, $childids) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->holiday->writeall_advance))) { + if (($object->date_debut > dol_now()) || !empty($user->admin)) { + print ''.$langs->trans("ActionCancelCP").''; + } else { + print 'trans("NotAllowed").'">'.$langs->trans("ActionCancelCP").''; + } + } } } - if (($user->id == $object->fk_validator || in_array($object->fk_user, $childids) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->holiday->writeall_advance))) && ($object->statut == 2 || $object->statut == 3)) // Status validated or approved - { - if (($object->date_debut > dol_now()) || $user->admin) print ''.$langs->trans("ActionCancelCP").''; - else print ''.$langs->trans("ActionCancelCP").''; + + if ($object->statut == Holiday::STATUS_APPROVED) { // If validated or approved + if ($user->id == $object->fk_validator + || in_array($object->fk_user, $childids) + || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->holiday->writeall_advance))) { + if (($object->date_debut > dol_now()) || !empty($user->admin)) { + print ''.$langs->trans("ActionCancelCP").''; + } else { + print 'trans("NotAllowed").'">'.$langs->trans("ActionCancelCP").''; + } + } else { // I have no rights on the user of the holiday. + if (!empty($user->admin)) { // If current validator can't cancel an approved leave, we allow admin user + print ''.$langs->trans("ActionCancelCP").''; + } else { + print ''.$langs->trans("ActionCancelCP").''; + } + } } + + if ($cancreate && $object->statut == Holiday::STATUS_CANCELED) { print ''.$langs->trans("SetToDraft").''; From 0325b68bfbe23586ee0efb7018acf16a6bd11e4a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Aug 2021 10:17:36 +0200 Subject: [PATCH 05/15] Fix missing autoselect --- htdocs/admin/agenda_xcal.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/htdocs/admin/agenda_xcal.php b/htdocs/admin/agenda_xcal.php index 59dd1bf1ac2..f42cb5c842f 100644 --- a/htdocs/admin/agenda_xcal.php +++ b/htdocs/admin/agenda_xcal.php @@ -165,24 +165,27 @@ $urlvcal = ''.$langs->trans("WebCalUrlForVCalExport", 'vcal', '').''); $message .= ''; +$message .= ajax_autoselect('onlinepaymenturl1'); $message .= '
'; $urlical = '
'; $urlical .= $urlwithroot.'/public/agenda/agendaexport.php?format=ical&type=event'.$getentity.'&exportkey='.($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY ?urlencode($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY) : 'KEYNOTDEFINED').''; $message .= img_picto('', 'globe').' '.str_replace('{url}', $urlical, ''.$langs->trans("WebCalUrlForVCalExport", 'ical/ics', '').''); $message .= ''; +$message .= ajax_autoselect('onlinepaymenturl2'); $message .= '
'; $urlrss = ''; $urlrss .= $urlwithroot.'/public/agenda/agendaexport.php?format=rss'.$getentity.'&exportkey='.($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY ?urlencode($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY) : 'KEYNOTDEFINED').''; $message .= img_picto('', 'globe').' '.str_replace('{url}', $urlrss, ''.$langs->trans("WebCalUrlForVCalExport", 'rss', '').''); $message .= ''; +$message .= ajax_autoselect('onlinepaymenturl3'); $message .= '
'; print $message; From fdffc0c13a55cc2c4e6b877af5c736e075a5d449 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Aug 2021 11:32:25 +0200 Subject: [PATCH 06/15] NEW Add param $nolog to avoid logging into dol_delete_recursive_dir() --- htdocs/core/lib/files.lib.php | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 3c35bcda2a9..a5f61a60aac 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1159,10 +1159,11 @@ function dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disable * @param object $object Current object in use * @param boolean $allowdotdot Allow to delete file path with .. inside. Never use this, it is reserved for migration purpose. * @param int $indexdatabase Try to remove also index entries. + * @param int $nolog Disable log file * @return boolean True if no error (file is deleted or if glob is used and there's nothing to delete), False if error * @see dol_delete_dir() */ -function dol_delete_file($file, $disableglob = 0, $nophperrors = 0, $nohook = 0, $object = null, $allowdotdot = false, $indexdatabase = 1) +function dol_delete_file($file, $disableglob = 0, $nophperrors = 0, $nohook = 0, $object = null, $allowdotdot = false, $indexdatabase = 1, $nolog = 0) { global $db, $conf, $user, $langs; global $hookmanager; @@ -1170,7 +1171,9 @@ function dol_delete_file($file, $disableglob = 0, $nophperrors = 0, $nohook = 0, // Load translation files required by the page $langs->loadLangs(array('other', 'errors')); - dol_syslog("dol_delete_file file=".$file." disableglob=".$disableglob." nophperrors=".$nophperrors." nohook=".$nohook); + if (empty($nolog)) { + dol_syslog("dol_delete_file file=".$file." disableglob=".$disableglob." nophperrors=".$nophperrors." nohook=".$nohook); + } // Security: // We refuse transversal using .. and pipes into filenames. @@ -1304,11 +1307,15 @@ function dol_delete_dir($dir, $nophperrors = 0) * @param int $nophperrors Disable all PHP output errors * @param int $onlysub Delete only files and subdir, not main directory * @param int $countdeleted Counter to count nb of elements found really deleted + * @param int $indexdatabase Try to remove also index entries. + * @param int $nolog Disable log files (too verbose when making recursive directories) * @return int Number of files and directory we try to remove. NB really removed is returned into var by reference $countdeleted. */ -function dol_delete_dir_recursive($dir, $count = 0, $nophperrors = 0, $onlysub = 0, &$countdeleted = 0) +function dol_delete_dir_recursive($dir, $count = 0, $nophperrors = 0, $onlysub = 0, &$countdeleted = 0, $indexdatabase = 1, $nolog = 0) { - dol_syslog("functions.lib:dol_delete_dir_recursive ".$dir, LOG_DEBUG); + if (empty($nolog)) { + dol_syslog("functions.lib:dol_delete_dir_recursive ".$dir, LOG_DEBUG); + } if (dol_is_dir($dir)) { $dir_osencoded = dol_osencode($dir); if ($handle = opendir("$dir_osencoded")) { @@ -1319,9 +1326,9 @@ function dol_delete_dir_recursive($dir, $count = 0, $nophperrors = 0, $onlysub = if ($item != "." && $item != "..") { if (is_dir(dol_osencode("$dir/$item")) && !is_link(dol_osencode("$dir/$item"))) { - $count = dol_delete_dir_recursive("$dir/$item", $count, $nophperrors, 0, $countdeleted); + $count = dol_delete_dir_recursive("$dir/$item", $count, $nophperrors, 0, $countdeleted, $indexdatabase, $nolog); } else { - $result = dol_delete_file("$dir/$item", 1, $nophperrors); + $result = dol_delete_file("$dir/$item", 1, $nophperrors, 0, null, false, $indexdatabase, $nolog); $count++; if ($result) { $countdeleted++; @@ -1332,6 +1339,7 @@ function dol_delete_dir_recursive($dir, $count = 0, $nophperrors = 0, $onlysub = } closedir($handle); + // Delete also the main directory if (empty($onlysub)) { $result = dol_delete_dir($dir, $nophperrors); $count++; From 227f01b0006adb62cd5697ca5e537bc8463337bc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Aug 2021 11:51:01 +0200 Subject: [PATCH 07/15] Fix can add a redirection into the executeCLI method. --- htdocs/core/class/utils.class.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/utils.class.php b/htdocs/core/class/utils.class.php index bdd6cc2b83a..7902b069b94 100644 --- a/htdocs/core/class/utils.class.php +++ b/htdocs/core/class/utils.class.php @@ -593,12 +593,14 @@ class Utils /** * Execute a CLI command. * - * @param string $command Command line to execute. - * @param string $outputfile A path for an output file (used only when method is 2). For example: $conf->admin->dir_temp.'/out.tmp'; - * @param int $execmethod 0=Use default method (that is 1 by default), 1=Use the PHP 'exec', 2=Use the 'popen' method - * @return array array('result'=>...,'output'=>...,'error'=>...). result = 0 means OK. + * @param string $command Command line to execute. + * Warning: The command line is sanitize so can't contains any redirection char '>'. Use param $redirectionfile if you need it. + * @param string $outputfile A path for an output file (used only when method is 2). For example: $conf->admin->dir_temp.'/out.tmp'; + * @param int $execmethod 0=Use default method (that is 1 by default), 1=Use the PHP 'exec', 2=Use the 'popen' method + * @param string $redirectionfile If defined, file to redirect output to. + * @return array array('result'=>...,'output'=>...,'error'=>...). result = 0 means OK. */ - public function executeCLI($command, $outputfile, $execmethod = 0) + public function executeCLI($command, $outputfile, $execmethod = 0, $redirectionfile = null) { global $conf, $langs; @@ -607,6 +609,9 @@ class Utils $error = ''; $command = escapeshellcmd($command); + if ($redirectionfile) { + $command .= " > ".dol_sanitizePathName($redirectionfile); + } $command .= " 2>&1"; if (!empty($conf->global->MAIN_EXEC_USE_POPEN)) { From 041784876d92e721c1d3a3c20b1f3e3f9e67c667 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Aug 2021 11:58:14 +0200 Subject: [PATCH 08/15] Fix option $nolog --- htdocs/core/lib/files.lib.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index a5f61a60aac..9db9379523e 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -1229,7 +1229,9 @@ function dol_delete_file($file, $disableglob = 0, $nophperrors = 0, $nohook = 0, } if ($ok) { - dol_syslog("Removed file ".$filename, LOG_DEBUG); + if (empty($nolog)) { + dol_syslog("Removed file ".$filename, LOG_DEBUG); + } // Delete entry into ecm database $rel_filetodelete = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $filename); @@ -1267,7 +1269,9 @@ function dol_delete_file($file, $disableglob = 0, $nophperrors = 0, $nohook = 0, $ok = unlink($file_osencoded); } if ($ok) { - dol_syslog("Removed file ".$file_osencoded, LOG_DEBUG); + if (empty($nolog)) { + dol_syslog("Removed file ".$file_osencoded, LOG_DEBUG); + } } else { dol_syslog("Failed to remove file ".$file_osencoded, LOG_WARNING); } From 983d7e51774de945468d16ea575c1179070b9659 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Aug 2021 12:19:16 +0200 Subject: [PATCH 09/15] FIX Add option $noescapecommand in executeCLI for better compatibility --- htdocs/core/class/utils.class.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/utils.class.php b/htdocs/core/class/utils.class.php index 7902b069b94..5371d917022 100644 --- a/htdocs/core/class/utils.class.php +++ b/htdocs/core/class/utils.class.php @@ -597,10 +597,12 @@ class Utils * Warning: The command line is sanitize so can't contains any redirection char '>'. Use param $redirectionfile if you need it. * @param string $outputfile A path for an output file (used only when method is 2). For example: $conf->admin->dir_temp.'/out.tmp'; * @param int $execmethod 0=Use default method (that is 1 by default), 1=Use the PHP 'exec', 2=Use the 'popen' method - * @param string $redirectionfile If defined, file to redirect output to. + * @param string $redirectionfile If defined, a redirection of output to this files is added. + * @param int $noescapecommand 1=Do not escape command. Warning: Using this parameter need you alreay sanitized the command. if not, it will lead to security vulnerability. + * This parameter is provided for backward compatibility with external modules. Always use 0 in core. * @return array array('result'=>...,'output'=>...,'error'=>...). result = 0 means OK. */ - public function executeCLI($command, $outputfile, $execmethod = 0, $redirectionfile = null) + public function executeCLI($command, $outputfile, $execmethod = 0, $redirectionfile = null, $noescapecommand = 0) { global $conf, $langs; @@ -608,7 +610,9 @@ class Utils $output = ''; $error = ''; - $command = escapeshellcmd($command); + if (empty($noescapecommand)) { + $command = escapeshellcmd($command); + } if ($redirectionfile) { $command .= " > ".dol_sanitizePathName($redirectionfile); } From a25346e30244aca0d86a36e9f982aad06cc6f247 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Aug 2021 15:00:29 +0200 Subject: [PATCH 10/15] FIX Date of payment of subscription must not be set to 1970-01-01. Fix look and feel v14 --- htdocs/adherents/card.php | 4 ++-- htdocs/adherents/subscription.php | 19 ++++++++++--------- htdocs/core/lib/company.lib.php | 13 +++++++++++++ htdocs/core/lib/member.lib.php | 16 +--------------- htdocs/societe/partnership.php | 3 +++ 5 files changed, 29 insertions(+), 26 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 7c5d074d51e..fc019ae53f5 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -1822,7 +1822,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { $result = $company->fetch($object->socid); print $company->getNomUrl(1); } else { - print $langs->trans("NoThirdPartyAssociatedToMember"); + print ''.$langs->trans("NoThirdPartyAssociatedToMember").''; } } print ''; @@ -1846,7 +1846,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { } print ''; - //VCard + // VCard print ''; print $langs->trans("VCard").''; print ''; diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index 7f8da3a33b3..14b71a3c950 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -209,7 +209,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! // Subscription informations $datesubscription = 0; $datesubend = 0; - $paymentdate = 0; + $paymentdate = ''; // Do not use 0 here, default value is '' that means not filled where 0 means 1970-01-01 if (GETPOST("reyear", "int") && GETPOST("remonth", "int") && GETPOST("reday", "int")) { $datesubscription = dol_mktime(0, 0, 0, GETPOST("remonth", "int"), GETPOST("reday", "int"), GETPOST("reyear", "int")); } @@ -602,7 +602,7 @@ if ($rowid > 0) { $result = $company->fetch($object->fk_soc); print $company->getNomUrl(1); } else { - print $langs->trans("NoThirdPartyAssociatedToMember"); + print ''.$langs->trans("NoThirdPartyAssociatedToMember").''; } } print ''; @@ -628,7 +628,7 @@ if ($rowid > 0) { if ($object->user_id) { $form->form_users($_SERVER['PHP_SELF'].'?rowid='.$object->id, $object->user_id, 'none'); } else { - print $langs->trans("NoDolibarrAccess"); + print ''.$langs->trans("NoDolibarrAccess").''; } } print ''; @@ -970,17 +970,18 @@ if ($rowid > 0) { print ''.$langs->trans('MoreActions'); print ''; print ''; - print ' '.$langs->trans("None").'
'; + print ''; + print '
'; // Add entry into bank accoun if (!empty($conf->banque->enabled)) { print ' '.$langs->trans("MoreActionBankDirect").'
'; + print '>
'; } // Add invoice with no payments if (!empty($conf->societe->enabled) && !empty($conf->facture->enabled)) { print 'fk_soc)) print ' disabled'; - print '> '.$langs->trans("MoreActionInvoiceOnly"); + print '>
'; } // Add invoice with payments if (!empty($conf->banque->enabled) && !empty($conf->societe->enabled) && !empty($conf->facture->enabled)) { print 'fk_soc)) print ' disabled'; - print '> '.$langs->trans("MoreActionBankViaInvoice"); + print '>
'; } print ''; diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 7d261f2d5ab..0204fd28922 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -272,6 +272,19 @@ function societe_prepare_head(Societe $object) $h++; } + if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'thirdparty') { + if (!empty($user->rights->partnership->read)) { + $nbPartnership = is_array($object->partnerships) ? count($object->partnerships) : 0; + $head[$h][0] = DOL_URL_ROOT.'/societe/partnership.php?socid='.$object->id; + $head[$h][1] = $langs->trans("Partnership"); + $head[$h][2] = 'partnership'; + if ($nbPartnership > 0) { + $head[$h][1] .= ''.$nbPartnership.''; + } + $h++; + } + } + // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab diff --git a/htdocs/core/lib/member.lib.php b/htdocs/core/lib/member.lib.php index fc274e0d624..ed3b69752f1 100644 --- a/htdocs/core/lib/member.lib.php +++ b/htdocs/core/lib/member.lib.php @@ -63,9 +63,7 @@ function member_prepare_head(Adherent $object) $h++; } - $tabtoadd = (!empty(getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR')) && getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') ? 'member' : 'thirdparty'; - - if ($tabtoadd == 'member') { + if (getDolGlobalString('PARTNERSHIP_IS_MANAGED_FOR') == 'member') { if (!empty($user->rights->partnership->read)) { $nbPartnership = is_array($object->partnerships) ? count($object->partnerships) : 0; $head[$h][0] = DOL_URL_ROOT.'/adherents/partnership.php?rowid='.$object->id; @@ -76,20 +74,8 @@ function member_prepare_head(Adherent $object) } $h++; } - } else { - if (!empty($user->rights->partnership->read)) { - $nbPartnership = is_array($object->partnerships) ? count($object->partnerships) : 0; - $head[$h][0] = DOL_URL_ROOT.'/societe/partnership.php?socid='.$object->id; - $head[$h][1] = $langs->trans("Partnership"); - $head[$h][2] = 'partnership'; - if ($nbPartnership > 0) { - $head[$h][1] .= ''.$nbPartnership.''; - } - $h++; - } } - // Show more tabs from modules // Entries must be declared in modules descriptor with line // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab diff --git a/htdocs/societe/partnership.php b/htdocs/societe/partnership.php index 9cb065d2c3b..b1f0f24fbe1 100644 --- a/htdocs/societe/partnership.php +++ b/htdocs/societe/partnership.php @@ -50,6 +50,9 @@ $backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); $socid = GETPOST('socid', 'int'); if (!empty($user->socid)) { $socid = $user->socid; +} + +if (empty($id) && $socid && (empty($conf->global->PARTNERSHIP_IS_MANAGED_FOR) || $conf->global->PARTNERSHIP_IS_MANAGED_FOR == 'thirdparty')) { $id = $socid; } From 5f16de81500a10cc27cf335b1cf29864a515862e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Aug 2021 15:08:29 +0200 Subject: [PATCH 11/15] Code comment --- htdocs/adherents/subscription.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index 14b71a3c950..2ea8c62dd03 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -268,6 +268,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! $error++; $action = 'addsubscription'; } else { + // If an amount has been provided, we check also fields that becomes mandatory when amount is not null. if (!empty($conf->banque->enabled) && GETPOST("paymentsave") != 'none') { if (GETPOST("subscription")) { if (!GETPOST("label")) { @@ -280,7 +281,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! $errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("FinancialAccount")); } } else { - if (GETPOST("accountid")) { + if (GETPOST("accountid", 'int')) { $errmsg = $langs->trans("ErrorDoNotProvideAccountsIfNullAmount"); } } From 21852bd16bbc5274880633423b9d3c06f3731b96 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Aug 2021 15:25:41 +0200 Subject: [PATCH 12/15] Show link to invoices on member record --- htdocs/adherents/card.php | 8 ++++++++ htdocs/adherents/subscription.php | 28 +++++++++++++++++++++------- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index fc019ae53f5..b33e03d5855 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -1821,6 +1821,14 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { $company = new Societe($db); $result = $company->fetch($object->socid); print $company->getNomUrl(1); + + // Show link to invoices + $tmparray = $company->getOutstandingBills('customer'); + if (!empty($tmparray['refs'])) { + print ' - '.img_picto($langs->trans("Invoices"), 'bill', 'class="paddingright"').'
'.$langs->trans("Invoices").': '.count($tmparray['refs']); + // TODO Add alert if warning on at least one invoice late + print ''; + } } else { print ''.$langs->trans("NoThirdPartyAssociatedToMember").''; } diff --git a/htdocs/adherents/subscription.php b/htdocs/adherents/subscription.php index 2ea8c62dd03..3a967677e17 100644 --- a/htdocs/adherents/subscription.php +++ b/htdocs/adherents/subscription.php @@ -260,7 +260,7 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! } // Check if a payment is mandatory or not - if (!$error && $adht->subscription) { // Member type need subscriptions + if ($adht->subscription) { // Member type need subscriptions if (!is_numeric($amount)) { // If field is '' or not a numeric value $errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Amount")); @@ -273,24 +273,30 @@ if ($user->rights->adherent->cotisation->creer && $action == 'subscription' && ! if (GETPOST("subscription")) { if (!GETPOST("label")) { $errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")); + setEventMessages($errmsg, null, 'errors'); + $error++; + $action = 'addsubscription'; } if (GETPOST("paymentsave") != 'invoiceonly' && !GETPOST("operation")) { $errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("PaymentMode")); + setEventMessages($errmsg, null, 'errors'); + $error++; + $action = 'addsubscription'; } if (GETPOST("paymentsave") != 'invoiceonly' && !(GETPOST("accountid", 'int') > 0)) { $errmsg = $langs->trans("ErrorFieldRequired", $langs->transnoentities("FinancialAccount")); + setEventMessages($errmsg, null, 'errors'); + $error++; + $action = 'addsubscription'; } } else { if (GETPOST("accountid", 'int')) { $errmsg = $langs->trans("ErrorDoNotProvideAccountsIfNullAmount"); + setEventMessages($errmsg, null, 'errors'); + $error++; + $action = 'addsubscription'; } } - if ($errmsg) { - $error++; - setEventMessages($errmsg, null, 'errors'); - $error++; - $action = 'addsubscription'; - } } } } @@ -602,6 +608,14 @@ if ($rowid > 0) { $company = new Societe($db); $result = $company->fetch($object->fk_soc); print $company->getNomUrl(1); + + // Show link to invoices + $tmparray = $company->getOutstandingBills('customer'); + if (!empty($tmparray['refs'])) { + print ' - '.img_picto($langs->trans("Invoices"), 'bill', 'class="paddingright"').''.$langs->trans("Invoices").': '.count($tmparray['refs']); + // TODO Add alert if warning on at least one invoice late + print ''; + } } else { print ''.$langs->trans("NoThirdPartyAssociatedToMember").''; } From fc6a0dfcaae12e70c08775ea989046cd6ec3d4b1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Aug 2021 15:47:18 +0200 Subject: [PATCH 13/15] FIX #yogosha6944 Protection against traversal path. --- htdocs/core/lib/functions.lib.php | 8 ++++---- test/phpunit/SecurityTest.php | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 3e6bcd9d5d1..4334aa9a12d 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -753,9 +753,9 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = $out = dol_string_nohtmltag($out, 0); // Remove also other dangerous string sequences // '"' is dangerous because param in url can close the href= or src= and add javascript functions. - // '../' is dangerous because it allows dir transversals + // '../' or '..\' is dangerous because it allows dir transversals // Note &, '&', '&'... is a simple char like '&' alone but there is no reason to accept such way to encode input data. - $out = str_ireplace(array('&', '&', '&', '"', '"', '"', '"', '"', '/', '/', '/', '../'), '', $out); + $out = str_ireplace(array('&', '&', '&', '"', '"', '"', '"', '"', '/', '/', '\', '\', '/', '../', '..\\'), '', $out); } while ($oldstringtoclean != $out); // keep lines feed } @@ -768,9 +768,9 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = // Remove html tags $out = dol_html_entity_decode($out, ENT_COMPAT | ENT_HTML5, 'UTF-8'); // '"' is dangerous because param in url can close the href= or src= and add javascript functions. - // '../' is dangerous because it allows dir transversals + // '../' or '..\' is dangerous because it allows dir transversals // Note &, '&', '&'... is a simple char like '&' alone but there is no reason to accept such way to encode input data. - $out = str_ireplace(array('&', '&', '&', '"', '"', '"', '"', '"', '/', '/', '/', '../'), '', $out); + $out = str_ireplace(array('&', '&', '&', '"', '"', '"', '"', '"', '/', '/', '\', '\', '/', '../', '..\\'), '', $out); } while ($oldstringtoclean != $out); } break; diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index 87edca884e4..81eff830b49 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -349,7 +349,8 @@ class SecurityTest extends PHPUnit\Framework\TestCase $_POST["param1"]="333"; $_GET["param2"]='a/b#e(pr)qq-rr\cc'; $_GET["param3"]='"na/b#e(pr)qq-rr\cc'; // Same than param2 + " and n - $_GET["param4"]='../dir'; + $_GET["param4a"]='../../dir'; + $_GET["param4b"]='..\..\dirwindows'; $_GET["param5"]="a_1-b"; $_POST["param6"]="">assertEquals($result, 'na/b#e(pr)qq-rr\cc', 'Test on param3'); - $result=GETPOST("param4", 'alpha'); // Must return string sanitized from ../ + $result=GETPOST("param4a", 'alpha'); // Must return string sanitized from ../ print __METHOD__." result=".$result."\n"; $this->assertEquals($result, 'dir'); + $result=GETPOST("param4b", 'alpha'); // Must return string sanitized from ../ + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, 'dirwindows'); + // Test with aZ09 $result=GETPOST("param1", 'aZ09'); @@ -412,7 +417,11 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals($result, ''); - $result=GETPOST("param4", 'aZ09'); // Must return '' as string contains car not in aZ09 definition + $result=GETPOST("param4a", 'aZ09'); // Must return '' as string contains car not in aZ09 definition + print __METHOD__." result=".$result."\n"; + $this->assertEquals('', $result); + + $result=GETPOST("param4b", 'aZ09'); // Must return '' as string contains car not in aZ09 definition print __METHOD__." result=".$result."\n"; $this->assertEquals('', $result); From d46dfd017a9490eb6b6e0dfed24fb71a102262d8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Aug 2021 15:47:18 +0200 Subject: [PATCH 14/15] FIX #yogosha6944 Protection against traversal path. --- htdocs/core/lib/functions.lib.php | 8 ++++---- htdocs/document.php | 3 ++- test/phpunit/SecurityTest.php | 15 ++++++++++++--- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 3e6bcd9d5d1..4334aa9a12d 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -753,9 +753,9 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = $out = dol_string_nohtmltag($out, 0); // Remove also other dangerous string sequences // '"' is dangerous because param in url can close the href= or src= and add javascript functions. - // '../' is dangerous because it allows dir transversals + // '../' or '..\' is dangerous because it allows dir transversals // Note &, '&', '&'... is a simple char like '&' alone but there is no reason to accept such way to encode input data. - $out = str_ireplace(array('&', '&', '&', '"', '"', '"', '"', '"', '/', '/', '/', '../'), '', $out); + $out = str_ireplace(array('&', '&', '&', '"', '"', '"', '"', '"', '/', '/', '\', '\', '/', '../', '..\\'), '', $out); } while ($oldstringtoclean != $out); // keep lines feed } @@ -768,9 +768,9 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = // Remove html tags $out = dol_html_entity_decode($out, ENT_COMPAT | ENT_HTML5, 'UTF-8'); // '"' is dangerous because param in url can close the href= or src= and add javascript functions. - // '../' is dangerous because it allows dir transversals + // '../' or '..\' is dangerous because it allows dir transversals // Note &, '&', '&'... is a simple char like '&' alone but there is no reason to accept such way to encode input data. - $out = str_ireplace(array('&', '&', '&', '"', '"', '"', '"', '"', '/', '/', '/', '../'), '', $out); + $out = str_ireplace(array('&', '&', '&', '"', '"', '"', '"', '"', '/', '/', '\', '\', '/', '../', '..\\'), '', $out); } while ($oldstringtoclean != $out); } break; diff --git a/htdocs/document.php b/htdocs/document.php index 59501cc4701..046eb9b14bf 100644 --- a/htdocs/document.php +++ b/htdocs/document.php @@ -195,7 +195,8 @@ if (!in_array($type, array('text/x-javascript')) && !dolIsAllowedForPreview($ori } // Security: Delete string ../ into $original_file -$original_file = str_replace("../", "/", $original_file); +$original_file = str_replace('../', '/', $original_file); +$original_file = str_replace('..\\', '/', $original_file); // Find the subdirectory name as the reference $refname = basename(dirname($original_file)."/"); diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index 87edca884e4..81eff830b49 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -349,7 +349,8 @@ class SecurityTest extends PHPUnit\Framework\TestCase $_POST["param1"]="333"; $_GET["param2"]='a/b#e(pr)qq-rr\cc'; $_GET["param3"]='"na/b#e(pr)qq-rr\cc'; // Same than param2 + " and n - $_GET["param4"]='../dir'; + $_GET["param4a"]='../../dir'; + $_GET["param4b"]='..\..\dirwindows'; $_GET["param5"]="a_1-b"; $_POST["param6"]="">assertEquals($result, 'na/b#e(pr)qq-rr\cc', 'Test on param3'); - $result=GETPOST("param4", 'alpha'); // Must return string sanitized from ../ + $result=GETPOST("param4a", 'alpha'); // Must return string sanitized from ../ print __METHOD__." result=".$result."\n"; $this->assertEquals($result, 'dir'); + $result=GETPOST("param4b", 'alpha'); // Must return string sanitized from ../ + print __METHOD__." result=".$result."\n"; + $this->assertEquals($result, 'dirwindows'); + // Test with aZ09 $result=GETPOST("param1", 'aZ09'); @@ -412,7 +417,11 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals($result, ''); - $result=GETPOST("param4", 'aZ09'); // Must return '' as string contains car not in aZ09 definition + $result=GETPOST("param4a", 'aZ09'); // Must return '' as string contains car not in aZ09 definition + print __METHOD__." result=".$result."\n"; + $this->assertEquals('', $result); + + $result=GETPOST("param4b", 'aZ09'); // Must return '' as string contains car not in aZ09 definition print __METHOD__." result=".$result."\n"; $this->assertEquals('', $result); From edb239837c5b498430e82648121f05961714d66a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 23 Aug 2021 16:03:34 +0200 Subject: [PATCH 15/15] FIX #yogosha6944 Protection against traversal path. --- htdocs/document.php | 2 +- htdocs/viewimage.php | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/htdocs/document.php b/htdocs/document.php index 046eb9b14bf..3c06801c9a0 100644 --- a/htdocs/document.php +++ b/htdocs/document.php @@ -194,7 +194,7 @@ if (!in_array($type, array('text/x-javascript')) && !dolIsAllowedForPreview($ori $type = 'application/octet-stream'; } -// Security: Delete string ../ into $original_file +// Security: Delete string ../ or ..\ into $original_file $original_file = str_replace('../', '/', $original_file); $original_file = str_replace('..\\', '/', $original_file); diff --git a/htdocs/viewimage.php b/htdocs/viewimage.php index 9c584f5b8bb..f514c7c0302 100644 --- a/htdocs/viewimage.php +++ b/htdocs/viewimage.php @@ -221,8 +221,9 @@ if (preg_match('/\.noexe$/i', $original_file)) { accessforbidden('Error: Using the image wrapper to output a file ending with .noexe is not allowed.', 0, 0, 1); } -// Security: Delete string ../ into $original_file -$original_file = str_replace("../", "/", $original_file); +// Security: Delete string ../ or ..\ into $original_file +$original_file = str_replace('../', '/', $original_file); +$original_file = str_replace('..\\', '/', $original_file); // Find the subdirectory name as the reference $refname = basename(dirname($original_file)."/");