diff --git a/ChangeLog b/ChangeLog index 01f85bf17a6..a64c0cbc1ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,12 @@ English Dolibarr ChangeLog -------------------------------------------------------------- +***** ChangeLog for 23.0.3 compared to 23.0.2 ***** +FIX: IDOR on messaging.php - credit Aksoum Abderrahmane +FIX: Some remaining cross-customer object creation on API (proposal, orders) - credit Mitch311 +SEC: Better sanitization param for GETPOST of htmlheader of website page - See commit bbbbb56c6455514dcd0acca53afc17a92ed21bb9 + + ***** ChangeLog for 23.0.2 compared to 23.0.1 ***** diff --git a/dev/build/makepack-dolibarr.php b/dev/build/makepack-dolibarr.php index 946a8504c41..b79641b8b44 100755 --- a/dev/build/makepack-dolibarr.php +++ b/dev/build/makepack-dolibarr.php @@ -662,6 +662,8 @@ if ($nboftargetok) { run("rm -fr $BUILDROOT/$PROJECT/htdocs/install/mssql"); run("rm -fr $BUILDROOT/$PROJECT/htdocs/install/sqlite3"); + run("rm -fr $BUILDROOT/$PROJECT/htdocs/install/install.forced.php"); + run("rm -fr $BUILDROOT/$PROJECT/node_modules"); run("rm -fr $BUILDROOT/$PROJECT/dev/ansible"); diff --git a/dev/build/makepack-dolibarr.pl b/dev/build/makepack-dolibarr.pl index 18740bcca52..ae4cbe50292 100755 --- a/dev/build/makepack-dolibarr.pl +++ b/dev/build/makepack-dolibarr.pl @@ -722,6 +722,8 @@ if ($nboftargetok) { $ret = `rm -fr $BUILDROOT/$PROJECT/htdocs/install/mssql`; $ret = `rm -fr $BUILDROOT/$PROJECT/htdocs/install/sqlite3`; + $ret = `rm -fr $BUILDROOT/$PROJECT/htdocs/install/install.forced.php`; + $ret = `rm -fr $BUILDROOT/$PROJECT/node_modules`; $ret = `rm -fr $BUILDROOT/$PROJECT/dev/ansible`; diff --git a/htdocs/accountancy/journal/expensereportsjournal.php b/htdocs/accountancy/journal/expensereportsjournal.php index 07dfa1e0032..9438d44d158 100644 --- a/htdocs/accountancy/journal/expensereportsjournal.php +++ b/htdocs/accountancy/journal/expensereportsjournal.php @@ -366,7 +366,7 @@ if ($action == 'writebookkeeping' && !$error && $user->hasRight('accounting', 'b $account_label = $accountingaccount->label; // get compte id and label - if ($accountingaccount->fetch(0, $k, true)) { + if ($accountingaccount->id > 0) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; $bookkeeping->doc_ref = $val["ref"]; diff --git a/htdocs/adherents/admin/website.php b/htdocs/adherents/admin/website.php index 1c032c39207..bf8cc6e10de 100644 --- a/htdocs/adherents/admin/website.php +++ b/htdocs/adherents/admin/website.php @@ -107,6 +107,9 @@ if ($action == 'update') { } else { $res = dolibarr_set_const($db, "MEMBER_NEWFORM_FORCEMORPHY", $forcemorphy, 'chaine', 0, '', $conf->entity); } + if (GETPOSTISSET('MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATE')) { + $res = dolibarr_set_const($db, "MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATE", GETPOST('MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATE') == 'yes' ? 1 : 0, 'chaine', 0, '', $conf->entity); + } if (!($res > 0)) { $error++; @@ -318,9 +321,9 @@ if (getDolGlobalString('MEMBER_ENABLE_PUBLIC')) { // Search a member after member creation form print ''; - print $langs->trans("MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATE"); + print $form->textwithpicto($langs->trans("MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATE"), $langs->trans("MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATEDesc")); print ''; - print $form->selectyesno("MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATE"); // Reverse the logic "hide -> show" for retrocompatibility + print $form->selectyesno("MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATE", getDolGlobalInt("MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATE")); // Reverse the logic "hide -> show" for retrocompatibility print "\n"; print ''; diff --git a/htdocs/admin/invoice_situation.php b/htdocs/admin/invoice_situation.php index cdeeb3ac5fd..33d5450022e 100644 --- a/htdocs/admin/invoice_situation.php +++ b/htdocs/admin/invoice_situation.php @@ -107,7 +107,8 @@ $item->fieldAttr = array( 'type' => 'number', 'step' => '0.01', 'min' => 0, - 'max' => 100 + 'max' => 100, + 'class' => 'width75 right', ); @@ -133,6 +134,8 @@ include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; * View */ +$action = 'edit'; + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); $help_url = 'EN:Invoice_Configuration|FR:Configuration_module_facture|ES:ConfiguracionFactura'; @@ -150,27 +153,7 @@ print dol_get_fiche_head($head, 'situation', $langs->trans("InvoiceSituation"), print ''.$langs->trans("InvoiceFirstSituationDesc").'

'; - -/* - * Numbering module - */ - -if ($action == 'edit') { - print $formSetup->generateOutput(true); -} else { - print $formSetup->generateOutput(); -} - -if (count($formSetup->items) > 0) { - if ($action != 'edit') { - print '
'; - print ''.$langs->trans("Modify").''; - print '
'; - } -} else { - print '
'.$langs->trans("NothingToSetup"); -} - +print $formSetup->generateOutput(true); print dol_get_fiche_end(); diff --git a/htdocs/admin/payment.php b/htdocs/admin/payment.php index e02e2c89d58..74e4928cd45 100644 --- a/htdocs/admin/payment.php +++ b/htdocs/admin/payment.php @@ -280,12 +280,14 @@ print ' '; print "\n"; // Allow payments on different thirdparties bills but same parent company +/* print ''; print $langs->trans("PaymentOnDifferentThirdBills"); print ''; print $form->selectyesno("FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS", getDolGlobalInt('FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS'), 1); print ''; print "\n"; +*/ // Allow to group payments by mod in rapports print ''; diff --git a/htdocs/admin/security_headers_http.php b/htdocs/admin/security_headers_http.php index 1478f89baf7..6292f045efa 100644 --- a/htdocs/admin/security_headers_http.php +++ b/htdocs/admin/security_headers_http.php @@ -168,6 +168,8 @@ if (preg_match('/set_([a-z0-9_\-]+)/i', $action, $reg)) { $securitycspstring = ""; if (isset($sourcetype) && $sourcetype == "data") { $forceCSPArr[$directivecsp][] = "data:".$sourcedatacsp; + } elseif (isset($sourcetype) && $sourcetype == "blob") { + $forceCSPArr[$directivecsp][] = "blob:".$sourcedatacsp; } elseif (isset($sourcetype) && $sourcetype == "input") { if (empty($forceCSPArr[$directivecsp])) { $forceCSPArr[$directivecsp] = array(); diff --git a/htdocs/ai/class/ai.class.php b/htdocs/ai/class/ai.class.php index 4c93e825fed..62770027b41 100644 --- a/htdocs/ai/class/ai.class.php +++ b/htdocs/ai/class/ai.class.php @@ -252,7 +252,11 @@ class Ai } } - $localurl = 2; // Accept both local and external endpoints + // By default, we accept only external endpoints ($dolibarr_ai_allow_local_endpoints is not set). + // To allow local endpoints, we must set $dolibarr_ai_allow_local_endpoints to 1 or 2 in conf.php. + global $dolibarr_ai_allow_local_endpoints; + $localurl = $dolibarr_ai_allow_local_endpoints ?? 0; + $response = getURLContent($this->apiEndpoint, 'POST', $payload, 1, $headers, array('http', 'https'), $localurl); if (empty($response['http_code'])) { diff --git a/htdocs/asset/class/asset.class.php b/htdocs/asset/class/asset.class.php index a9fa58ad208..d2c71880b50 100644 --- a/htdocs/asset/class/asset.class.php +++ b/htdocs/asset/class/asset.class.php @@ -748,7 +748,7 @@ class Asset extends CommonObject } $sql = "SELECT ad.rowid, ad.depreciation_mode, ad.ref, ad.depreciation_date, ad.depreciation_ht, ad.cumulative_depreciation_ht,"; - $sql .= " " . $this->db->ifsql('EXISTS (SELECT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab WHERE ab.doc_type = \'asset\' AND ab.fk_docdet = ad.rowid)', '1', '0') . " AS bookkeeping"; + $sql .= " " . $this->db->ifsql('EXISTS (SELECT fk_docdet FROM ' . MAIN_DB_PREFIX . 'accounting_bookkeeping as ab WHERE ab.doc_type = \'asset\' AND ab.fk_docdet = ad.rowid)', '1', '0') . " AS bookkeeping"; $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad"; $sql .= " WHERE ad.fk_asset = " . (int) $this->id; $sql .= " ORDER BY ad.depreciation_date ASC"; diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index 45eb1aa0928..79b2a126894 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -1450,7 +1450,6 @@ if ($action == 'create') { // aaa // Ref customer $morehtmlref .= $form->editfieldkey("", 'title', $object->title, $object, $user->hasRight('mailing', 'creer'), 'string', '', 0, 1); $morehtmlref .= $form->editfieldval("", 'title', $object->title, $object, $user->hasRight('mailing', 'creer'), 'string', '', null, null, '', 1); - $morehtmlref .= ''; $morehtmlstatus = ''; $nbtry = $nbok = 0; @@ -1484,6 +1483,7 @@ if ($action == 'create') { // aaa } } } + $morehtmlref .= ''; dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'ref', $morehtmlref, '', 0, '', $morehtmlstatus); @@ -1548,19 +1548,24 @@ if ($action == 'create') { // aaa print ''; print $langs->trans("MAIN_MAIL_SENDMODE"); print ''; - if (getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING') && getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING') != 'default') { - $text = $listofmethods[getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING')]; - } elseif (getDolGlobalString('MAIN_MAIL_SENDMODE')) { - $text = $listofmethods[getDolGlobalString('MAIN_MAIL_SENDMODE')]; - } else { - $text = $listofmethods['mail']; - } - print $text; - if (getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING') != 'default') { - if (getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING') != 'mail') { - print ' ('.getDolGlobalString('MAIN_MAIL_SMTP_SERVER_EMAILING').')'; + if ($object->messtype != 'sms') { + if (getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING') && getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING') != 'default') { + $text = $listofmethods[getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING')]; + } elseif (getDolGlobalString('MAIN_MAIL_SENDMODE')) { + $text = $listofmethods[getDolGlobalString('MAIN_MAIL_SENDMODE')]; + } else { + $text = $listofmethods['mail']; } - } elseif (getDolGlobalString('MAIN_MAIL_SENDMODE') != 'mail' && getDolGlobalString('MAIN_MAIL_SMTP_SERVER')) { + print $text; + if (getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING') != 'default') { + if (getDolGlobalString('MAIN_MAIL_SENDMODE_EMAILING') != 'mail') { + print ' ('.getDolGlobalString('MAIN_MAIL_SMTP_SERVER_EMAILING', getDolGlobalString('MAIN_MAIL_SMTP_SERVER')).')'; + } + } elseif (getDolGlobalString('MAIN_MAIL_SENDMODE') != 'mail' && getDolGlobalString('MAIN_MAIL_SMTP_SERVER')) { + print ' ('.getDolGlobalString('MAIN_MAIL_SMTP_SERVER').')'; + } + } else { + print 'SMS '; print ' ('.getDolGlobalString('MAIN_MAIL_SMTP_SERVER').')'; } print ''; diff --git a/htdocs/comm/propal/class/api_proposals.class.php b/htdocs/comm/propal/class/api_proposals.class.php index 875e6affbb5..eb656527d8e 100644 --- a/htdocs/comm/propal/class/api_proposals.class.php +++ b/htdocs/comm/propal/class/api_proposals.class.php @@ -314,8 +314,20 @@ class Proposals extends DolibarrApi if (!DolibarrApiAccess::$user->hasRight('propal', 'creer')) { throw new RestException(403, "Insufficiant rights"); } + // Check mandatory fields - $result = $this->_validate($request_data); + $this->_validate($request_data); + + // Check thirdparty validity + $socid = (int) $request_data['socid']; + $thirdpartytmp = new Societe($this->db); + $thirdparty_result = $thirdpartytmp->fetch($socid); + if ($thirdparty_result < 1) { + throw new RestException(404, 'Thirdparty with id='.$socid.' not found or not allowed'); + } + if (!DolibarrApi::_checkAccessToResource('societe', $thirdpartytmp->id)) { + throw new RestException(404, 'Thirdparty with id='.$thirdpartytmp->id.' not found or not allowed'); + } foreach ($request_data as $field => $value) { if ($field === 'caller') { diff --git a/htdocs/commande/class/api_orders.class.php b/htdocs/commande/class/api_orders.class.php index 396b1ec96d9..9eec8368925 100644 --- a/htdocs/commande/class/api_orders.class.php +++ b/htdocs/commande/class/api_orders.class.php @@ -319,8 +319,20 @@ class Orders extends DolibarrApi if (!DolibarrApiAccess::$user->hasRight('commande', 'creer')) { throw new RestException(403, "Insufficiant rights"); } + // Check mandatory fields - $result = $this->_validate($request_data); + $this->_validate($request_data); + + // Check thirdparty validity + $socid = (int) $request_data['socid']; + $thirdpartytmp = new Societe($this->db); + $thirdparty_result = $thirdpartytmp->fetch($socid); + if ($thirdparty_result < 1) { + throw new RestException(404, 'Thirdparty with id='.$socid.' not found or not allowed'); + } + if (!DolibarrApi::_checkAccessToResource('societe', $thirdpartytmp->id)) { + throw new RestException(404, 'Thirdparty with id='.$thirdpartytmp->id.' not found or not allowed'); + } foreach ($request_data as $field => $value) { if ($field === 'caller') { diff --git a/htdocs/compta/cashcontrol/cashcontrol_card.php b/htdocs/compta/cashcontrol/cashcontrol_card.php index 2b659593325..6a510e77323 100644 --- a/htdocs/compta/cashcontrol/cashcontrol_card.php +++ b/htdocs/compta/cashcontrol/cashcontrol_card.php @@ -423,7 +423,7 @@ if ($action == "valid" && $permissiontoadd) { // validate = close if ($contextpage == 'takepos') { print " "; exit; } diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index 5a24ba839b1..54e94f69a7c 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -361,6 +361,17 @@ class Invoices extends DolibarrApi // Check mandatory fields (not using output, only possible exception is important) $this->_validate($request_data); + // Check thirdparty validity + $socid = (int) $request_data['socid']; + $thirdpartytmp = new Societe($this->db); + $thirdparty_result = $thirdpartytmp->fetch($socid); + if ($thirdparty_result < 1) { + throw new RestException(404, 'Thirdparty with id='.$socid.' not found or not allowed'); + } + if (!DolibarrApi::_checkAccessToResource('societe', $thirdpartytmp->id)) { + throw new RestException(404, 'Thirdparty with id='.$thirdpartytmp->id.' not found or not allowed'); + } + foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 0ebb0b7627a..b999211d44c 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -1423,6 +1423,9 @@ class Facture extends CommonInvoice $this->date = dol_now(); $this->source = 0; + // Avoid updating the row ranks + $this->context['createfromclone'] = 1; + $num = count($object->lines); for ($i = 0; $i < $num; $i++) { $line = new FactureLigne($this->db); diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index ed341ce9c17..63a611f47d0 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -76,7 +76,7 @@ if (isModEnabled('category')) { } // Load translation files required by the page -$langs->loadLangs(array('bills', 'companies', 'products', 'categories')); +$langs->loadLangs(array('bills', 'companies', 'products', 'categories', 'cashdesk')); $search_all = trim(GETPOST('search_all', 'alphanohtml')); @@ -220,6 +220,7 @@ $diroutputmassaction = $conf->invoice->dir_output.'/temp/massgeneration/'.$user- $now = dol_now(); $error = 0; +$sql = ''; // Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context $object = new Facture($db); @@ -346,6 +347,10 @@ foreach ($object->fields as $key => $val) { } // Extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; +// Add hook to complete $arrayfield +$parameters = array('arrayfields' => &$arrayfields); +$reshook = $hookmanager->executeHooks('completeArrayFields', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; // For POS context, we force some fields if ($contextpage == 'poslist') { diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index f5c26e12e22..70d8214c8cf 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -708,7 +708,7 @@ class BonPrelevement extends CommonObject $paiement->num_payment = $this->ref; // Set ref of direct debit note $paiement->id_prelevement = $this->id; - $result = $paiement->create($user); // This use ->paiementid, that is ID of payment mode + $result = $paiement->create($user, 1); // This use ->paiementid, that is ID of payment mode. closepaidinvoices=1 to convert deposit invoice to available credit if ($result < 0) { $error++; diff --git a/htdocs/compta/tva/clients.php b/htdocs/compta/tva/clients.php index f54fd979770..385774ed312 100644 --- a/htdocs/compta/tva/clients.php +++ b/htdocs/compta/tva/clients.php @@ -5,7 +5,7 @@ * Copyright (C) 2006 Yannick Warnier * Copyright (C) 2014 Ferran Marcet * Copyright (C) 2018-2024 Frédéric France - * Copyright (C) 2024-2025 MDW + * Copyright (C) 2024-2026 MDW * Copyright (C) 2026 Juan Pablo Farber * * This program is free software; you can redistribute it and/or modify @@ -423,6 +423,7 @@ if (!is_array($x_coll) || !is_array($x_paye)) { print ''; $action = "tvadetail"; + $parameters = array(); $parameters["mode"] = $modetax; $parameters["start"] = $date_start; $parameters["end"] = $date_end; @@ -454,6 +455,9 @@ if (!is_array($x_coll) || !is_array($x_paye)) { print ''."\n"; foreach ($x_both[$thirdparty_id]['coll']['detail'] as $index => $fields) { + // Sort by payment date/invoice date + usort($x_both[$thirdparty_id]['coll']['detail'], 'cmp_fields_date'); + // Define type // We MUST use dtype (type in line). We can use something else, only if dtype is really unknown. $type = (isset($fields['dtype']) ? $fields['dtype'] : $fields['ptype']); @@ -644,6 +648,9 @@ if (!is_array($x_coll) || !is_array($x_paye)) { print ''."\n"; foreach ($x_both[$thirdparty_id]['paye']['detail'] as $index => $fields) { + // Sort by payment date/invoice date + usort($x_both[$thirdparty_id]['paye']['detail'], 'cmp_fields_date'); + // Define type // We MUST use dtype (type in line). We can use something else, only if dtype is really unknown. $type = (isset($fields['dtype']) ? $fields['dtype'] : $fields['ptype']); @@ -810,3 +817,20 @@ print ''; llxFooter(); $db->close(); + +/** + * Helper compare function to sort lines by payment date first + * + * @param array{datep:int,datef:int} $a Left argument to compare + * @param array{datep:int,datef:int} $b Right argument to compare + * @return int<-1,1> Indicates sort order between arguments + */ +function cmp_fields_date(&$a, &$b) +{ + // Compare payment date + if ($a['datep'] != $b['datep']) { + return $a['datep'] <=> $b['datep']; + } + // In case the payment date is the same, order by invoice date + return $a['datef'] <=> $b['datef']; +} diff --git a/htdocs/contrat/class/api_contracts.class.php b/htdocs/contrat/class/api_contracts.class.php index 80083fe486e..c1a2a89d624 100644 --- a/htdocs/contrat/class/api_contracts.class.php +++ b/htdocs/contrat/class/api_contracts.class.php @@ -36,9 +36,7 @@ class Contracts extends DolibarrApi */ public static $FIELDS = array( 'socid', - 'date_contrat', - 'commercial_signature_id', - 'commercial_suivi_id' + 'date_contrat' ); /** @@ -236,6 +234,10 @@ class Contracts extends DolibarrApi throw new RestException(403, "Missing permission: Create/modify contracts/subscriptions"); } + // Check mandatory fields + $this->_validate($request_data); + + // Check thirdparty validity $socid = (int) $request_data['socid']; $thirdpartytmp = new Societe($this->db); $thirdparty_result = $thirdpartytmp->fetch($socid); @@ -246,9 +248,6 @@ class Contracts extends DolibarrApi throw new RestException(404, 'Thirdparty with id='.$thirdpartytmp->id.' not found or not allowed'); } - // Check mandatory fields - $result = $this->_validate($request_data); - foreach ($request_data as $field => $value) { if ($field === 'caller') { // Add a mention of caller so on trigger called after action, we can filter to avoid a loop if we try to sync back again with the caller diff --git a/htdocs/contrat/services_list.php b/htdocs/contrat/services_list.php index 13063725684..b4f51a88aff 100644 --- a/htdocs/contrat/services_list.php +++ b/htdocs/contrat/services_list.php @@ -382,28 +382,28 @@ if ($filter_datecloture_start != '' && $filter_opcloture == -1) { } if (!empty($filter_opouvertureprevue) && $filter_opouvertureprevue != -1 && $filter_opouvertureprevue != ' BETWEEN ' && $filter_dateouvertureprevue_start != '') { - $sql .= " AND cd.date_ouverture_prevue ".$filter_opouvertureprevue." '".$db->idate($filter_dateouvertureprevue_start)."'"; + $sql .= " AND cd.date_ouverture_prevue ".preg_replace('/[^<>]/', '', $filter_opouvertureprevue)." '".$db->idate($filter_dateouvertureprevue_start)."'"; } if (!empty($filter_opouvertureprevue) && $filter_opouvertureprevue == ' BETWEEN ') { - $sql .= " AND cd.date_ouverture_prevue ".$filter_opouvertureprevue." '".$db->idate($filter_dateouvertureprevue_start)."' AND '".$db->idate($filter_dateouvertureprevue_end)."'"; + $sql .= " AND cd.date_ouverture_prevue ".$db->sanitize($filter_opouvertureprevue)." '".$db->idate($filter_dateouvertureprevue_start)."' AND '".$db->idate($filter_dateouvertureprevue_end)."'"; } if (!empty($filter_op1) && $filter_op1 != -1 && $filter_op1 != ' BETWEEN ' && $filter_date1_start != '') { - $sql .= " AND cd.date_ouverture ".$filter_op1." '".$db->idate($filter_date1_start)."'"; + $sql .= " AND cd.date_ouverture ".preg_replace('/[^<>]/', '', $filter_op1)." '".$db->idate($filter_date1_start)."'"; } if (!empty($filter_op1) && $filter_op1 == ' BETWEEN ') { - $sql .= " AND cd.date_ouverture ".$filter_op1." '".$db->idate($filter_date1_start)."' AND '".$db->idate($filter_date1_end)."'"; + $sql .= " AND cd.date_ouverture ".$db->sanitize($filter_op1)." '".$db->idate($filter_date1_start)."' AND '".$db->idate($filter_date1_end)."'"; } if (!empty($filter_op2) && $filter_op2 != -1 && $filter_op2 != ' BETWEEN ' && $filter_date2_start != '') { - $sql .= " AND cd.date_fin_validite ".$filter_op2." '".$db->idate($filter_date2_start)."'"; + $sql .= " AND cd.date_fin_validite ".preg_replace('/[^<>]/', '', $filter_op2)." '".$db->idate($filter_date2_start)."'"; } if (!empty($filter_op2) && $filter_op2 == ' BETWEEN ') { - $sql .= " AND cd.date_fin_validite ".$filter_op2." '".$db->idate($filter_date2_start)."' AND '".$db->idate($filter_date2_end)."'"; + $sql .= " AND cd.date_fin_validite ".$db->sanitize($filter_op2)." '".$db->idate($filter_date2_start)."' AND '".$db->idate($filter_date2_end)."'"; } if (!empty($filter_opcloture) && $filter_opcloture != ' BETWEEN ' && $filter_opcloture != -1 && $filter_datecloture_start != '') { - $sql .= " AND cd.date_cloture ".$filter_opcloture." '".$db->idate($filter_datecloture_start)."'"; + $sql .= " AND cd.date_cloture ".preg_replace('/[^<>]/', '', $filter_opcloture)." '".$db->idate($filter_datecloture_start)."'"; } if (!empty($filter_opcloture) && $filter_opcloture == ' BETWEEN ') { - $sql .= " AND cd.date_cloture ".$filter_opcloture." '".$db->idate($filter_datecloture_start)."' AND '".$db->idate($filter_datecloture_end)."'"; + $sql .= " AND cd.date_cloture ".$db->sanitize($filter_opcloture)." '".$db->idate($filter_datecloture_start)."' AND '".$db->idate($filter_datecloture_end)."'"; } // Add where from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; diff --git a/htdocs/core/ajax/objectonoff.php b/htdocs/core/ajax/objectonoff.php index 5bd06d0a08f..d2b5adf7f40 100644 --- a/htdocs/core/ajax/objectonoff.php +++ b/htdocs/core/ajax/objectonoff.php @@ -42,8 +42,6 @@ if (!defined('NOREQUIRESOC')) { // Load Dolibarr environment require '../../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/genericobject.class.php'; - /** * @var Conf $conf * @var DoliDB $db @@ -51,6 +49,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/genericobject.class.php'; * @var Translate $langs * @var User $user */ +require_once DOL_DOCUMENT_ROOT.'/core/class/genericobject.class.php'; $action = GETPOST('action', 'aZ09'); $backtopage = GETPOST('backtopage'); @@ -131,12 +130,19 @@ if (($action == 'set') && !empty($id)) { // Test on permission already done in h foreach ($object->errors as $msg) { print $msg."\n";; } + + $db->close(); + http_response_code(500); exit; } if ($backtopage) { + $db->close(); + header('Location: '.$backtopage); exit; } } + +$db->close(); diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 7c3e0223ff4..92752e4e86c 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -915,6 +915,10 @@ abstract class CommonInvoice extends CommonObject */ public function getVentilExportCompta($mode = 0) { + if (!isModEnabled('accounting')) { + return 0; + } + $alreadydispatched = 0; $type = 'customer_invoice'; diff --git a/htdocs/core/class/doleditor.class.php b/htdocs/core/class/doleditor.class.php index 6b90c1fec67..03342f40607 100644 --- a/htdocs/core/class/doleditor.class.php +++ b/htdocs/core/class/doleditor.class.php @@ -457,7 +457,7 @@ class DolEditor $out .= 'jQuery(document).ready(function() {'; $out .= ' jQuery(".buttonforacesave").click(function() { - console.log("We click on savefile button for component '.dol_escape_js($this->htmlname).'"); + console.log("We click on button (with class .buttonforacesave) that must fill ace fields for component '.dol_escape_js($this->htmlname).'"); var aceEditor = window.ace.edit("'.dol_escape_js($this->htmlname).'aceeditorid"); if (aceEditor) { var cursorPos = aceEditor.getCursorPosition(); diff --git a/htdocs/core/class/html.formaccounting.class.php b/htdocs/core/class/html.formaccounting.class.php index 03466d8a270..132bfb8b3f6 100644 --- a/htdocs/core/class/html.formaccounting.class.php +++ b/htdocs/core/class/html.formaccounting.class.php @@ -197,21 +197,18 @@ class FormAccounting extends Form $selected = array(); $langs->load('accountancy'); while ($obj = $this->db->fetch_object($resql)) { - $label = $langs->trans($obj->label); - - $select_value_in = $obj->rowid; - $select_value_out = $obj->rowid; - - // Try to guess if we have found default value - if ($select_in == 1) { - $select_value_in = $obj->code; - } - if ($select_out == 1) { - $select_value_out = $obj->code; + // Build the full text directly here + $translatedLabel = $langs->trans($obj->label); + if (empty($translatedLabel) || $translatedLabel === $obj->label) { + $translatedLabel = $obj->label; // fallback to the raw label } + $label = $obj->code . ' - ' . $translatedLabel; + + $select_value_in = ($select_in == 1 ? $obj->code : $obj->rowid); + $select_value_out = ($select_out == 1 ? $obj->code : $obj->rowid); + // Remember guy's we store in database llx_accounting_bookkeeping the code of accounting_journal and not the rowid if (!empty($selectedIds) && in_array($select_value_in, $selectedIds)) { - //var_dump("Found ".$selectid." ".$select_value_in); $selected[] = $select_value_out; } $options[$select_value_out] = $label; @@ -223,7 +220,7 @@ class FormAccounting extends Form } } - $out .= Form::multiselectarray($htmlname, $options, $selected, $showempty, 0, $morecss, 0, 0, '', 'code_journal', '', ($disabledajaxcombo ? 0 : 1)); + $out .= Form::multiselectarray($htmlname, $options, $selected, 0, 0, $morecss, 0, 0, '', 'code_journal', '', ($disabledajaxcombo ? 0 : 1)); return $out; } diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index fcb2fe502fe..e79f3b9ed81 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -1503,6 +1503,7 @@ class FormMail extends Form * @param string $htmlContent HTML name of WYSIWYG field to fill once layout has been chosen * @param string $showlinktolayout Show link to layout * @return string HTML for model email boxes + * @see getContentPageTemplate() */ public function getEmailLayoutSelector($htmlContent = 'message', $showlinktolayout = 'email') { @@ -1837,27 +1838,25 @@ class FormMail extends Form if ($type_template == 'body') { // Special case to use this->withbody as content $defaultmessage = (string) $this->withbody; - } elseif ($type_template == 'facture_send') { + } elseif ($type_template == 'facture_send' || $type_template == 'facture' || $type_template == 'facture_relance') { $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendInvoice"); - } elseif ($type_template == 'facture_relance') { - $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendInvoiceReminder"); - } elseif ($type_template == 'propal_send') { + } elseif ($type_template == 'propal_send' || $type_template == 'propal') { $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendProposal"); - } elseif ($type_template == 'supplier_proposal_send') { + } elseif ($type_template == 'supplier_proposal_send' || $type_template == 'supplier_proposal') { $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierProposal"); - } elseif ($type_template == 'order_send') { + } elseif ($type_template == 'order_send' || $type_template == 'order') { $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendOrder"); - } elseif ($type_template == 'order_supplier_send') { + } elseif ($type_template == 'order_supplier_send' || $type_template == 'order_supplier') { $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierOrder"); - } elseif ($type_template == 'invoice_supplier_send') { + } elseif ($type_template == 'invoice_supplier_send' || $type_template == 'invoice_supplier') { $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendSupplierInvoice"); - } elseif ($type_template == 'shipping_send') { + } elseif ($type_template == 'shipping_send' || $type_template == 'shipping') { $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendShipping"); - } elseif ($type_template == 'reception_send') { + } elseif ($type_template == 'reception_send' || $type_template == 'reception') { $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendReception"); - } elseif ($type_template == 'fichinter_send') { + } elseif ($type_template == 'fichinter_send' || $type_template == 'fichinter') { $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendFichInter"); - } elseif ($type_template == 'actioncomm_send') { + } elseif ($type_template == 'actioncomm_send' || $type_template == 'actioncomm') { $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendActionComm"); } elseif (!empty($type_template)) { $defaultmessage = $outputlangs->transnoentities("PredefinedMailContentGeneric"); diff --git a/htdocs/core/class/html.formsetup.class.php b/htdocs/core/class/html.formsetup.class.php index efbb0283257..539fc6ee041 100644 --- a/htdocs/core/class/html.formsetup.class.php +++ b/htdocs/core/class/html.formsetup.class.php @@ -242,7 +242,8 @@ class FormSetup if ($reshook > 0) { return $hookmanager->resPrint; } else { - $out = ''; + $out = '
'; + $out .= '
'; if (empty($hideTitle)) { if (empty($title)) { $title = $this->langs->transnoentitiesnoconv("Parameter"); @@ -265,6 +266,7 @@ class FormSetup $out .= ''; $out .= '
'; + $out .= ''; return $out; } } diff --git a/htdocs/core/class/html.formwebsite.class.php b/htdocs/core/class/html.formwebsite.class.php index 9bc9d5fe8e1..f2ac69198f6 100644 --- a/htdocs/core/class/html.formwebsite.class.php +++ b/htdocs/core/class/html.formwebsite.class.php @@ -349,6 +349,7 @@ class FormWebsite * * @param string $htmlContent HTML name of WYSIWYG field * @return string HTML for model page boxes + * @see getEmailLayoutSelector() */ public function getContentPageTemplate($htmlContent = 'message') { @@ -359,8 +360,12 @@ class FormWebsite require_once DOL_DOCUMENT_ROOT.'/core/lib/emaillayout.lib.php'; $listofsamples = dol_dir_list(DOL_DOCUMENT_ROOT.'/website/samples', 'files', 0, '^page-sample-.*\.html$'); - $arrayofsamples = array(); - $arrayofsamples['empty'] = 'EmptyPage'; // Always this one first + + // Define list of layouts to use + $arrayofsamples = array( + 'empty' => 'EmptyPage', + ); + foreach ($listofsamples as $sample) { $reg = array(); if (preg_match('/^page-sample-(.*)\.html$/', $sample['name'], $reg)) { @@ -391,7 +396,7 @@ class FormWebsite $contentHtml = file_exists($pathtoTemplateFile) ? make_substitutions(@file_get_contents($pathtoTemplateFile), $substitutionarray) : ''; $out .= '
'; - $out .= ''.$template.''; + $out .= ''.$template.''; $out .= ''.($template != 'text' ? ucfirst($template) : ucfirst($templateFunction)).''; $out .= '
'; } diff --git a/htdocs/core/class/notify.class.php b/htdocs/core/class/notify.class.php index 464dfd5f27e..a342693db32 100644 --- a/htdocs/core/class/notify.class.php +++ b/htdocs/core/class/notify.class.php @@ -1290,7 +1290,7 @@ class Notify if (!empty($mailTemplateLabel)) { include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; $formmail = new FormMail($this->db); - $emailTemplate = $formmail->getEMailTemplate($this->db, $object_type.'_send', $user, $outputlangs, 0, 1, $mailTemplateLabel); + $emailTemplate = $formmail->getEMailTemplate($this->db, $object_type, $user, $outputlangs, 0, 1, $mailTemplateLabel); } if (!empty($mailTemplateLabel) && is_object($emailTemplate) && $emailTemplate->id > 0) { if (property_exists($object, 'thirdparty')) { diff --git a/htdocs/core/customreports.php b/htdocs/core/customreports.php index 47e3b4fffac..b71e43bc676 100644 --- a/htdocs/core/customreports.php +++ b/htdocs/core/customreports.php @@ -68,13 +68,15 @@ if (!defined('USE_CUSTOM_REPORT_AS_INCLUDE')) { $search_measures = GETPOST('search_measures', 'array:alphanohtml'); - //$search_xaxis = GETPOST('search_xaxis', 'array'); if (GETPOST('search_xaxis', 'alpha') && GETPOST('search_xaxis', 'alpha') != '-1') { $search_xaxis = array(GETPOST('search_xaxis', 'alpha')); + } else { + $search_xaxis = array(); } - //$search_groupby = GETPOST('search_groupby', 'array'); if (GETPOST('search_groupby', 'alpha') && GETPOST('search_groupby', 'alpha') != '-1') { $search_groupby = array(GETPOST('search_groupby', 'alpha')); + } else { + $search_groupby = array(); } '@phan-var-force string[] $search_groupby'; @@ -482,7 +484,7 @@ if (count($search_groupby)) { $fieldtocount = $gvalsanitized; } - $sql = "SELECT DISTINCT ".$fieldtocount." as val"; // $fieldtocount has been sanitized by previous lines as we can't use db->sanitie() + $sql = "SELECT DISTINCT ".$fieldtocount." as val"; // $fieldtocount has been sanitized by previous lines as we can't use db->sanitize() if (strpos($fieldtocount, 'te') === 0) { $tabletouse = $object->table_element; diff --git a/htdocs/core/filemanagerdol/connectors/php/config.inc.php b/htdocs/core/filemanagerdol/connectors/php/config.inc.php index 0704d51f615..7cb8b015ec3 100644 --- a/htdocs/core/filemanagerdol/connectors/php/config.inc.php +++ b/htdocs/core/filemanagerdol/connectors/php/config.inc.php @@ -33,9 +33,9 @@ define('NOTOKENRENEWAL', 1); // Disables token renewal // is a security hole if anybody can access without // being an authenticated user. require_once '../../../../main.inc.php'; - /** * @var Conf $conf + * @var User $user * * @var string $dolibarr_main_data_root * @var string $dolibarr_main_url_root @@ -49,6 +49,13 @@ if ($pos == '/') { //define('DOL_URL_ROOT', $pos); $entity = ((!empty($_SESSION['dol_entity']) && $_SESSION['dol_entity'] > 1) ? $_SESSION['dol_entity'] : null); + +if (!empty($user->admin) && !$user->hasRight('website', 'write')) { + accessforbidden('Need to be admin or having write permission on website module'); + exit; +} + + // SECURITY: You must explicitly enable this "connector". (Set it to "true"). // WARNING: don't just set "$Config['Enabled'] = true ;", you must be sure that only // authenticated users can access this file or use some kind of session checking. diff --git a/htdocs/core/filemanagerdol/connectors/php/connector.php b/htdocs/core/filemanagerdol/connectors/php/connector.php index 25d9312015f..94ea7f864cc 100644 --- a/htdocs/core/filemanagerdol/connectors/php/connector.php +++ b/htdocs/core/filemanagerdol/connectors/php/connector.php @@ -26,6 +26,9 @@ ob_start(); require 'config.inc.php'; // This include the main.inc.php +/** + * @var array $Config + */ require 'connector.lib.php'; if (!$Config['Enabled']) { diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index fdc61e4ecbb..d012cf09139 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -2229,6 +2229,7 @@ function GetContentPolicySources() // Fetch directives "fetch" => array( "*" => array("label" => "*", "data-sourcetype" => "select"), + "blob" => array("label" => "blob:", "data-sourcetype" => "blob"), "data" => array("label" => "data:", "data-sourcetype" => "data"), "self" => array("label" => "self", "data-sourcetype" => "quoted"), "unsafe-eval" => array("label" => "unsafe-eval", "data-sourcetype" => "quoted"), diff --git a/htdocs/core/lib/ajax.lib.php b/htdocs/core/lib/ajax.lib.php index 980598d8619..ab47f91e300 100644 --- a/htdocs/core/lib/ajax.lib.php +++ b/htdocs/core/lib/ajax.lib.php @@ -843,7 +843,9 @@ function ajax_object_onoff($object, $code, $field, $text_on, $text_off, $input = } }).fail( function(response) { - alert(response.responseText); + //alert(response.responseText); + console.warn(response.responseText); + Dolibarr.tools.setEventMessage(response.responseText, "errors"); } ); }); @@ -886,7 +888,9 @@ function ajax_object_onoff($object, $code, $field, $text_on, $text_off, $input = } }).fail( function(response) { - alert(response.responseText); + //alert(response.responseText); + console.warn(response.responseText); + Dolibarr.tools.setEventMessage(response.responseText, "errors"); } ); }); diff --git a/htdocs/core/lib/pdf.lib.php b/htdocs/core/lib/pdf.lib.php index 04b4960a6c6..443e82e6c96 100644 --- a/htdocs/core/lib/pdf.lib.php +++ b/htdocs/core/lib/pdf.lib.php @@ -88,7 +88,7 @@ function pdf_getFormat($outputlangs = null, $mode = 'setup') { global $conf, $db, $langs; - dol_syslog("pdf_getFormat Get paper format with mode=".$mode." MAIN_PDF_FORMAT=".(!getDolGlobalString('MAIN_PDF_FORMAT') ? 'null' : $conf->global->MAIN_PDF_FORMAT)." outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null')." and langs->defaultlang=".(is_object($langs) ? $langs->defaultlang : 'null')); + dol_syslog("pdf_getFormat Get paper format with mode=".$mode." MAIN_PDF_FORMAT=".getDolGlobalString('MAIN_PDF_FORMAT')." outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null')." and langs->defaultlang=".(is_object($langs) ? $langs->defaultlang : 'null')); // Default value if setup was not done and/or entry into c_paper_format not defined $width = 210; @@ -242,7 +242,9 @@ function pdf_getEncryption($pathoffile) //ob_start(); @($parser = new TCPDF_PARSER(ltrim($content))); - [$xref, $data] = $parser->getParsedData(); + $tmp = $parser->getParsedData(); + $xref = $tmp[0]; + $data = $tmp[1] ?? null; unset($parser); //ob_end_clean(); @@ -265,10 +267,8 @@ function pdf_getEncryption($pathoffile) */ function pdf_getPDFFont($outputlangs) { - global $conf; - if (getDolGlobalString('MAIN_PDF_FORCE_FONT')) { - return $conf->global->MAIN_PDF_FORCE_FONT; + return getDolGlobalString('MAIN_PDF_FORCE_FONT'); } $font = 'Helvetica'; // By default, for FPDI, or ISO language on TCPDF @@ -311,8 +311,7 @@ function pdf_getPDFFontSize($outputlangs) */ function pdf_getHeightForLogo($logo, $url = false) { - global $conf; - $height = (!getDolGlobalString('MAIN_DOCUMENTS_LOGO_HEIGHT') ? 20 : $conf->global->MAIN_DOCUMENTS_LOGO_HEIGHT); + $height = getDolGlobalInt('MAIN_DOCUMENTS_LOGO_HEIGHT', 20); $maxwidth = 130; include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; $tmp = dol_getImageSize($logo, $url); @@ -1296,7 +1295,10 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_ $pdf->SetDrawColor(224, 224, 224); // Option for footer text color if (getDolGlobalString('PDF_FOOTER_TEXT_COLOR')) { - [$r, $g, $b] = sscanf(getDolGlobalString('PDF_FOOTER_TEXT_COLOR'), '%d, %d, %d'); + $tmparray = sscanf(getDolGlobalString('PDF_FOOTER_TEXT_COLOR'), '%d, %d, %d'); + $r = $tmparray[0]; + $g = $tmparray[1]; + $b = $tmparray[2]; $pdf->SetTextColor($r, $g, $b); } @@ -1334,7 +1336,10 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_ // Option for footer background color (without freetext zone) if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) { - [$r, $g, $b] = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d'); + $tmparray = sscanf(getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR'), '%d, %d, %d'); + $r = $tmparray[0]; + $g = $tmparray[1]; + $b = $tmparray[2]; $pdf->setAutoPageBreak(false, 0); // Disable auto pagebreak $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', array(), $fill_color = array($r, $g, $b)); $pdf->setAutoPageBreak(true, 0); // Restore pagebreak @@ -1386,7 +1391,10 @@ function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_ // Option for footer background color (without freetext zone) if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) { - [$r, $g, $b] = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d'); + $tmparray = sscanf(getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR'), '%d, %d, %d'); + $r = $tmparray[0]; + $g = $tmparray[1]; + $b = $tmparray[2]; $pdf->setAutoPageBreak(false, 0); // Disable auto pagebreak $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', array(), $fill_color = array($r, $g, $b)); $pdf->setAutoPageBreak(true, 0); // Restore pagebreak @@ -1844,7 +1852,8 @@ function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, } if (isset($productCustomerPrice) && !empty($productCustomerPrice->ref_customer)) { - switch ($conf->global->PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE) { + $idcustprice = getDolGlobalInt('PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE'); + switch ($idcustprice) { case 1: $ref_prodserv = $productCustomerPrice->ref_customer; break; diff --git a/htdocs/core/lib/project.lib.php b/htdocs/core/lib/project.lib.php index f0ffcf20e1d..78f393b3e8f 100644 --- a/htdocs/core/lib/project.lib.php +++ b/htdocs/core/lib/project.lib.php @@ -2509,7 +2509,7 @@ function projectLinesPerMonth(&$inc, $firstdaytoshow, $fuser, $parent, $lines, & if ($lines[$i]->id > 0) { //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level); //var_dump($totalforeachday); - $ret = projectLinesPerMonth($inc, $firstdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $TWeek); + $ret = projectLinesPerMonth($inc, $firstdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $TWeek, $arrayfields); //var_dump('ret with parent='.$lines[$i]->id.' level='.$level); //var_dump($ret); foreach ($ret as $key => $val) { diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index d66feae5592..2e89de5a733 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -1204,10 +1204,10 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl $sql .= " AND dbt.".$dbt_keyfield." = ".((int) $user->socid); } elseif (isModEnabled("societe") && !$user->hasRight('societe', 'client', 'voir')) { // If internal user without permission to see all thirdparties: Check permission for internal users that are restricted on their objects + if (empty($dbt_keyfield)) { + dol_print_error(null, 'Param dbt_keyfield is required but not defined'); + } if ($feature != 'ticket') { - if (empty($dbt_keyfield)) { - dol_print_error(null, 'Param dbt_keyfield is required but not defined'); - } $sql = "SELECT COUNT(sc.fk_soc) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; @@ -1227,7 +1227,7 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON sc.fk_soc = dbt.".$dbt_keyfield." AND sc.fk_user = ".((int) $user->id); $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")"; $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")"; - $sql .= " AND (sc.fk_user = ".((int) $user->id)." OR sc.fk_user IS NULL)"; + $sql .= " AND (sc.fk_user = ".((int) $user->id)." OR dbt.".$dbt_keyfield." IS NULL OR dbt.".$dbt_keyfield." = 0)"; } } elseif (isModEnabled('multicompany')) { // If multicompany, and user is an internal user with all permissions, check that object is in correct entity diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index adc96d61e41..21c6bec53fc 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -105,7 +105,7 @@ function dolKeepOnlyPhpCode($str) } } } - return $newstr; + return str_replace(array("\r\n", "\r"), array("\n", "\n"), $newstr); } /** diff --git a/htdocs/core/lib/website2.lib.php b/htdocs/core/lib/website2.lib.php index 68f6c48053f..8359a81e9b7 100644 --- a/htdocs/core/lib/website2.lib.php +++ b/htdocs/core/lib/website2.lib.php @@ -937,7 +937,7 @@ function showWebsiteTemplates(Website $website, int $refresh) /** - * Check a new string containing only php code (including attributes[$elementtype]['type']) && is_array($extrafiel $colspan++; } - print ''; + print ''; print ''; print $langs->trans("None"); print ''; diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 5e8403df697..3e7969a1057 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -974,13 +974,20 @@ if (!empty($usemargins) && $user->hasRight('margins', 'creer')) { } - // Set vat rate if field is an input box - $('#tva_tx').val(tva_tx); - // Set vat rate by selecting the combo - //$('#tva_tx option').val(tva_tx); // This is bugged, it replaces the vat key of all options - $('#tva_tx option').removeAttr('selected'); - console.log("stringforvatrateselection="+stringforvatrateselection+" -> value of option label for this key="+$('#tva_tx option[value="'+stringforvatrateselection+'"]').val()); - $('#tva_tx option[value="'+stringforvatrateselection+'"]').prop('selected', true); + // Set vat rate: handle both input box and combo cases + if ($('#tva_tx option').length) { + // It is a combo: try exact match first (rate + code), fallback to numeric match + if ($('#tva_tx option[value="' + stringforvatrateselection + '"]').length) { + $('#tva_tx').val(stringforvatrateselection); + } else { + $('#tva_tx option').filter(function () { + return parseFloat($(this).val()) === parseFloat(tva_tx); + }).first().prop('selected', true); + } + } else { + // It is an input box + $('#tva_tx').val(tva_tx); + }

'; - print 'Website features are protected to be disabled if the PHP system functions ('.implode(',', $systemfunctions).') are not disabled for the website context.
'; + print 'Website features are DISABLED if the PHP system functions ('.implode(',', $systemfunctions).') are NOT disabled for the website context.
'; print 'The value "'.$systemfunction.'" has NOT been found into the current disable_functions=
'; print '