From 99fb08240376c647b11bbd708bcb4457377ee9d7 Mon Sep 17 00:00:00 2001 From: Atm-Gregr Date: Mon, 24 Jan 2022 14:50:54 +0100 Subject: [PATCH 1/7] prevent access denied page --- htdocs/core/lib/security.lib.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 3ea554a4a8f..b26c723a014 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -615,6 +615,9 @@ function checkUserAccessToObject($user, array $featuresarray, $objectid = 0, $ta if ($feature == 'task') { $feature = 'projet_task'; } + if ($feature == 'banque') { + $feature = 'fk_account@bank_account'; + } $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website'); // Test on entity only (Objects with no link to company) $checksoc = array('societe'); // Test for societe object From e3aae6d2e1343a905f34624368e59d377c0e7a3a Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Tue, 1 Mar 2022 10:50:22 +0100 Subject: [PATCH 2/7] FIX: object cloning: set unique extrafield values to null to prevent duplicates --- htdocs/core/class/commonobject.class.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index a4fc828ef4b..b2d5ac8e068 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -5307,8 +5307,15 @@ abstract class CommonObject $attributeLabel = $extrafields->attributes[$this->table_element]['label'][$attributeKey]; $attributeParam = $extrafields->attributes[$this->table_element]['param'][$attributeKey]; $attributeRequired = $extrafields->attributes[$this->table_element]['required'][$attributeKey]; + $attributeUnique = $extrafields->attributes[$this->table_element]['unique'][$attributeKey]; $attrfieldcomputed = $extrafields->attributes[$this->table_element]['computed'][$attributeKey]; + // If we clone, we have to clean unique extrafields to prevent duplicates. + // This behaviour can be prevented by external code by changing $this->context['createfromclone'] value in createFrom hook + if (! empty($this->context['createfromclone']) && $this->context['createfromclone'] == 'createfromclone' && ! empty($attributeUnique)) { + $new_array_options[$key] = null; + } + // Similar code than into insertExtraFields if ($attributeRequired) { From 53b185ce9c987f4dbd8b0aae80e380c8f78f8f17 Mon Sep 17 00:00:00 2001 From: Atm-Gregr Date: Mon, 4 Apr 2022 10:19:51 +0200 Subject: [PATCH 3/7] fix condition on remx --- htdocs/comm/remx.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/remx.php b/htdocs/comm/remx.php index f8a4c12fba7..1e3f56c30db 100644 --- a/htdocs/comm/remx.php +++ b/htdocs/comm/remx.php @@ -62,7 +62,7 @@ if (GETPOST('cancel', 'alpha') && !empty($backtopage)) { exit; } -if ($action == 'confirm_split' && GETPOST("confirm", "alpha") == 'yes' && $user->rights->societe->creer) { +if ($action == 'confirm_split' && GETPOST("confirm", "alpha") == 'yes' && ($user->rights->societe->creer || $user->rights->facture->creer)) { //if ($user->rights->societe->creer) //if ($user->rights->facture->creer) @@ -153,7 +153,7 @@ if ($action == 'confirm_split' && GETPOST("confirm", "alpha") == 'yes' && $user- } } -if ($action == 'setremise' && $user->rights->societe->creer) { +if ($action == 'setremise' && ($user->rights->societe->creer || $user->rights->facture->creer)) { //if ($user->rights->societe->creer) //if ($user->rights->facture->creer) @@ -192,7 +192,7 @@ if ($action == 'setremise' && $user->rights->societe->creer) { } } -if (GETPOST('action', 'aZ09') == 'confirm_remove' && GETPOST("confirm") == 'yes' && $user->rights->societe->creer) { +if (GETPOST('action', 'aZ09') == 'confirm_remove' && GETPOST("confirm") == 'yes' && ($user->rights->societe->creer || $user->rights->facture->creer)) { //if ($user->rights->societe->creer) //if ($user->rights->facture->creer) From 2009cc96e0e7d31a2e1cf3a422cd850a59112198 Mon Sep 17 00:00:00 2001 From: Atm-Gregr Date: Mon, 4 Apr 2022 10:21:06 +0200 Subject: [PATCH 4/7] clean branch --- htdocs/core/lib/security.lib.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index b26c723a014..3ea554a4a8f 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -615,9 +615,6 @@ function checkUserAccessToObject($user, array $featuresarray, $objectid = 0, $ta if ($feature == 'task') { $feature = 'projet_task'; } - if ($feature == 'banque') { - $feature = 'fk_account@bank_account'; - } $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website'); // Test on entity only (Objects with no link to company) $checksoc = array('societe'); // Test for societe object From 71012a7933bfd44570377563546c4135fa6451e8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 7 Mar 2022 13:21:32 +0100 Subject: [PATCH 5/7] FIX #19777 #20281 --- htdocs/compta/paiement/cheque/card.php | 50 ++++++++++++------- .../cheque/class/remisecheque.class.php | 1 + htdocs/core/class/html.formfile.class.php | 6 +-- .../modules/cheque/modules_chequereceipts.php | 3 +- htdocs/ecm/class/ecmfiles.class.php | 6 ++- 5 files changed, 41 insertions(+), 25 deletions(-) diff --git a/htdocs/compta/paiement/cheque/card.php b/htdocs/compta/paiement/cheque/card.php index 32f81532ecf..2fcd4d780ff 100644 --- a/htdocs/compta/paiement/cheque/card.php +++ b/htdocs/compta/paiement/cheque/card.php @@ -41,12 +41,7 @@ $ref = GETPOST('ref', 'alpha'); $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); -// Security check -$fieldname = (!empty($ref) ? 'ref' : 'rowid'); -if ($user->socid) { - $socid = $user->socid; -} -$result = restrictedArea($user, 'cheque', $id, 'bordereau_cheque', '', 'fk_user_author', $fieldname); +$object = new RemiseCheque($db); $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); @@ -63,11 +58,22 @@ if (empty($page) || $page == -1) { $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; $offset = $limit * $page; -$dir = $conf->bank->dir_output.'/checkdeposits/'; +$upload_dir = $conf->bank->multidir_output[$object->entity ? $object->entity : $conf->entity]."/checkdeposits"; + $filterdate = dol_mktime(0, 0, 0, GETPOST('fdmonth'), GETPOST('fdday'), GETPOST('fdyear')); $filteraccountid = GETPOST('accountid', 'int'); -$object = new RemiseCheque($db); +// Security check +$fieldname = (!empty($ref) ? 'ref' : 'rowid'); +if ($user->socid) { + $socid = $user->socid; +} +$result = restrictedArea($user, 'cheque', $id, 'bordereau_cheque', '', 'fk_user_author', $fieldname); + +$usercanread = $user->rights->banque->cheque; +$usercancreate = $user->rights->banque->cheque; +$usercandelete = $user->rights->banque->cheque; + /* @@ -242,7 +248,9 @@ if ($action == 'builddoc' && $user->rights->banque->cheque) { $langs->load("other"); - $file = $dir.get_exdir($object->ref, 0, 1, 0, $object, 'cheque').GETPOST('file'); + $filetodelete = GETPOST('file', 'alpha'); + $file = $upload_dir.'/'.$filetodelete; + $ret = dol_delete_file($file, 0, 0, 0, $object); if ($ret) { setEventMessages($langs->trans("FileWasRemoved", GETPOST('file')), null, 'mesgs'); @@ -633,6 +641,12 @@ if ($action == 'new') { $i = 1; if ($num > 0) { while ($objp = $db->fetch_object($resql)) { + $paymentstatic->id = $objp->pid; + $paymentstatic->ref = $objp->pref; + + $accountlinestatic->id = $objp->rowid; + $accountlinestatic->ref = $objp->ref; + print ''; print ''.$i.''; print ''.dol_print_date($db->jdate($objp->date), 'day').''; // Operation date @@ -642,8 +656,6 @@ if ($action == 'new') { print ''.price($objp->amount).''; // Link to payment print ''; - $paymentstatic->id = $objp->pid; - $paymentstatic->ref = $objp->pref; if ($paymentstatic->id) { print $paymentstatic->getNomUrl(1); } else { @@ -652,8 +664,6 @@ if ($action == 'new') { print ''; // Link to bank transaction print ''; - $accountlinestatic->id = $objp->rowid; - $accountlinestatic->ref = $objp->ref; if ($accountlinestatic->id > 0) { print $accountlinestatic->getNomUrl(1); } else { @@ -663,10 +673,10 @@ if ($action == 'new') { // Action button print ''; if ($object->statut == 0) { - print 'rowid.'">'.img_delete().''; + print 'rowid.'">'.img_delete().''; } if ($object->statut == 1 && $objp->statut != 2) { - print 'rowid.'">'.img_picto($langs->trans("RejectCheck"), 'disable').''; + print 'rowid.'">'.img_picto($langs->trans("RejectCheck"), 'disable').''; } if ($objp->statut == 2) { print '   '.img_picto($langs->trans('CheckRejected'), 'statut8').''; @@ -722,11 +732,13 @@ print ''; if ($action != 'new') { if ($object->statut == 1) { - $filename = dol_sanitizeFileName($object->ref); - $filedir = $dir.get_exdir($object->ref, 0, 1, 0, $object, 'checkdeposits'); + // Documents + $objref = dol_sanitizeFileName($object->ref); + $filedir = $upload_dir.'/'.$objref; $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; - - print $formfile->showdocuments('remisecheque', $filename, $filedir, $urlsource, 1, 1); + $genallowed = $usercancreate; + $delallowed = $usercandelete; + print $formfile->showdocuments('remisecheque', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang); print '
'; } diff --git a/htdocs/compta/paiement/cheque/class/remisecheque.class.php b/htdocs/compta/paiement/cheque/class/remisecheque.class.php index 683b2fd0423..559697bf495 100644 --- a/htdocs/compta/paiement/cheque/class/remisecheque.class.php +++ b/htdocs/compta/paiement/cheque/class/remisecheque.class.php @@ -615,6 +615,7 @@ class RemiseCheque extends CommonObject // We save charset_output to restore it because write_file can change it if needed for // output format that does not support UTF8. $sav_charseSupprimert_output = $outputlangs->charset_output; + $result = $docmodel->write_file($this, $conf->bank->dir_output.'/checkdeposits', $this->ref, $outputlangs); if ($result > 0) { //$outputlangs->charset_output=$sav_charset_output; diff --git a/htdocs/core/class/html.formfile.class.php b/htdocs/core/class/html.formfile.class.php index fcca60dad78..349b05416aa 100644 --- a/htdocs/core/class/html.formfile.class.php +++ b/htdocs/core/class/html.formfile.class.php @@ -359,9 +359,9 @@ class FormFile * Return a string to show the box with list of available documents for object. * This also set the property $this->numoffiles * - * @param string $modulepart Module the files are related to ('propal', 'facture', 'facture_fourn', 'mymodule', 'mymodule:myobject', 'mymodule_temp', ...) - * @param string $modulesubdir Existing (so sanitized) sub-directory to scan (Example: '0/1/10', 'FA/DD/MM/YY/9999'). Use '' if file is not into subdir of module. - * @param string $filedir Directory to scan + * @param string $modulepart Module the files are related to ('propal', 'facture', 'facture_fourn', 'mymodule', 'mymodule:MyObject', 'mymodule_temp', ...) + * @param string $modulesubdir Existing (so sanitized) sub-directory to scan (Example: '0/1/10', 'FA/DD/MM/YY/9999'). Use '' if file is not into a subdir of module. + * @param string $filedir Directory to scan (must not end with a /). Example: '/mydolibarrdocuments/facture/FAYYMM-1234' * @param string $urlsource Url of origin page (for return) * @param int|string[] $genallowed Generation is allowed (1/0 or array list of templates) * @param int $delallowed Remove is allowed (1/0) diff --git a/htdocs/core/modules/cheque/modules_chequereceipts.php b/htdocs/core/modules/cheque/modules_chequereceipts.php index dfdf0fbe363..e50a6877848 100644 --- a/htdocs/core/modules/cheque/modules_chequereceipts.php +++ b/htdocs/core/modules/cheque/modules_chequereceipts.php @@ -126,8 +126,7 @@ abstract class ModeleNumRefChequeReceipts } /** - * \class ModeleChequeReceipts - * \brief Classe mere des modeles de + * Class parent for templates of document generation */ abstract class ModeleChequeReceipts extends CommonDocGenerator { diff --git a/htdocs/ecm/class/ecmfiles.class.php b/htdocs/ecm/class/ecmfiles.class.php index 035a7aee9c6..a451a462ea3 100644 --- a/htdocs/ecm/class/ecmfiles.class.php +++ b/htdocs/ecm/class/ecmfiles.class.php @@ -327,7 +327,11 @@ class EcmFiles extends CommonObject $resql = $this->db->query($sql); if (!$resql) { $error++; - $this->errors[] = 'Error '.$this->db->lasterror(); + if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { + $this->errors[] = 'Error DB_ERROR_RECORD_ALREADY_EXISTS : '.$this->db->lasterror(); + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + } dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR); } From b199234afe1d9c7371a6ce35c789a95b0fee1893 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Tue, 5 Apr 2022 12:01:09 +0200 Subject: [PATCH 6/7] FIX : each time we create a supplier order, we need to give it a ref_supplier --- htdocs/fourn/commande/list.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/htdocs/fourn/commande/list.php b/htdocs/fourn/commande/list.php index de195504d39..56ebfb5cbf7 100644 --- a/htdocs/fourn/commande/list.php +++ b/htdocs/fourn/commande/list.php @@ -292,10 +292,8 @@ if (empty($reshook)) { $objecttmp->mode_reglement_id = $cmd->mode_reglement_id; $objecttmp->fk_project = $cmd->fk_project; $objecttmp->multicurrency_code = $cmd->multicurrency_code; - if (empty($createbills_onebythird)) { - $objecttmp->ref_supplier = !empty($cmd->ref_supplier) ? $cmd->ref_supplier : $default_ref_supplier; - $default_ref_supplier+=1; - } + $objecttmp->ref_supplier = !empty($cmd->ref_supplier) ? $cmd->ref_supplier : $default_ref_supplier; + $default_ref_supplier+=1; $datefacture = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); if (empty($datefacture)) { From c3ae63f587f76670c113746f0d2f1e62b129548a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 6 Apr 2022 11:34:49 +0200 Subject: [PATCH 7/7] FIX out of memory when more than 100 000 invoices. --- htdocs/compta/facture/list.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index ccf3c2f3f0c..f2cc5943e7a 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -757,12 +757,28 @@ $sql .= ' f.rowid DESC '; $nbtotalofrecords = ''; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { + /* This old and fast method to get and count full list returns all record so use a high amount of memory. $result = $db->query($sql); $nbtotalofrecords = $db->num_rows($result); - if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 + */ + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + if ($sall || $search_product_category > 0 || $search_user > 0) { + $sqlforcount = preg_replace('/^SELECT[a-zA-Z0-9\._\s\(\),=<>\:\-\']+\sFROM/', 'SELECT COUNT(DISTINCT f.rowid) as nbtotalofrecords FROM', $sql); + } else { + $sqlforcount = preg_replace('/^SELECT[a-zA-Z0-9\._\s\(\),=<>\:\-\']+\sFROM/', 'SELECT COUNT(f.rowid) as nbtotalofrecords FROM', $sql); + $sqlforcount = preg_replace('/LEFT JOIN '.MAIN_DB_PREFIX.'paiement_facture as pf ON pf.fk_facture = f.rowid/', '', $sqlforcount); + } + $sqlforcount = preg_replace('/GROUP BY.*$/', '', $sqlforcount); + + $resql = $db->query($sqlforcount); + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + + if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 $page = 0; $offset = 0; } + $db->free($resql); } $sql .= $db->plimit($limit + 1, $offset);