diff --git a/ChangeLog b/ChangeLog index 805f13a58fa..8cc161dceaf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2361,6 +2361,17 @@ The following changes may create regressions for some external modules, but were * The load of hook context productdao has been removed before calling loadvirtualstock. Modules must use the context of main parent page or 'all' for all cases. * booking.class.php was removed, please have a look at calendar.class.php +***** ChangeLog for 18.0.10 compared to 18.0.9 ***** + +FIX: autofill price with multicurrency on supplier doc (backport commit 391aca5) (#38028) +FIX: calculate the files count on ECM when add multiple files in one time (#31866) +FIX: #GHSA-hq5j-39f9-qxcv (#37812) +FIX: SQL Injection via Operator Injection in Contract Service List +FIX: #GHSA-crgg-h74r-2m8r (#37636) +FIX: do not print Extrafields in PDF if printable is 0 +FIX: a param must not come from end user entry. + + ***** ChangeLog for 18.0.9 compared to 18.0.8 ***** 100 files changed, 2283 insertions(+), 591 deletions(-) diff --git a/htdocs/categories/categorie_list.php b/htdocs/categories/categorie_list.php index 20fdef48fa7..ce54c365786 100644 --- a/htdocs/categories/categorie_list.php +++ b/htdocs/categories/categorie_list.php @@ -237,7 +237,11 @@ if (empty($reshook)) { $form = new Form($db); $title = $langs->trans("Categories"); -$title .= ' ('.$langs->trans(empty(Categorie::$MAP_TYPE_TITLE_AREA[$type]) ? ucfirst($type) : Categorie::$MAP_TYPE_TITLE_AREA[$type]).')'; +if ($type == 'product' || $type == 'service') { + $title .= ' ('.$langs->trans("ProductsOrServices").')'; +} else { + $title .= ' ('.$langs->trans(empty(Categorie::$MAP_TYPE_TITLE_AREA[$type]) ? ucfirst($type) : Categorie::$MAP_TYPE_TITLE_AREA[$type]).')'; +} //$help_url = "EN:Module_Categorie|FR:Module_Categorie_FR|ES:Módulo_Categorie"; $help_url = ''; $morejs = array(); diff --git a/htdocs/categories/index.php b/htdocs/categories/index.php index 88c32f3d89f..04a848e2878 100644 --- a/htdocs/categories/index.php +++ b/htdocs/categories/index.php @@ -95,11 +95,22 @@ if ($resql) { // Get list of category type $arrayofcateg = array(); foreach ($categstatic->MAP_ID as $key => $idtype) { - $arrayofcateg[$key] = array(); - $arrayofcateg[$key]['key'] = $key; - $arrayofcateg[$key]['nb'] = $countobjects[$idtype] ?? 0; - $arrayofcateg[$key]['label'] = $langs->transnoentitiesnoconv($categstatic::$MAP_TYPE_TITLE_AREA[$key]); - $arrayofcateg[$key]['labelwithoutaccent'] = dol_string_unaccent($langs->transnoentitiesnoconv($categstatic::$MAP_TYPE_TITLE_AREA[$key])); + if ($key == 'product' && !isModEnabled("product")) { + continue; + } + if ($key == 'service' && !isModEnabled("service")) { + continue; + } + + $arrayofcateg[$idtype] = array(); + $arrayofcateg[$idtype]['key'] = $key; + $arrayofcateg[$idtype]['nb'] = $countobjects[$idtype] ?? 0; + $arrayofcateg[$idtype]['label'] = $langs->transnoentitiesnoconv($categstatic::$MAP_TYPE_TITLE_AREA[$key]); + $arrayofcateg[$idtype]['labelwithoutaccent'] = dol_string_unaccent($langs->transnoentitiesnoconv($categstatic::$MAP_TYPE_TITLE_AREA[$key])); + if ($key == 'product' || $key == 'service') { + $arrayofcateg[$idtype]['label'] = $langs->transnoentitiesnoconv("ProductsAndServices"); + $arrayofcateg[$idtype]['labelwithoutaccent'] = dol_string_unaccent($langs->transnoentitiesnoconv("ProductsAndServices")); + } } $arrayofcateg = dol_sort_array($arrayofcateg, 'labelwithoutaccent', 'asc', 1, 0, 1); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index e663ff06648..eb5b3ee945e 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7000,6 +7000,8 @@ abstract class CommonObject switch ($attributeType) { case 'int': + case 'duration': + case 'stars': if (!is_numeric($value) && $value != '') { $this->errors[] = $langs->trans("ExtraFieldHasWrongValue", $attributeLabel); return -1; @@ -7007,6 +7009,11 @@ abstract class CommonObject $new_array_options[$key] = null; } break; + case 'boolean': + if ($value === '' || $value === false || $value === null) { + $new_array_options[$key] = null; + } + break; case 'price': case 'double': $value = price2num($value); diff --git a/htdocs/core/modules/modSociete.class.php b/htdocs/core/modules/modSociete.class.php index dd13fd55255..f7c76f59d2a 100644 --- a/htdocs/core/modules/modSociete.class.php +++ b/htdocs/core/modules/modSociete.class.php @@ -402,7 +402,7 @@ class modSociete extends DolibarrModules 's.code_compta' => "Text", 's.code_compta_fournisseur' => "Text", 's.client' => "Numeric", 's.fournisseur' => "Numeric", 's.address' => "Text", 's.zip' => "Text", 's.town' => "Text", 's.phone' => "Text", 's.email' => "Text", - 't.code' => "List:c_stcomm:libelle:code", + 't.code' => "List:c_typent:libelle:code", 'c.entity' => 'List:entity:label:rowid', 's.entity' => 'List:entity:label:rowid', ); diff --git a/htdocs/ecm/class/ecmdirectory.class.php b/htdocs/ecm/class/ecmdirectory.class.php index da05d3ba89c..7b9184e09c4 100644 --- a/htdocs/ecm/class/ecmdirectory.class.php +++ b/htdocs/ecm/class/ecmdirectory.class.php @@ -293,11 +293,36 @@ class EcmDirectory extends CommonObject /** * Update cache of nb of documents into database * - * @param string $value '+' or '-' or new number + * @param string $value '+' (one more) or '-' (one less) or new number (like '5') or 'database' (recompute from database) * @return int Return integer <0 if KO, >0 if OK */ public function changeNbOfFiles($value) { + global $conf; + + if ($value == 'database') { + $relativepath = $conf->ecm->dir_output . '/' . $this->getRelativePath(); // Ex: dir1/dir2/dir3/ + $relativepath = preg_replace('/^' . preg_quote(DOL_DATA_ROOT, '/') . '/', '', $relativepath); + $relativepath = trim($relativepath, '/'); + + // Get nb file in relative path + $sql = "SELECT COUNT(*) AS nb"; + $sql .= " FROM " . $this->db->prefix() . "ecm_files"; + $sql .= " WHERE filepath = '" . $this->db->escape($relativepath) . "'"; + + dol_syslog(get_class($this) . "::changeNbOfFiles - Get nb file in relative path", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + $this->error = "Error " . $this->db->lasterror(); + return -1; + } else { + $value = 0; + if ($obj = $this->db->fetch_object($resql)) { + $value = (int) $obj->nb; + } + } + } + // Update request $sql = "UPDATE ".MAIN_DB_PREFIX."ecm_directories SET"; if (preg_match('/[0-9]+/', $value)) { diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index 5b1409d12d1..ffd552393e1 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -33,6 +33,7 @@ */ + require_once 'version.inc.php'; // Define the DOL_VERSION diff --git a/htdocs/fourn/commande/contact.php b/htdocs/fourn/commande/contact.php index 81e82d0f05b..3415c92aedd 100644 --- a/htdocs/fourn/commande/contact.php +++ b/htdocs/fourn/commande/contact.php @@ -6,6 +6,7 @@ * Copyright (C) 2023 Christian Foellmann * Copyright (C) 2024-2025 Frédéric France * Copyright (C) 2025 MDW + * Copyright (C) 2026 Serhii Bondarenko * * 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 @@ -29,7 +30,6 @@ // Load Dolibarr environment require '../../main.inc.php'; - /** * @var Conf $conf * @var DoliDB $db @@ -37,7 +37,6 @@ require '../../main.inc.php'; * @var Translate $langs * @var User $user */ - require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php'; @@ -190,8 +189,14 @@ if ($id > 0 || !empty($ref)) { print dol_get_fiche_end(); - // Contacts lines - include DOL_DOCUMENT_ROOT.'/core/tpl/contacts.tpl.php'; + // Contacts lines (modules that overwrite templates must declare this into descriptor) + $dirtpls = array_merge($conf->modules_parts['tpl'], array('/core/tpl')); + foreach ($dirtpls as $reldir) { + $res = @include dol_buildpath($reldir.'/contacts.tpl.php'); + if ($res) { + break; + } + } } else { // Contact not found recordNotFound('', 0); diff --git a/htdocs/fourn/facture/contact.php b/htdocs/fourn/facture/contact.php index 73d18dcc40c..b1ac80762d9 100644 --- a/htdocs/fourn/facture/contact.php +++ b/htdocs/fourn/facture/contact.php @@ -6,6 +6,7 @@ * Copyright (C) 2021-2025 Frédéric France * Copyright (C) 2023 Christian Foellmann * Copyright (C) 2025 MDW + * Copyright (C) 2026 Serhii Bondarenko * * 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 @@ -273,8 +274,14 @@ if ($id > 0 || !empty($ref)) { //print '
'; //print '
'; - // Contacts lines - include DOL_DOCUMENT_ROOT.'/core/tpl/contacts.tpl.php'; + // Contacts lines (modules that overwrite templates must declare this into descriptor) + $dirtpls = array_merge($conf->modules_parts['tpl'], array('/core/tpl')); + foreach ($dirtpls as $reldir) { + $res = @include dol_buildpath($reldir.'/contacts.tpl.php'); + if ($res) { + break; + } + } } else { recordNotFound('', 0); } diff --git a/htdocs/public/webportal/tpl/home.tpl.php b/htdocs/public/webportal/tpl/home.tpl.php index 0f9594a7967..00336240c55 100644 --- a/htdocs/public/webportal/tpl/home.tpl.php +++ b/htdocs/public/webportal/tpl/home.tpl.php @@ -37,5 +37,11 @@ if (empty($context) || !is_object($context)) { getControllerUrl('invoicelist') . '" title="' . $langs->trans('WebPortalInvoiceListDesc') . '">' . $langs->trans('WebPortalInvoiceListTitle') . ''; ?> + logged_member && $context->logged_member->id > 0) : ?> + + diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index eee2f624182..30e5c20c047 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -1498,6 +1498,11 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($canvasdisplayactio $selectedcustomer = ((GETPOSTISSET('customer') && $action == 'create') ? GETPOSTINT('customer') : $selectedcustomer); $selectedsupplier = ((GETPOSTISSET('supplier') && $action == 'create') ? GETPOSTINT('supplier') : $object->fournisseur); + if ($selectedprospect && $selectedcustomer && getDolGlobalString("SOCIETE_DISABLE_PROSPECTSCUSTOMERS")) { + // If both are not allowed, we reset $selectedcustomer + $selectedcustomer = 0; + } + print ''; if ($conf->browser->layout != 'phone') { print ''.$form->editfieldkey('', 'customerprospect', '', $object, 0, 'string', '', 0).''; diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 3eccc36c77f..5536efeffc0 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1678,7 +1678,6 @@ if ($action == 'create') { } print img_picto('', 'project', 'class="pictofixedwidth"').$formproject->select_projects($projSocFilter, $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500'); print '   id).'">'; - print ''; print ''; } @@ -1953,7 +1952,11 @@ if ($action == 'create') { if ($action != 'classify') { $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; } - $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') ? $object->socid : -1), $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + $canLinkAll = getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS'); + $canLinkAll = ($canLinkAll === '' || $canLinkAll === false) ? 0 : $canLinkAll; + $currentSocId = ($object->id > 0) ? $object->socid : $socid; + $projectSocId = ((int) $canLinkAll == 1) ? -1 : $currentSocId; + $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $projectSocId, $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); } else { if (!empty($object->fk_project)) { $proj = new Project($db); diff --git a/htdocs/supplier_proposal/contact.php b/htdocs/supplier_proposal/contact.php index e3b43474df0..d17f5ebb2e9 100644 --- a/htdocs/supplier_proposal/contact.php +++ b/htdocs/supplier_proposal/contact.php @@ -7,6 +7,7 @@ * Copyright (C) 2024 Alexandre Spangaro * Copyright (C) 2024-2025 Frédéric France * Copyright (C) 2025 MDW + * Copyright (C) 2026 Serhii Bondarenko * * 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 @@ -190,8 +191,14 @@ if ($id > 0 || !empty($ref)) { print dol_get_fiche_end(); - // Contacts lines - include DOL_DOCUMENT_ROOT.'/core/tpl/contacts.tpl.php'; + // Contacts lines (modules that overwrite templates must declare this into descriptor) + $dirtpls = array_merge($conf->modules_parts['tpl'], array('/core/tpl')); + foreach ($dirtpls as $reldir) { + $res = @include dol_buildpath($reldir.'/contacts.tpl.php'); + if ($res) { + break; + } + } } else { // Contact not found print "ErrorRecordNotFound";