diff --git a/ChangeLog b/ChangeLog index b6d139108ee..3c52f18a9e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,109 @@ English Dolibarr ChangeLog -------------------------------------------------------------- +***** ChangeLog for 20.0.4 compared to 20.0.3 ***** +FIX: $this->origin_object can not be instance of CommandeFournisseur if it is already an instanceof CommonObject +FIX: 17.0 API endpoints "PUT": prevent overwriting all extrafields if only some are supplied in the request cf. PR #29237 +FIX: 17.0 - collisions in cache for dol_getIdFromCode +FIX: #18713 +FIX: 20.0 - PHP8 fatal when creating a reception unless corresponding PDF model is enabled +FIX: #21294 Stock import sql query +FIX: #26250 fatal error on kit +FIX: #28702 +FIX: #29624 - substitution of __DATE_DELIVERY__ +FIX: #32113 +FIX: #32186 +FIX: #32339 Delete a loan settlement is partial +FIX: #32387 +FIX: #32477 Loan - Insurance amount need decimals +FIX: #32611 +FIX: #32736 + avoid php warning +FIX: #32743 +FIX: #32765 JS Error: Uncaught TypeError +FIX: #32801 VAT type is inverted in form VAT selector +FIX: #32840 +FIX: #32843 +FIX: #32880 - Tags are using a special rendering. +FIX: add other fields +FIX: autofill price with multicurrency on supplier doc +FIX: avoid phan error +FIX: avoid php8 warnings +FIX: avoid warning with the new Dolistore website +FIX: backport from develop to avoid php warning +FIX: Bad calculation of the theoretical stock. Did not take into account +FIX: bad dispatched quantities for batches on shipment card +FIX: Brian is in the kitchen +FIX: broken feature, compatibility with "Default search filters" +FIX: broken feature with check $pa_ht_isemptystring +FIX: Bug on select user on time.php (all project list) +FIX: can not delete files in task card +FIX: Check "$search_sale" only if it's an internal user +FIX: clean unique extrafields when create product combination +FIX: code not visible correctly into view of dictionary +FIX: compatibility between next_prev_filter and hook return +FIX: compatibility with multicompany +FIX: Complete path was started in #17243 for pdf_cannelle +FIX: Continue for eagle_proforma +FIX: country id is not saved when we provide country_code only +FIX: #CVE-2024-34051 +FIX: delete supplier order when at least one line linked to customer order line +FIX: display error when loan can't be deleted +FIX: display full tree on shipment card when a kit contains a same component in other sub-kit +FIX: DROP INDEX IF EXISTS is not possible ! +FIX: extrafields lost during creation from rec invoice +FIX: FEC import +FIX: Fiscal year - missing translation on status +FIX: Fix return value of hook sendMail when hook return -1 who must be return false in sendfile() function +FIX: GETPOST('private_message') +FIX: glob is better for search files with wildcard + avoid warning +FIX: if $force_entity = 0 ($force_entity != 'default') = false +FIX: Loan - Insurance amount need decimals +FIX: Many status on invoice linked object block +FIX: merge problem +FIX: missing company name if donation is linked to third party +FIX: missing default values if $objsrc or $soc fields are empty +FIX: missing edit extrafields inline for member card +FIX: missing quick edit for extrafields +FIX: more bugs and warnings +FIX: Multilangs : PDF lines description +FIX: Must not have both thirdparty and member. +FIX: ODT substitution when many HTML tags in string +FIX: on the road again +FIX: pdf_cannelle (supplier_invoice) add background - Complete #17243 +FIX: Prices didn't update when clone a propale with update prices +FIX: product variants copy: also copy multiprice variations +FIX: refactorize (maybe broken feature for not received completely) +FIX: remove debug trace +FIX: remove socid when cloning a project without third parties +FIX: removes traces of <<"rpmbuild", "RPM_MANDRIVA"=>"rpmbuild", "RPM_OPENSUSE"=>"rpmbuild", -"DEB"=>"dpkg", +"DEB"=>"dpkg,po2debconf", # need also debhelper "FLATPACK"=>"flatpack", "EXEDOLIWAMP"=>"ISCC.exe", "SNAPSHOT"=>"tar" @@ -85,8 +85,9 @@ if (! $ENV{"DESTIBETARC"} || ! $ENV{"DESTISTABLE"}) print "set DESTIBETARC=c:/tmp\n"; print "set DESTISTABLE=c:/tmp\n"; print "\n"; - print "Example: DESTIBETARC='/media/HDDATA1_LD/Mes Sites/Web/Dolibarr/dolibarr.org/files/lastbuild'\n"; - print "Example: DESTISTABLE='/media/HDDATA1_LD/Mes Sites/Web/Dolibarr/dolibarr.org/files/stable'\n"; + print "Example in .bashrc:\n"; + print "export DESTIBETARC='/mnt/HDDATA1_LD/Mes Archives/Doli/dolibarr/lastbuild'\n"; + print "export DESTISTABLE='/mnt/HDDATA1_LD/Mes Archives/Doli/dolibarr/stable'\n"; sleep 2; exit 1; } diff --git a/htdocs/accountancy/class/accountancyexport.class.php b/htdocs/accountancy/class/accountancyexport.class.php index 40315b46433..cc093ca77b6 100644 --- a/htdocs/accountancy/class/accountancyexport.class.php +++ b/htdocs/accountancy/class/accountancyexport.class.php @@ -1000,7 +1000,7 @@ class AccountancyExport // We need to keep the 10 latest number of invoices doc_ref not the beginning part that is the useless almost same part // $tab['num_piece3'] = str_pad(self::trunc($line->piece_num, 10), 10); - $tab['num_piece3'] = substr(self::trunc($line->doc_ref, 20), -10); + $tab['num_piece3'] = str_pad(substr(self::trunc($line->doc_ref, 20), -10), 10); $tab['reserved'] = str_repeat(' ', 10); // position 159 $tab['currency_amount'] = str_repeat(' ', 13); // position 169 // get document file diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index b4bc00f68ca..ef0a83fa579 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -614,7 +614,7 @@ if ($mode == 'common' || $mode == 'commonkanban') { if ($nbmodulesnotautoenabled <= getDolGlobalInt('MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING', 1)) { // If only minimal initial modules enabled $deschelp .= '
'.$desc."
\n"; } - if (getDolGlobalString('MAIN_SETUP_MODULES_INFO')) { // Show a custom message + if (getDolGlobalString('MAIN_SETUP_MODULES_INFO')) { // Show a custom message. A good usage for SaaS with option MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING. $deschelp .= '
'.$langs->trans(getDolGlobalString('MAIN_SETUP_MODULES_INFO'))."
\n"; } if ($deschelp) { diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 1099a9d0ff7..9952525b258 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -292,7 +292,7 @@ class BOM extends CommonObject * @param int $notrigger false=launch triggers after, true=disable triggers * @return int Return integer <0 if KO, Id of created object if OK */ - public function create(User $user, $notrigger = 1) + public function create(User $user, $notrigger = 0) { if ($this->efficiency <= 0 || $this->efficiency > 1) { $this->efficiency = 1; @@ -546,7 +546,7 @@ class BOM extends CommonObject * @param int $notrigger 0=launch triggers after, 1=disable triggers * @return int Return integer <0 if KO, >0 if OK */ - public function update(User $user, $notrigger = 1) + public function update(User $user, $notrigger = 0) { if ($this->efficiency <= 0 || $this->efficiency > 1) { $this->efficiency = 1; diff --git a/htdocs/comm/action/list.php b/htdocs/comm/action/list.php index ca2868bcf0b..114ea6e4963 100644 --- a/htdocs/comm/action/list.php +++ b/htdocs/comm/action/list.php @@ -461,6 +461,12 @@ if ($filtert > 0 || $usergroup > 0) { if ($usergroup > 0) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."usergroup_user as ugu ON ugu.fk_user = ar.fk_element"; } + +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + $sql .= " WHERE a.entity IN (".getEntity('agenda').")"; // Condition on actioncode if (!empty($actioncode)) { diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index a9a84415f4b..b343affbd48 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1922,7 +1922,7 @@ if ($action == 'create') { if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE')) { $warehouse_id = getDolGlobalString('MAIN_DEFAULT_WAREHOUSE'); } - if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER') && !empty($user->warehouse_id)) { + if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER') && !empty($user->fk_warehouse)) { $warehouse_id = $user->fk_warehouse; } } diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 586eb8bcbaa..db21f28fd8a 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1836,7 +1836,7 @@ if ($action == 'create' && $usercancreate) { if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE')) { $warehouse_id = getDolGlobalString('MAIN_DEFAULT_WAREHOUSE'); } - if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER') && !empty($user->warehouse_id)) { + if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE_USER') && !empty($user->fk_warehouse)) { $warehouse_id = $user->fk_warehouse; } } diff --git a/htdocs/compta/bank/class/paymentvarious.class.php b/htdocs/compta/bank/class/paymentvarious.class.php index c42bc942479..1a2bfe8076e 100644 --- a/htdocs/compta/bank/class/paymentvarious.class.php +++ b/htdocs/compta/bank/class/paymentvarious.class.php @@ -767,7 +767,7 @@ class PaymentVarious extends CommonObject */ public function info($id) { - $sql = 'SELECT v.rowid, v.datec, v.fk_user_author'; + $sql = 'SELECT v.rowid, v.datec, v.fk_user_author, fk_user_modif, tms'; $sql .= ' FROM '.MAIN_DB_PREFIX.'payment_various as v'; $sql .= ' WHERE v.rowid = '.((int) $id); @@ -780,6 +780,7 @@ class PaymentVarious extends CommonObject $this->id = $obj->rowid; $this->user_creation = $obj->fk_user_author; + $this->user_creation_id = $obj->fk_user_author; $this->user_modification_id = $obj->fk_user_modif; $this->date_creation = $this->db->jdate($obj->datec); $this->date_modification = $this->db->jdate($obj->tms); diff --git a/htdocs/compta/bank/various_payment/document.php b/htdocs/compta/bank/various_payment/document.php index 7c717d7ede0..3ee2fbd77e9 100644 --- a/htdocs/compta/bank/various_payment/document.php +++ b/htdocs/compta/bank/various_payment/document.php @@ -129,7 +129,7 @@ if ($object->id) { $morehtmlref .= ''; $linkback = ''.$langs->trans("BackToList").''; - $morehtmlstatus = $morehtmlright; + $morehtmlstatus = ''; dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'ref', $morehtmlref, '', 0, '', $morehtmlstatus); print '
'; diff --git a/htdocs/compta/facture/card-rec.php b/htdocs/compta/facture/card-rec.php index 8e996becd5c..94405e1ad8e 100644 --- a/htdocs/compta/facture/card-rec.php +++ b/htdocs/compta/facture/card-rec.php @@ -145,10 +145,14 @@ $result = restrictedArea($user, 'facture', $object->id, $objecttype); /* * Actions */ - if (GETPOST('cancel', 'alpha')) { - $action = 'list'; - $massaction = ''; + if ($action != 'updateline') { + $action = 'list'; + $massaction = ''; + } else { + $action = ''; + $cancel = ''; + } } if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index cc0460ffead..2df00a8f637 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -2006,7 +2006,7 @@ if (empty($reshook)) { $line->fk_prev_id = $line->id; $line->fetch_optionals(); if (getDolGlobalInt('INVOICE_USE_SITUATION') == 2) { - $line->situation_percent = $line->get_allprev_progress($object->id);; // get good progress including credit note + $line->situation_percent = 0; // New situation percent must be 0 (No cumulative) } else { $line->situation_percent = $line->get_prev_progress($object->id); // get good progress including credit note } diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 361a1c03013..9772c590d85 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -2496,10 +2496,12 @@ class Facture extends CommonInvoice if (isset($this->retained_warranty)) { $this->retained_warranty = (float) $this->retained_warranty; } - - - // Check parameters - // Put here code to add control on parameters values + if (!isset($this->user_creation_id) && isset($this->fk_user_author) ) { + $this->user_creation_id = $this->fk_user_author; + } + if (!isset($this->user_validation_id) && isset($this->fk_user_valid) ) { + $this->user_validation_id = $this->fk_user_valid; + } // Update request $sql = "UPDATE ".MAIN_DB_PREFIX."facture SET"; @@ -2524,7 +2526,8 @@ class Facture extends CommonInvoice $sql .= " total_ttc=".(isset($this->total_ttc) ? (float) $this->total_ttc : "null").","; $sql .= " revenuestamp=".((isset($this->revenuestamp) && $this->revenuestamp != '') ? (float) $this->revenuestamp : "null").","; $sql .= " fk_statut=".(isset($this->status) ? (int) $this->status : "null").","; - $sql .= " fk_user_valid=".(isset($this->fk_user_valid) ? (int) $this->fk_user_valid : "null").","; + $sql .= " fk_user_author=".(isset($this->user_creation_id) ? ((int) $this->user_creation_id) : "null").","; + $sql .= " fk_user_valid=".(isset($this->user_validation_id) ? (int) $this->user_validation_id : "null").","; $sql .= " fk_facture_source=".(isset($this->fk_facture_source) ? (int) $this->fk_facture_source : "null").","; $sql .= " fk_projet=".(isset($this->fk_project) ? (int) $this->fk_project : "null").","; $sql .= " fk_cond_reglement=".(isset($this->cond_reglement_id) ? (int) $this->cond_reglement_id : "null").","; @@ -3871,7 +3874,12 @@ class Facture extends CommonInvoice $fk_prev_id = 'null'; } if (!isset($situation_percent) || $situation_percent > 100 || (string) $situation_percent == '' || $situation_percent == null) { - $situation_percent = 100; + // INVOICE_USE_SITUATION = 2 - Lines situation percent on new lines must be 0 (No cumulative) + if ($this->type == Facture::TYPE_SITUATION && getDolGlobalInt('INVOICE_USE_SITUATION') == 2 && (int) $situation_percent < 100) { + $situation_percent = 0; + } else { + $situation_percent = 100; + } } if (empty($ref_ext)) { $ref_ext = ''; @@ -5061,11 +5069,12 @@ class Facture extends CommonInvoice //Avoid php warning Warning: mt_rand(): max(0) is smaller than min(1) when no product exists if (empty($num_prods)) { $num_prods = 1; + $prodids[$num_prods] = 1; } // Initialize parameters $this->id = 0; - $this->entity = 1; + $this->entity = $conf->entity; $this->ref = 'SPECIMEN'; $this->specimen = 1; $this->socid = 1; diff --git a/htdocs/compta/stats/supplier_turnover_by_thirdparty.php b/htdocs/compta/stats/supplier_turnover_by_thirdparty.php index 367666b0692..1c21c1e2303 100644 --- a/htdocs/compta/stats/supplier_turnover_by_thirdparty.php +++ b/htdocs/compta/stats/supplier_turnover_by_thirdparty.php @@ -1,6 +1,7 @@ - * Copyright (C) 2023 Ferran Marcet +/* Copyright (C) 2020 Maxime Kohlhaas + * Copyright (C) 2023 Ferran Marcet + * Copyright (C) 2025 Alexandre Spangaro * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -56,11 +57,25 @@ $socid = GETPOSTINT('socid'); // Category $selected_cat = GETPOSTINT('search_categ'); +if ($selected_cat == -1) { + $selected_cat = 0; +} $subcat = false; if (GETPOST('subcat', 'alpha') === 'yes') { $subcat = true; } +// Security check +if ($user->socid > 0) { + $socid = $user->socid; +} +if (isModEnabled('comptabilite')) { + $result = restrictedArea($user, 'compta', '', '', 'resultat'); +} +if (isModEnabled('accounting')) { + $result = restrictedArea($user, 'accounting', '', '', 'comptarapport'); +} + // Hook $hookmanager->initHooks(array('supplierturnoverbythirdpartylist')); @@ -148,12 +163,24 @@ $commonparams['sortorder'] = $sortorder; $commonparams['sortfield'] = $sortfield; $headerparams = array(); -$headerparams['date_startyear'] = $date_startyear; -$headerparams['date_startmonth'] = $date_startmonth; -$headerparams['date_startday'] = $date_startday; -$headerparams['date_endyear'] = $date_endyear; -$headerparams['date_endmonth'] = $date_endmonth; -$headerparams['date_endday'] = $date_endday; +if (!empty($date_startyear)) { + $headerparams['date_startyear'] = $date_startyear; +} +if (!empty($date_startmonth)) { + $headerparams['date_startmonth'] = $date_startmonth; +} +if (!empty($date_startday)) { + $headerparams['date_startday'] = $date_startday; +} +if (!empty($date_endyear)) { + $headerparams['date_endyear'] = $date_endyear; +} +if (!empty($date_endmonth)) { + $headerparams['date_endmonth'] = $date_endmonth; +} +if (!empty($date_endday)) { + $headerparams['date_endday'] = $date_endday; +} $tableparams = array(); $tableparams['search_categ'] = $selected_cat; @@ -173,16 +200,7 @@ foreach ($allparams as $key => $value) { $paramslink .= '&'.$key.'='.$value; } -// Security check -if ($user->socid > 0) { - $socid = $user->socid; -} -if (isModEnabled('comptabilite')) { - $result = restrictedArea($user, 'compta', '', '', 'resultat'); -} -if (isModEnabled('accounting')) { - $result = restrictedArea($user, 'accounting', '', '', 'comptarapport'); -} + /* @@ -203,6 +221,9 @@ if ($modecompta == "BOOKKEEPINGCOLLECTED") { $modecompta = "RECETTES-DEPENSES"; } +$namelink = ''; +$builddate = dol_now(); + // Show report header if ($modecompta == "CREANCES-DETTES") { $name = $langs->trans("PurchaseTurnover").', '.$langs->trans("ByThirdParties"); @@ -223,7 +244,6 @@ if ($modecompta == "CREANCES-DETTES") { // TODO } -$builddate = dol_now(); $period = $form->selectDate($date_start, 'date_start', 0, 0, 0, '', 1, 0, 0, '', '', '', '', 1, '', '', 'tzserver'); $period .= ' - '; $period .= $form->selectDate($date_end, 'date_end', 0, 0, 0, '', 1, 0, 0, '', '', '', '', 1, '', '', 'tzserver'); @@ -235,7 +255,7 @@ if ($date_end == dol_time_plus_duree($date_start, 1, 'y') - 1) { $exportlink = ''; -report_header($name, '', $period, $periodlink, $description, $builddate, $exportlink, $tableparams, $calcmode); +report_header($name, $namelink, $period, $periodlink, $description, $builddate, $exportlink, $tableparams, $calcmode); if (isModEnabled('accounting')) { if ($modecompta != 'BOOKKEEPING') { diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index 4a2fa3fb219..2a871d7a486 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -395,10 +395,6 @@ $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; -$sql .= $db->order($sortfield, $sortorder); - -//print $sql; - // Count total nb of records $nbtotalofrecords = ''; if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { @@ -410,7 +406,7 @@ if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { } } -// Complete request and execute it with limit +// Complete request and execute it with order and limit $sql .= $db->order($sortfield, $sortorder); if ($limit) { $sql .= $db->plimit($limit + 1, $offset); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index e6198c8bb6e..63cde541d60 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -701,7 +701,7 @@ abstract class CommonObject public $user_creation; /** - * @var int User id author/creation + * @var int|null User id author/creation */ public $user_creation_id; @@ -5487,16 +5487,12 @@ abstract class CommonObject } $this->tpl['label'] .= $discount->getNomUrl(0, 'discount'); } elseif (!empty($line->fk_product)) { - $productstatic = new Product($this->db); - $productstatic->id = $line->fk_product; - $productstatic->ref = $line->ref; - $productstatic->type = $line->fk_product_type; - if (empty($productstatic->ref)) { + if (empty($line->product)) { $line->fetch_product(); - $productstatic = $line->product; } + $productstatic = $line->product; - $this->tpl['label'] .= $productstatic->getNomUrl(1); + $this->tpl['label'] .= (is_object($productstatic) ? $productstatic->getNomUrl(1) : $line->ref); $this->tpl['label'] .= ' - '.(!empty($line->label) ? $line->label : $line->product_label); // Dates if ($line->product_type == 1 && ($date_start || $date_end)) { @@ -10059,9 +10055,9 @@ abstract class CommonObject /** * Create object in the database * - * @param User $user User that creates - * @param int<0,1> $notrigger 0=launch triggers after, 1=disable triggers - * @return int<-1,max> Return integer <0 if KO, Id of created object if OK + * @param User $user User that creates + * @param int<0,1> $notrigger 0=launch triggers after, 1=disable triggers + * @return int<-1,max> Return integer <0 if KO, Id of created object if OK */ public function createCommon(User $user, $notrigger = 0) { @@ -10080,6 +10076,7 @@ abstract class CommonObject if (array_key_exists('date_creation', $fieldvalues) && empty($fieldvalues['date_creation'])) { $fieldvalues['date_creation'] = $this->db->idate($now); } + // For backward compatibility, if a property ->fk_user_creat exists and not filled. if (array_key_exists('fk_user_creat', $fieldvalues) && !($fieldvalues['fk_user_creat'] > 0)) { $fieldvalues['fk_user_creat'] = $user->id; $this->fk_user_creat = $user->id; diff --git a/htdocs/core/class/fileupload.class.php b/htdocs/core/class/fileupload.class.php index 686bc3566d0..3096985cc49 100644 --- a/htdocs/core/class/fileupload.class.php +++ b/htdocs/core/class/fileupload.class.php @@ -58,8 +58,11 @@ class FileUpload $this->element = $element; $pathname = str_replace('/class', '', $element_prop['classpath']); + + $filename = dol_sanitizeFileName($element_prop['classfile']); $dir_output = dol_sanitizePathName($element_prop['dir_output']); + $savingDocMask = ''; //print 'fileupload.class.php: element='.$element.' pathname='.$pathname.' filename='.$filename.' dir_output='.$dir_output."\n"; @@ -75,6 +78,11 @@ class FileUpload $object_ref = dol_sanitizeFileName($object->ref); + // add object reference as file name prefix if const MAIN_DISABLE_SUGGEST_REF_AS_PREFIX is not enabled + if (!getDolGlobalInt('MAIN_DISABLE_SUGGEST_REF_AS_PREFIX')) { + $savingDocMask = $object_ref.'-__file__'; + } + // Special cases to forge $object_ref used to forge $upload_dir if ($element == 'invoice_supplier') { $object_ref = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier').$object_ref; @@ -100,6 +108,7 @@ class FileUpload 'script_url' => $_SERVER['PHP_SELF'], 'upload_dir' => $dir_output.'/'.$object_ref.'/', 'upload_url' => DOL_URL_ROOT.'/document.php?modulepart='.$element.'&attachment=1&file=/'.$object_ref.'/', + 'saving_doc_mask' => $savingDocMask, 'param_name' => 'files', // Set the following option to 'POST', if your server does not support // DELETE requests. This is a parameter sent to the client: @@ -425,6 +434,14 @@ class FileUpload if ($validate) { if (dol_mkdir($this->options['upload_dir']) >= 0) { + // add object reference as file name prefix if const MAIN_DISABLE_SUGGEST_REF_AS_PREFIX is not enabled + $fileNameWithoutExt = preg_replace('/\.[^\.]+$/', '', $file->name); + $savingDocMask = $this->options['saving_doc_mask']; + if ($savingDocMask && strpos($savingDocMask, $fileNameWithoutExt) !== 0) { + $fileNameWithPrefix = preg_replace('/__file__/', $file->name, $savingDocMask); + $file->name = $fileNameWithPrefix; + } + $file_path = dol_sanitizePathName($this->options['upload_dir']).dol_sanitizeFileName($file->name); $append_file = !$this->options['discard_aborted_uploads'] && dol_is_file($file_path) && $file->size > dol_filesize($file_path); diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index a72d7dbd176..0148b7e250a 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4596,7 +4596,7 @@ class Form if (depositPercent.length > 0) { $("#' . $htmlname . '_deposit_percent_container").show().find("#' . $htmlname . '_deposit_percent").val(depositPercent); } else { - $("#' . $htmlname . '_deposit_percent_container").hide(); + $("#' . $htmlname . '_deposit_percent_container").hide().find("#' . $htmlname . '_deposit_percent").val(0); } return true; diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 24d223c02cc..6f1fe961852 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -3296,7 +3296,7 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, } elseif (isModEnabled("service")) { $original_file = $conf->service->multidir_output[$entity].'/'.$original_file; } - } elseif ($modulepart == 'product_batch' || $modulepart == 'produitlot') { + } elseif ($modulepart == 'product_batch' || $modulepart == 'productlot') { // Wrapping pour les lots produits if (empty($entity) || (empty($conf->productbatch->multidir_output[$entity]))) { return array('accessallowed' => 0, 'error' => 'Value entity must be provided'); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index cb6b009f99f..95f69e8e3fe 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -13502,7 +13502,7 @@ function forgeSQLFromUniversalSearchCriteria($filter, &$errorstr = '', $noand = $ret = ($noand ? "" : " AND ").($nopar ? "" : '(').preg_replace_callback('/'.$regexstring.'/i', 'dolForgeCriteriaCallback', $filter).($nopar ? "" : ')'); if (is_object($db)) { - $ret = str_replace('__NOW__', $db->idate(dol_now()), $ret); + $ret = str_replace('__NOW__', "'".$db->idate(dol_now())."'", $ret); } if (is_object($user)) { $ret = str_replace('__USER_ID__', (string) $user->id, $ret); @@ -13733,8 +13733,10 @@ function dolForgeCriteriaCallback($matches) $tmpescaped = 'NULL'; } elseif (is_int($tmpescaped)) { $tmpescaped = (int) $tmpescaped; - } else { + } elseif (is_numeric((string) $tmpescaped)) { // it can be a float with a . $tmpescaped = (float) $tmpescaped; + } else { + $tmpescaped = preg_replace('/[^a-z0-9_]/i', '', $tmpescaped); // it can be a name of field or a substitution variable like '__NOW__' } } diff --git a/htdocs/core/lib/signature.lib.php b/htdocs/core/lib/signature.lib.php index 4c2e13693ec..d07b2a410f2 100644 --- a/htdocs/core/lib/signature.lib.php +++ b/htdocs/core/lib/signature.lib.php @@ -176,7 +176,7 @@ function getOnlineSignatureUrl($mode, $type, $ref = '', $localorexternal = 1, $o if ($mode == 1) { $out .= "hash('".$securekeyseed."' + '".$type."' + $type + '_ref)"; } else { - $out .= '&securekey='.dol_hash($securekeyseed.$type.$ref.(!isModEnabled('multicompany') ? '' : $object->entity), '0'); + $out .= '&securekey='.dol_hash($securekeyseed.$type.$ref.(!isModEnabled('multicompany') ? '' : $obj->entity), '0'); } } diff --git a/htdocs/core/modules/modAdherent.class.php b/htdocs/core/modules/modAdherent.class.php index 51dd74cc117..2445000cee1 100644 --- a/htdocs/core/modules/modAdherent.class.php +++ b/htdocs/core/modules/modAdherent.class.php @@ -182,7 +182,7 @@ class modAdherent extends DolibarrModules $this->const[$r][0] = "MEMBER_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/members"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/members"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -438,8 +438,8 @@ class modAdherent extends DolibarrModules // ODT template /* - $src=DOL_DOCUMENT_ROOT.'/install/doctemplates/orders/template_order.odt'; - $dirodt=DOL_DATA_ROOT.'/doctemplates/orders'; + $src=DOL_DOCUMENT_ROOT.'/install/doctemplates/members/template_member.odt'; + $dirodt=DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/members'; $dest=$dirodt.'/template_order.odt'; if (file_exists($src) && ! file_exists($dest)) { diff --git a/htdocs/core/modules/modBom.class.php b/htdocs/core/modules/modBom.class.php index c08828442c9..748332a744c 100644 --- a/htdocs/core/modules/modBom.class.php +++ b/htdocs/core/modules/modBom.class.php @@ -127,7 +127,7 @@ class modBom extends DolibarrModules $this->const = array( 1 => array('BOM_ADDON_PDF', 'chaine', 'generic_bom_odt', 'Name of PDF model of BOM', 0), 2 => array('BOM_ADDON', 'chaine', 'mod_bom_standard', 'Name of numbering rules of BOM', 0), - 3 => array('BOM_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT/doctemplates/boms', '', 0) + 3 => array('BOM_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT'.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/boms', '', 0) ); // Some keys to add into the overwriting translation tables @@ -479,7 +479,7 @@ class modBom extends DolibarrModules // ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/boms/template_bom.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/boms'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/boms'; $dest = $dirodt.'/template_bom.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modCommande.class.php b/htdocs/core/modules/modCommande.class.php index 88fdc6d8abc..276ff239f75 100644 --- a/htdocs/core/modules/modCommande.class.php +++ b/htdocs/core/modules/modCommande.class.php @@ -94,7 +94,7 @@ class modCommande extends DolibarrModules $r++; $this->const[$r][0] = "COMMANDE_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/orders"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/orders"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; @@ -459,7 +459,7 @@ class modCommande extends DolibarrModules //ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/orders/template_order.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/orders'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/orders'; $dest = $dirodt.'/template_order.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modContrat.class.php b/htdocs/core/modules/modContrat.class.php index 8154c3f8902..a6bab80e3be 100644 --- a/htdocs/core/modules/modContrat.class.php +++ b/htdocs/core/modules/modContrat.class.php @@ -87,7 +87,7 @@ class modContrat extends DolibarrModules $this->const[$r][0] = "CONTRACT_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/contracts"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/contracts"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -230,7 +230,7 @@ class modContrat extends DolibarrModules //ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/contracts/template_contract.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/contracts'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/contracts'; $dest = $dirodt.'/template_contract.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modExpedition.class.php b/htdocs/core/modules/modExpedition.class.php index 0448e1a8f11..aadfda78a18 100644 --- a/htdocs/core/modules/modExpedition.class.php +++ b/htdocs/core/modules/modExpedition.class.php @@ -99,7 +99,7 @@ class modExpedition extends DolibarrModules $this->const[$r][0] = "EXPEDITION_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/shipments"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/shipments"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -120,7 +120,7 @@ class modExpedition extends DolibarrModules $this->const[$r][0] = "DELIVERY_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/deliveries"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/deliveries"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -343,7 +343,7 @@ class modExpedition extends DolibarrModules //ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/shipments/template_shipment.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/shipments'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/shipments'; $dest = $dirodt.'/template_shipment.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modFacture.class.php b/htdocs/core/modules/modFacture.class.php index 16c8e983673..62402977443 100644 --- a/htdocs/core/modules/modFacture.class.php +++ b/htdocs/core/modules/modFacture.class.php @@ -95,7 +95,7 @@ class modFacture extends DolibarrModules $this->const[$r][0] = "FACTURE_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/invoices"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/invoices"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -773,7 +773,7 @@ class modFacture extends DolibarrModules //ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/invoices/template_invoice.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/invoices'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/invoices'; $dest = $dirodt.'/template_invoice.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modFournisseur.class.php b/htdocs/core/modules/modFournisseur.class.php index 5e7a31b3d77..6a2dacb6bcc 100644 --- a/htdocs/core/modules/modFournisseur.class.php +++ b/htdocs/core/modules/modFournisseur.class.php @@ -117,7 +117,7 @@ class modFournisseur extends DolibarrModules // Add ability ODT for Supplier orders $this->const[$r][0] = "SUPPLIER_ORDER_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/supplier_orders"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/supplier_orders"; $this->const[$r][3] = ''; $this->const[$r][4] = 0; $r++; @@ -125,7 +125,7 @@ class modFournisseur extends DolibarrModules // Add ability ODT for Supplier Invoices $this->const[$r][0] = "SUPPLIER_INVOICE_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = ""; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/supplier_invoices"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -972,7 +972,7 @@ class modFournisseur extends DolibarrModules //ODT template for Supplier Orders $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/supplier_orders/template_supplier_order.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/supplier_orders'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/supplier_orders'; $dest = $dirodt.'/template_supplier_order.odt'; if (file_exists($src) && !file_exists($dest)) { @@ -993,7 +993,7 @@ class modFournisseur extends DolibarrModules //ODT template for Supplier Invoice $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/supplier_invoices/template_supplier_invoices.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/supplier_invoices'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/supplier_invoices'; $dest = $dirodt.'/template_supplier_invoices.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modHoliday.class.php b/htdocs/core/modules/modHoliday.class.php index 5e4002b26a4..453bb966a06 100644 --- a/htdocs/core/modules/modHoliday.class.php +++ b/htdocs/core/modules/modHoliday.class.php @@ -111,7 +111,7 @@ class modHoliday extends DolibarrModules $this->const[$r][0] = "HOLIDAY_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/holiday"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/holiday"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -308,7 +308,7 @@ class modHoliday extends DolibarrModules //ODT template /*$src=DOL_DOCUMENT_ROOT.'/install/doctemplates/holiday/template_holiday.odt'; - $dirodt=DOL_DATA_ROOT.'/doctemplates/holiday'; + $dirodt=DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/holiday'; $dest=$dirodt.'/template_order.odt'; if (file_exists($src) && ! file_exists($dest)) diff --git a/htdocs/core/modules/modMrp.class.php b/htdocs/core/modules/modMrp.class.php index 08456a9f99c..5b6289c8f10 100644 --- a/htdocs/core/modules/modMrp.class.php +++ b/htdocs/core/modules/modMrp.class.php @@ -138,7 +138,7 @@ class modMrp extends DolibarrModules $this->const = array( //1=>array('MRP_MO_ADDON_PDF', 'chaine', 'vinci', 'Name of default PDF model of MO', 0), 2=>array('MRP_MO_ADDON', 'chaine', 'mod_mo_standard', 'Name of numbering rules of MO', 0), - 3=>array('MRP_MO_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT/doctemplates/mrps', '', 0) + 3=>array('MRP_MO_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT'.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/mrps', '', 0) ); // Some keys to add into the overwriting translation tables @@ -442,7 +442,7 @@ class modMrp extends DolibarrModules // ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/mrps/template_mo.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/mrps'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/mrps'; $dest = $dirodt.'/template_mo.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modProjet.class.php b/htdocs/core/modules/modProjet.class.php index bed2e414cc6..0508a540ce8 100644 --- a/htdocs/core/modules/modProjet.class.php +++ b/htdocs/core/modules/modProjet.class.php @@ -92,7 +92,7 @@ class modProjet extends DolibarrModules $this->const[$r][0] = "PROJECT_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/projects"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/projects"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -113,7 +113,7 @@ class modProjet extends DolibarrModules $this->const[$r][0] = "PROJECT_TASK_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/tasks"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/tasks"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -379,7 +379,7 @@ class modProjet extends DolibarrModules //ODT template for project $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/projects/template_project.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/projects'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/projects'; $dest = $dirodt.'/template_project.odt'; if (file_exists($src) && !file_exists($dest)) { @@ -395,7 +395,7 @@ class modProjet extends DolibarrModules //ODT template for tasks $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/tasks/template_task_summary.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/tasks'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/tasks'; $dest = $dirodt.'/template_task_summary.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modPropale.class.php b/htdocs/core/modules/modPropale.class.php index 2e99a82acde..8bac74cc3b8 100644 --- a/htdocs/core/modules/modPropale.class.php +++ b/htdocs/core/modules/modPropale.class.php @@ -99,7 +99,7 @@ class modPropale extends DolibarrModules $this->const[$r][0] = "PROPALE_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/proposals"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/proposals"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -489,7 +489,7 @@ class modPropale extends DolibarrModules //ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/proposals/template_proposal.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/proposals'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/proposals'; $dest = $dirodt.'/template_proposal.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modReception.class.php b/htdocs/core/modules/modReception.class.php index e424325734e..e76ce8b8b78 100644 --- a/htdocs/core/modules/modReception.class.php +++ b/htdocs/core/modules/modReception.class.php @@ -91,7 +91,7 @@ class modReception extends DolibarrModules $this->const[$r][0] = "RECEPTION_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/receptions"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/receptions"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -266,7 +266,7 @@ class modReception extends DolibarrModules //ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/reception/template_reception.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/reception'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/reception'; $dest = $dirodt.'/template_reception.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modSociete.class.php b/htdocs/core/modules/modSociete.class.php index 0c075298d3a..43d8a9ac94b 100644 --- a/htdocs/core/modules/modSociete.class.php +++ b/htdocs/core/modules/modSociete.class.php @@ -101,7 +101,7 @@ class modSociete extends DolibarrModules $this->const[$r][0] = "COMPANY_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/thirdparties"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/thirdparties"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; @@ -947,7 +947,7 @@ class modSociete extends DolibarrModules //ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/thirdparties/template_thirdparty.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/thirdparties'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/thirdparties'; $dest = $dirodt.'/template_thirdparty.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modStock.class.php b/htdocs/core/modules/modStock.class.php index c55ad96883c..640300b9479 100644 --- a/htdocs/core/modules/modStock.class.php +++ b/htdocs/core/modules/modStock.class.php @@ -96,14 +96,14 @@ class modStock extends DolibarrModules $r++; $this->const[$r][0] = "STOCK_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/stocks"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/stocks"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; $r++; $this->const[$r][0] = "MOUVEMENT_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/stocks/movements"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/stocks/movements"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; @@ -538,7 +538,7 @@ class modStock extends DolibarrModules //ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/stocks/template_warehouse.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/stocks'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/stocks'; $dest = $dirodt.'/template_warehouse.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modSupplierProposal.class.php b/htdocs/core/modules/modSupplierProposal.class.php index d7c7941d08b..4dacfc3ed09 100644 --- a/htdocs/core/modules/modSupplierProposal.class.php +++ b/htdocs/core/modules/modSupplierProposal.class.php @@ -92,7 +92,7 @@ class modSupplierProposal extends DolibarrModules $this->const[$r][0] = "SUPPLIER_PROPOSAL_ADDON_PDF_ODT_PATH"; $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/supplier_proposals"; + $this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/supplier_proposals"; $this->const[$r][3] = ""; $this->const[$r][4] = 0; @@ -163,7 +163,7 @@ class modSupplierProposal extends DolibarrModules //ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/supplier_proposals/template_supplier_proposal.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/supplier_proposals'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/supplier_proposals'; $dest = $dirodt.'/template_supplier_proposal.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/modTicket.class.php b/htdocs/core/modules/modTicket.class.php index 17e6ecc9430..4fd1a842ed6 100644 --- a/htdocs/core/modules/modTicket.class.php +++ b/htdocs/core/modules/modTicket.class.php @@ -110,7 +110,7 @@ class modTicket extends DolibarrModules $this->const = array( 1 => array('TICKET_ENABLE_PUBLIC_INTERFACE', 'chaine', '0', 'Enable ticket public interface', 0), 2 => array('TICKET_ADDON', 'chaine', 'mod_ticket_simple', 'Ticket ref module', 0), - 3 => array('TICKET_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT/doctemplates/tickets', 'Ticket templates ODT/ODS directory for templates', 0), + 3 => array('TICKET_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT'.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/tickets', 'Ticket templates ODT/ODS directory for templates', 0), 4 => array('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', 'chaine', 0, 'Automatically mark ticket as read when created from backend', 0), 5 => array('TICKET_DELAY_BEFORE_FIRST_RESPONSE', 'chaine', '0', 'Maximum wanted elapsed time before a first answer to a ticket (in hours). Display a warning in tickets list if not respected.', 0), 6 => array('TICKET_DELAY_SINCE_LAST_RESPONSE', 'chaine', '0', 'Maximum wanted elapsed time between two answers on the same ticket (in hours). Display a warning in tickets list if not respected.', 0), @@ -414,7 +414,7 @@ class modTicket extends DolibarrModules //ODT template $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/tickets/template_ticket.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/tickets'; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/tickets'; $dest = $dirodt.'/template_ticket.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php b/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php index 885a25b84b5..e9657f8e300 100644 --- a/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php +++ b/htdocs/core/modules/supplier_order/doc/pdf_cornas.modules.php @@ -269,13 +269,14 @@ class pdf_cornas extends ModelePDFSuppliersOrders $pdf = pdf_getInstance($this->format); $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance - $heightforinfotot = 50; // Height reserved to output the info and total part + $pdf->SetAutoPageBreak(1, 0); + + $heightforinfotot = 40; // Height reserved to output the info and total part $heightforfreetext = (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT) ? $conf->global->MAIN_PDF_FREETEXT_HEIGHT : 5); // Height reserved to output the free text on last page $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin) if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS')) { $heightforfooter += 6; } - $pdf->SetAutoPageBreak(1, 0); if (class_exists('TCPDF')) { $pdf->setPrintHeader(false); @@ -328,6 +329,8 @@ class pdf_cornas extends ModelePDFSuppliersOrders $tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext; + $nexY = $tab_top - 1; + // Incoterm $height_incoterms = 0; if (isModEnabled('incoterm')) { @@ -337,7 +340,7 @@ class pdf_cornas extends ModelePDFSuppliersOrders $pdf->SetFont('', '', $default_font_size - 1); $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1); - $nexY = $pdf->GetY(); + $nexY = max($pdf->GetY(), $nexY); $height_incoterms = $nexY - $tab_top; // Rect takes a length in 3rd parameter @@ -360,6 +363,8 @@ class pdf_cornas extends ModelePDFSuppliersOrders $pagenb = $pdf->getPage(); if (!empty($notetoshow)) { + $tab_top -= 2; + $tab_width = $this->page_largeur - $this->marge_gauche - $this->marge_droite; $pageposbeforenote = $pagenb; @@ -368,8 +373,6 @@ class pdf_cornas extends ModelePDFSuppliersOrders $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs); $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow); - $tab_top -= 2; - $pdf->startTransaction(); $pdf->SetFont('', '', $default_font_size - 1); @@ -484,21 +487,11 @@ class pdf_cornas extends ModelePDFSuppliersOrders // Use new auto column system $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref); + $nexY = $tab_top + $this->tabTitleHeight; $pageposbeforeprintlines = $pdf->getPage(); $pagenb = $pageposbeforeprintlines; - // Show square - if ($pagenb == $pageposbeforeprintlines) { - $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code); - $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; - } else { - $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code); - $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; - } - - $nexY = $tab_top + $this->tabTitleHeight; - // Loop on each lines for ($i = 0; $i < $nblines; $i++) { $curY = $nexY; @@ -547,20 +540,20 @@ class pdf_cornas extends ModelePDFSuppliersOrders } // Description of product line - $curX = $this->posxdesc - 1; $showpricebeforepagebreak = 1; if ($this->getColumnStatus('desc')) { $pdf->startTransaction(); $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc, 1); - $pageposafter = $pdf->getPage(); + if ($pageposafter > $pageposbefore) { // There is a pagebreak $pdf->rollbackTransaction(true); + $pageposafter = $pageposbefore; + $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it. $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc, 1); - $pageposafter = $pdf->getPage(); $posyafter = $pdf->GetY(); if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text @@ -587,8 +580,10 @@ class pdf_cornas extends ModelePDFSuppliersOrders $posYAfterDescription = $pdf->GetY(); } - $nexY = $pdf->GetY(); + $nexY = max($pdf->GetY(), $posYAfterImage); + $pageposafter = $pdf->getPage(); + $pdf->setPage($pageposbefore); $pdf->setTopMargin($this->marge_haute); $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it. @@ -790,6 +785,14 @@ class pdf_cornas extends ModelePDFSuppliersOrders } } + // Show square + if ($pagenb == $pageposbeforeprintlines) { + $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, $hidetop, 0, $object->multicurrency_code, $outputlangsbis); + } else { + $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0, $object->multicurrency_code, $outputlangsbis); + } + $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1; + // Affiche zone infos $posy = $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs); @@ -1143,9 +1146,10 @@ class pdf_cornas extends ModelePDFSuppliersOrders * @param int $hidetop Hide top bar of array * @param int $hidebottom Hide bottom bar of array * @param string $currency Currency code + * @param Translate $outputlangsbis Langs object bis * @return void */ - protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '') + protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '', $outputlangsbis = null) { global $conf; diff --git a/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php b/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php index 9fd63c8ce7e..93aea2559f5 100644 --- a/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php +++ b/htdocs/core/modules/supplier_order/doc/pdf_muscadet.modules.php @@ -998,9 +998,10 @@ class pdf_muscadet extends ModelePDFSuppliersOrders * @param int $hidetop Hide top bar of array * @param int $hidebottom Hide bottom bar of array * @param string $currency Currency code + * @param Translate $outputlangsbis Langs object bis * @return void */ - protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '') + protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0, $currency = '', $outputlangsbis = null) { global $conf; diff --git a/htdocs/expedition/dispatch.php b/htdocs/expedition/dispatch.php index 3fccaf70d88..cef0e7f1deb 100644 --- a/htdocs/expedition/dispatch.php +++ b/htdocs/expedition/dispatch.php @@ -773,13 +773,16 @@ if ($object->id > 0 || !empty($object->ref)) { print ''; // Dispatch column print ''; // Warehouse column - $sql = "SELECT ed.rowid, ed.qty, ed.fk_entrepot,"; - $sql .= " eb.batch, eb.eatby, eb.sellby, cd.fk_product"; - $sql .= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_batch as eb on ed.rowid = eb.fk_expeditiondet"; - $sql .= " JOIN ".MAIN_DB_PREFIX."commandedet as cd on ed.fk_elementdet = cd.rowid"; - $sql .= " WHERE ed.fk_elementdet =".(int) $objp->rowid; - $sql .= " AND ed.fk_expedition =".(int) $object->id; + $sql = "SELECT ed.rowid"; + $sql .= ", cd.fk_product"; + $sql .= ", ".$db->ifsql('eb.rowid IS NULL', 'ed.qty', 'eb.qty')." as qty"; + $sql .= ", ed.fk_entrepot"; + $sql .= ", eb.batch, eb.eatby, eb.sellby"; + $sql .= " FROM ".$db->prefix()."expeditiondet as ed"; + $sql .= " LEFT JOIN ".$db->prefix()."expeditiondet_batch as eb on ed.rowid = eb.fk_expeditiondet"; + $sql .= " INNER JOIN ".$db->prefix()."commandedet as cd on ed.fk_origin_line = cd.rowid"; + $sql .= " WHERE ed.fk_origin_line = ".(int) $objp->rowid; + $sql .= " AND ed.fk_expedition = ".(int) $object->id; $sql .= " ORDER BY ed.rowid, ed.fk_elementdet"; $resultsql = $db->query($sql); diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index 4e38fe07568..388e1d7b5c5 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -35,7 +35,7 @@ if (!defined('DOL_APPLICATION_TITLE')) { define('DOL_APPLICATION_TITLE', 'Dolibarr'); } if (!defined('DOL_VERSION')) { - define('DOL_VERSION', '20.0.4'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c + define('DOL_VERSION', '20.0.5'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c } if (!defined('EURO')) { diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index df1e1e20cb4..d7746cd8715 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1684,8 +1684,13 @@ class CommandeFournisseur extends CommonOrder // End call triggers } - $this->db->commit(); - return $this->id; + if (!$error) { + $this->db->commit(); + return $this->id; + } else { + $this->db->rollback(); + return -4; + } } else { $this->error = $this->db->lasterror(); $this->db->rollback(); diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 8f3041a20ec..0f23e7776a6 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1962,6 +1962,7 @@ if ($action == 'create') { $formconfirm = ''; + $text = ''; // Confirmation de la suppression de la commande if ($action == 'delete') { diff --git a/htdocs/fourn/facture/card-rec.php b/htdocs/fourn/facture/card-rec.php index 023d1177369..eccfafa8bb5 100644 --- a/htdocs/fourn/facture/card-rec.php +++ b/htdocs/fourn/facture/card-rec.php @@ -722,6 +722,7 @@ if (empty($reshook)) { unset($_POST['date_end_fill']); unset($_POST['situations']); unset($_POST['progress']); + unset($_POST['fourn_ref']); } else { setEventMessages($object->error, $object->errors, 'errors'); } @@ -864,6 +865,7 @@ if (empty($reshook)) { unset($_POST['date_endyear']); unset($_POST['situations']); unset($_POST['progress']); + unset($_POST['fourn_ref']); } else { setEventMessages($object->error, $object->errors, 'errors'); } diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index a7d7df70c25..f1ab09df0d6 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -910,7 +910,7 @@ if (empty($reshook)) { $object->fk_incoterms = GETPOSTINT('incoterm_id'); $object->location_incoterms = GETPOST('location_incoterms', 'alpha'); $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha'); - $object->multicurrency_tx = GETPOSTINT('originmulticurrency_tx'); + $object->multicurrency_tx = GETPOSTFLOAT('originmulticurrency_tx'); $object->transport_mode_id = GETPOSTINT('transport_mode_id'); // Proprietes particulieres a facture avoir @@ -1013,7 +1013,7 @@ if (empty($reshook)) { $object->fk_incoterms = GETPOSTINT('incoterm_id'); $object->location_incoterms = GETPOST('location_incoterms', 'alpha'); $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha'); - $object->multicurrency_tx = GETPOSTINT('originmulticurrency_tx'); + $object->multicurrency_tx = GETPOSTFLOAT('originmulticurrency_tx'); // Source facture $object->fac_rec = $fac_recid; @@ -1080,7 +1080,7 @@ if (empty($reshook)) { $object->fk_incoterms = GETPOSTINT('incoterm_id'); $object->location_incoterms = GETPOST('location_incoterms', 'alpha'); $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha'); - $object->multicurrency_tx = GETPOSTINT('originmulticurrency_tx'); + $object->multicurrency_tx = GETPOSTFLOAT('originmulticurrency_tx'); $object->transport_mode_id = GETPOSTINT('transport_mode_id'); // Auto calculation of date due if not filled by user @@ -1122,7 +1122,7 @@ if (empty($reshook)) { $object->origin_id = GETPOSTINT('originid'); - require_once DOL_DOCUMENT_ROOT.'/'.$element.'/class/'.$subelement.'.class.php'; + dol_include_once('/'.$element.'/class/'.$subelement.'.class.php'); $classname = ucfirst($subelement); if ($classname == 'Fournisseur.commande') { $classname = 'CommandeFournisseur'; @@ -1150,7 +1150,7 @@ if (empty($reshook)) { // Add lines if ($id > 0) { - require_once DOL_DOCUMENT_ROOT.'/'.$element.'/class/'.$subelement.'.class.php'; + dol_include_once('/'.$element.'/class/'.$subelement.'.class.php'); $classname = ucfirst($subelement); if ($classname == 'Fournisseur.commande') { $classname = 'CommandeFournisseur'; @@ -2121,7 +2121,7 @@ if ($action == 'create') { $subelement = 'fournisseur.commande'; } - require_once DOL_DOCUMENT_ROOT.'/'.$element.'/class/'.$subelement.'.class.php'; + dol_include_once('/'.$element.'/class/'.$subelement.'.class.php'); $classname = ucfirst($subelement); if ($classname == 'Fournisseur.commande') { $classname = 'CommandeFournisseur'; diff --git a/htdocs/hrm/skill_tab.php b/htdocs/hrm/skill_tab.php index ea6715d7734..fae86ffe033 100644 --- a/htdocs/hrm/skill_tab.php +++ b/htdocs/hrm/skill_tab.php @@ -284,6 +284,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $sql_skill .= " FROM ".MAIN_DB_PREFIX."hrm_skillrank AS sr"; $sql_skill .= " JOIN ".MAIN_DB_PREFIX."hrm_skill AS s ON sr.fk_skill = s.rowid"; $sql_skill .= " AND sr.fk_object = ".((int) $id); + $sql_skill .= " AND sr.objecttype = '".$db->escape($objecttype)."'"; $result = $db->query($sql_skill); $numSkills = $db->num_rows($result); $TSkillsJob = array(); diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 1852ed06c2b..6cbb118a170 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -214,13 +214,13 @@ function testSqlAndScriptInject($val, $type) // List of dom events is on https://www.w3schools.com/jsref/dom_obj_event.asp and https://developer.mozilla.org/en-US/docs/Web/Events $inj += preg_match('/on(mouse|drag|key|load|touch|pointer|select|transition)[a-z]*\s*=/i', $val); // onmousexxx can be set on img or any html tag like - $inj += preg_match('/on(abort|after|animation|auxclick|before|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|copy|cut)[a-z]*\s*=/i', $val); + $inj += preg_match('/on(abort|after|animation|auxclick|before|blur|bounce|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|copy|cut)[a-z]*\s*=/i', $val); $inj += preg_match('/on(dblclick|drop|durationchange|emptied|end|ended|error|focus|focusin|focusout|formdata|gotpointercapture|hashchange|input|invalid)[a-z]*\s*=/i', $val); $inj += preg_match('/on(lostpointercapture|offline|online|pagehide|pageshow)[a-z]*\s*=/i', $val); $inj += preg_match('/on(paste|pause|play|playing|progress|ratechange|reset|resize|scroll|search|seeked|seeking|show|stalled|start|submit|suspend)[a-z]*\s*=/i', $val); $inj += preg_match('/on(timeupdate|toggle|unload|volumechange|waiting|wheel)[a-z]*\s*=/i', $val); // More not into the previous list - $inj += preg_match('/on(repeat|begin|finish|beforeinput)[a-z]*\s*=/i', $val); + $inj += preg_match('/on(repeat|begin|finish)[a-z]*\s*=/i', $val); // We refuse html into html because some hacks try to obfuscate evil strings by inserting HTML into HTML. // Example: error=alert(1) or =alert(1) to bypass test on onerror= @@ -228,13 +228,13 @@ function testSqlAndScriptInject($val, $type) // List of dom events is on https://www.w3schools.com/jsref/dom_obj_event.asp and https://developer.mozilla.org/en-US/docs/Web/Events $inj += preg_match('/on(mouse|drag|key|load|touch|pointer|select|transition)[a-z]*\s*=/i', $tmpval); // onmousexxx can be set on img or any html tag like - $inj += preg_match('/on(abort|after|animation|auxclick|before|blur|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|copy|cut)[a-z]*\s*=/i', $tmpval); + $inj += preg_match('/on(abort|after|animation|auxclick|before|blur|bounce|cancel|canplay|canplaythrough|change|click|close|contextmenu|cuechange|copy|cut)[a-z]*\s*=/i', $tmpval); $inj += preg_match('/on(dblclick|drop|durationchange|emptied|end|ended|error|focus|focusin|focusout|formdata|gotpointercapture|hashchange|input|invalid)[a-z]*\s*=/i', $tmpval); $inj += preg_match('/on(lostpointercapture|offline|online|pagehide|pageshow)[a-z]*\s*=/i', $tmpval); $inj += preg_match('/on(paste|pause|play|playing|progress|ratechange|reset|resize|scroll|search|seeked|seeking|show|stalled|start|submit|suspend)[a-z]*\s*=/i', $tmpval); $inj += preg_match('/on(timeupdate|toggle|unload|volumechange|waiting|wheel)[a-z]*\s*=/i', $tmpval); // More not into the previous list - $inj += preg_match('/on(repeat|begin|finish|beforeinput)[a-z]*\s*=/i', $tmpval); + $inj += preg_match('/on(repeat|begin|finish)[a-z]*\s*=/i', $tmpval); //$inj += preg_match('/on[A-Z][a-z]+\*=/', $val); // To lock event handlers onAbort(), ... $inj += preg_match('/:|:|:/i', $val); // refused string ':' encoded (no reason to have it encoded) to lock 'javascript:...' diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index c79c226fc6f..f7f6805d64a 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -496,7 +496,7 @@ class modMyModule extends DolibarrModules } if ($myTmpObjectArray['includerefgeneration']) { $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/'.$moduledir.'/template_myobjects.odt'; - $dirodt = DOL_DATA_ROOT.'/doctemplates/'.$moduledir; + $dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/'.$moduledir; $dest = $dirodt.'/template_myobjects.odt'; if (file_exists($src) && !file_exists($dest)) { diff --git a/htdocs/product/admin/product.php b/htdocs/product/admin/product.php index 82759e7a8d5..e016add79f0 100644 --- a/htdocs/product/admin/product.php +++ b/htdocs/product/admin/product.php @@ -657,7 +657,7 @@ if (empty($conf->use_javascript_ajax)) { '2' => $langs->trans("Yes").' ('.$langs->trans("NumberOfKeyToSearch", 2).')', '3' => $langs->trans("Yes").' ('.$langs->trans("NumberOfKeyToSearch", 3).')', ); - print $form->selectarray("activate_usesearchtoselectproduct", $arrval, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT); + print $form->selectarray("activate_usesearchtoselectproduct", $arrval, getDolGlobalString('PRODUIT_USE_SEARCH_TO_SELECT'), 0, 0, 0, '', 0, 0, 0, '', 'minwidth400'); print ''; } print ''; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 0f368838f0f..6e20f5452cf 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -5198,8 +5198,6 @@ class Product extends CommonObject */ public function getChildsArbo($id, $firstlevelonly = 0, $level = 1, $parents = array()) { - global $alreadyfound; - if (empty($id)) { return array(); } @@ -5216,9 +5214,6 @@ class Product extends CommonObject dol_syslog(get_class($this).'::getChildsArbo id='.$id.' level='.$level. ' parents='.(is_array($parents) ? implode(',', $parents) : $parents), LOG_DEBUG); - if ($level == 1) { - $alreadyfound = array($id => 1); // We init array of found object to start of tree, so if we found it later (should not happened), we stop immediately - } // Protection against infinite loop if ($level > 30) { return array(); @@ -5227,14 +5222,16 @@ class Product extends CommonObject $res = $this->db->query($sql); if ($res) { $prods = array(); + if ($this->db->num_rows($res) > 0) { + $parents[] = $id; + } + while ($rec = $this->db->fetch_array($res)) { - if (!empty($alreadyfound[$rec['rowid']])) { + if (in_array($rec['id'], $parents)) { dol_syslog(get_class($this).'::getChildsArbo the product id='.$rec['rowid'].' was already found at a higher level in tree. We discard to avoid infinite loop', LOG_WARNING); - if (in_array($rec['id'], $parents)) { - continue; // We discard this child if it is already found at a higher level in tree in the same branch. - } + continue; // We discard this child if it is already found at a higher level in tree in the same branch. } - $alreadyfound[$rec['rowid']] = 1; + $prods[$rec['rowid']] = array( 0 => $rec['rowid'], 1 => $rec['qty'], @@ -5248,7 +5245,6 @@ class Product extends CommonObject //$prods[$this->db->escape($rec['label'])]= array(0=>$rec['id'],1=>$rec['qty'],2=>$rec['fk_product_type']); //$prods[$this->db->escape($rec['label'])]= array(0=>$rec['id'],1=>$rec['qty']); if (empty($firstlevelonly)) { - $parents[] = $rec['rowid']; $listofchilds = $this->getChildsArbo($rec['rowid'], 0, $level + 1, $parents); foreach ($listofchilds as $keyChild => $valueChild) { $prods[$rec['rowid']]['childs'][$keyChild] = $valueChild; diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 83b9b1e55a8..9a32ee96f96 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -139,7 +139,7 @@ class Task extends CommonObjectLine public $timespent_old_duration; public $timespent_date; public $timespent_datehour; // More accurate start date (same than timespent_date but includes hours, minutes and seconds) - public $timespent_withhour; // 1 = we entered also start hours for timesheet line + public $timespent_withhour; // 0 or 1 = we have entered also start hours for timesheet line public $timespent_fk_user; public $timespent_thm; public $timespent_note; @@ -1467,10 +1467,9 @@ class Task extends CommonObjectLine $timespent->fk_user = $this->timespent_fk_user; $timespent->fk_product = $this->timespent_fk_product; $timespent->note = $this->timespent_note; - $timespent->datec = $this->db->idate($now); + $timespent->datec = $now; $result = $timespent->create($user); - if ($result > 0) { $ret = $result; $this->timespent_id = $result; diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 4f7541724fc..00c4a8e8053 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -175,7 +175,6 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_year = ''; $search_note = ''; $search_duration = ''; - $search_value = ''; $search_date_startday = ''; $search_date_startmonth = ''; $search_date_startyear = ''; @@ -249,6 +248,7 @@ if ($action == 'addtimespent' && $user->hasRight('projet', 'time')) { $object->timespent_withhour = 1; } else { $object->timespent_date = dol_mktime(12, 0, 0, GETPOSTINT("timemonth"), GETPOSTINT("timeday"), GETPOSTINT("timeyear")); + $object->timespent_withhour = 0; } $object->timespent_fk_user = GETPOSTINT("userid"); $object->timespent_fk_product = GETPOSTINT("fk_product"); @@ -299,6 +299,7 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us $object->timespent_withhour = 1; } else { $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timelinemonth"), GETPOST("timelineday"), GETPOST("timelineyear")); + $object->timespent_withhour = 0; } $object->timespent_fk_user = GETPOSTINT("userid_line"); $object->timespent_fk_product = GETPOSTINT("fk_product"); @@ -328,6 +329,7 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us $object->timespent_withhour = 1; } else { $object->timespent_date = dol_mktime(12, 0, 0, GETPOSTINT("timelinemonth"), GETPOSTINT("timelineday"), GETPOSTINT("timelineyear")); + $object->timespent_withhour = 0; } $object->timespent_fk_user = GETPOSTINT("userid_line"); $object->timespent_fk_product = GETPOSTINT("fk_product"); diff --git a/htdocs/reception/list.php b/htdocs/reception/list.php index 13f20113775..b8334a9c729 100644 --- a/htdocs/reception/list.php +++ b/htdocs/reception/list.php @@ -1441,7 +1441,7 @@ print ''; $db->free($resql); $hidegeneratedfilelistifempty = 1; -if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) { +if ($massaction == 'builddoc' || $action == 'remove_file' || !empty($show_files)) { $hidegeneratedfilelistifempty = 0; } diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index 368d95fff57..301065a6764 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -201,6 +201,13 @@ class SecurityTest extends CommonClassTest $result = testSqlAndScriptInject($test, 0); $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject bbb'); + $test=''; + $result=testSqlAndScriptInject($test, 0); + $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject onbeforeintput'); + $test=''; + $result=testSqlAndScriptInject($test, 0); + $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject onbounce'); + $test = ''; $result = testSqlAndScriptInject($test, 0); $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject ccc'); @@ -1094,6 +1101,7 @@ class SecurityTest extends CommonClassTest $this->assertEquals('358080.38', $result); global $leftmenu; // Used into strings to eval + $conf->global->MAIN_FEATURES_LEVEL = 1; $leftmenu = 'AAA'; $result = dol_eval('$conf->currency && preg_match(\'/^(AAA|BBB)/\',$leftmenu)', 1, 1, '1'); @@ -1116,7 +1124,7 @@ class SecurityTest extends CommonClassTest print "result16 = ".$result."\n"; $this->assertFalse($result); - $string = '(isModEnabled("agenda") || isModEnabled("resource")) && getDolGlobalInt("MAIN_FEATURES_LEVEL") >= 0 && preg_match(\'/^(admintools|all|XXX)/\', $leftmenu)'; + $string = '(isModEnabled("user") || isModEnabled("resource")) && getDolGlobalInt("MAIN_FEATURES_LEVEL") >= 0 && preg_match(\'/^(admintools|all|XXX)/\', $leftmenu)'; $result = dol_eval($string, 1, 1, '1'); print "result17 = ".$result."\n"; $this->assertTrue($result);