From e9d65ea751cf068b04a2e1f333c74da7462e8e5f Mon Sep 17 00:00:00 2001 From: gauthier Date: Thu, 14 Jun 2018 11:56:22 +0200 Subject: [PATCH 01/20] FIX : need to filter on aa.entity for same accounting accounts available in several entities --- htdocs/accountancy/customer/list.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index f675c010b37..d5d828ef626 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -235,6 +235,7 @@ if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_STANDARD . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")"; } $sql .= " AND f.entity IN (" . getEntity('facture', 0) . ")"; // We don't share object for accountancy +$sql .= " AND aa.entity = " . $conf->entity; // Add where from hooks $parameters=array(); @@ -439,4 +440,4 @@ if ($result) { } llxFooter(); -$db->close(); \ No newline at end of file +$db->close(); From a21e138c7046a11baf65bdba6e62b8b511f9fb6f Mon Sep 17 00:00:00 2001 From: Ferran Marcet Date: Fri, 15 Jun 2018 11:19:04 +0200 Subject: [PATCH 02/20] Fix: Avoid converting into reduction twice and draft invoice --- htdocs/compta/facture/card.php | 4 +- .../compta/paiement/class/paiement.class.php | 62 ++++++++++--------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 67de173dff7..055a100848a 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -12,7 +12,7 @@ * Copyright (C) 2013 Jean-Francois FERRY * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2013 Cédric Salvador - * Copyright (C) 2014 Ferran Marcet + * Copyright (C) 2014-2018 Ferran Marcet * Copyright (C) 2015-2016 Marcos García * * This program is free software; you can redistribute it and/or modify @@ -4408,7 +4408,7 @@ else if ($id > 0 || ! empty($ref)) print ''; } // For deposit invoice - if ($object->type == Facture::TYPE_DEPOSIT && $user->rights->facture->creer && empty($discount->id)) + if ($object->type == Facture::TYPE_DEPOSIT && $user->rights->facture->creer && $object->statut > 0 && empty($discount->id)) { print ''; } diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index 42106c1cb13..6a8628da6c3 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -6,6 +6,7 @@ * Copyright (C) 2014 Raphaël Doursenaud * Copyright (C) 2014 Marcos García * Copyright (C) 2015 Juanjo Menent + * Copyright (C) 2018 Ferran Marcet * * 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 @@ -288,39 +289,40 @@ class Paiement extends CommonObject { $amount_ht = $amount_tva = $amount_ttc = array(); - // Loop on each vat rate - $i = 0; - foreach ($invoice->lines as $line) - { - if ($line->total_ht!=0) - { // no need to create discount if amount is null - $amount_ht[$line->tva_tx] += $line->total_ht; - $amount_tva[$line->tva_tx] += $line->total_tva; - $amount_ttc[$line->tva_tx] += $line->total_ttc; - $i ++; - } - } + // Insert one discount by VAT rate category + $discount = new DiscountAbsolute($this->db); + $discount->fetch('',$invoice->id); + if (empty($discount->id)) { - // Insert one discount by VAT rate category - $discount = new DiscountAbsolute($this->db); - $discount->description = '(DEPOSIT)'; - $discount->fk_soc = $invoice->socid; - $discount->fk_facture_source = $invoice->id; - foreach ($amount_ht as $tva_tx => $xxx) - { - $discount->amount_ht = abs($amount_ht[$tva_tx]); - $discount->amount_tva = abs($amount_tva[$tva_tx]); - $discount->amount_ttc = abs($amount_ttc[$tva_tx]); - $discount->tva_tx = abs($tva_tx); + $discount->description = '(DEPOSIT)'; + $discount->fk_soc = $invoice->socid; + $discount->fk_facture_source = $invoice->id; - $result = $discount->create($user); - if ($result < 0) - { - $error++; - break; - } - } + // Loop on each vat rate + $i = 0; + foreach ($invoice->lines as $line) { + if ($line->total_ht != 0) { // no need to create discount if amount is null + $amount_ht[$line->tva_tx] += $line->total_ht; + $amount_tva[$line->tva_tx] += $line->total_tva; + $amount_ttc[$line->tva_tx] += $line->total_ttc; + $i++; + } + } + + foreach ($amount_ht as $tva_tx => $xxx) { + $discount->amount_ht = abs($amount_ht[$tva_tx]); + $discount->amount_tva = abs($amount_tva[$tva_tx]); + $discount->amount_ttc = abs($amount_ttc[$tva_tx]); + $discount->tva_tx = abs($tva_tx); + + $result = $discount->create($user); + if ($result < 0) { + $error++; + break; + } + } + } if ($error) { From 5d6cd381b9999c6f615904c54217c4721965f6d5 Mon Sep 17 00:00:00 2001 From: altatof Date: Fri, 15 Jun 2018 15:59:14 +0200 Subject: [PATCH 03/20] Fix
detection --- htdocs/core/lib/functions.lib.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 6e9261fdd81..c0fbfb68010 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5067,6 +5067,7 @@ function dol_textishtml($msg,$option=0) { if (preg_match('//i',$msg)) return true; elseif (preg_match('/<(br|div|font|li|p|span|strong|table)>/i',$msg)) return true; elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*>/i',$msg)) return true; From 63fb82931cb0d8427503cb27f437ac6eb6704082 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 18 Jun 2018 10:41:11 +0200 Subject: [PATCH 04/20] Update functions.lib.php --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index c0fbfb68010..8c3bea14dae 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5067,8 +5067,8 @@ function dol_textishtml($msg,$option=0) { if (preg_match('//i',$msg)) return true; + elseif (preg_match('//i',$msg)) return true; elseif (preg_match('/<(br|div|font|li|p|span|strong|table)>/i',$msg)) return true; elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*>/i',$msg)) return true; elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*\/>/i',$msg)) return true; From fed61930d5e50916eaed657211b2ba943032db3b Mon Sep 17 00:00:00 2001 From: gauthier Date: Mon, 18 Jun 2018 11:37:15 +0200 Subject: [PATCH 05/20] FIX : clause must not be there --- htdocs/accountancy/customer/list.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index d5d828ef626..850e5cae6a9 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -198,7 +198,7 @@ $sql.=$hookmanager->resPrint; $sql .= " FROM " . MAIN_DB_PREFIX . "facture as f"; $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "facturedet as l ON f.rowid = l.fk_facture"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = l.fk_product"; -$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON p.accountancy_code_sell = aa.account_number"; +$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON (p.accountancy_code_sell = aa.account_number AND aa.entity = ".$conf->entity.")"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_system as accsys ON accsys.pcg_version = aa.fk_pcg_version"; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND product_type <= 2"; @@ -235,7 +235,6 @@ if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { $sql .= " AND f.type IN (" . Facture::TYPE_STANDARD . "," . Facture::TYPE_STANDARD . "," . Facture::TYPE_CREDIT_NOTE . "," . Facture::TYPE_DEPOSIT . "," . Facture::TYPE_SITUATION . ")"; } $sql .= " AND f.entity IN (" . getEntity('facture', 0) . ")"; // We don't share object for accountancy -$sql .= " AND aa.entity = " . $conf->entity; // Add where from hooks $parameters=array(); From df056980b5bbcaeb45ee28e818956f9fc273984c Mon Sep 17 00:00:00 2001 From: atm-greg Date: Tue, 19 Jun 2018 10:46:07 +0200 Subject: [PATCH 06/20] fix bad result on fetch ProductStockEntrepot --- htdocs/product/stock/product.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index bc4d6daaaa4..c0dccaa2181 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -85,6 +85,9 @@ if ($id > 0 || ! empty($ref)) $result = $object->fetch($id, $ref); } + +if(empty($id) && !empty($object->id)) $id = $object->id; + $modulepart='product'; // Get object canvas (By default, this is not defined, so standard usage of dolibarr) @@ -130,7 +133,7 @@ if ($action == 'addlimitstockwarehouse' && !empty($user->rights->produit->creer) if($maj_ok) { $pse = new ProductStockEntrepot($db); - if($pse->fetch('', GETPOST('id'), GETPOST('fk_entrepot')) > 0) { + if($pse->fetch('', $id, GETPOST('fk_entrepot')) > 0) { // Update $pse->seuil_stock_alerte = $seuil_stock_alerte; @@ -141,7 +144,7 @@ if ($action == 'addlimitstockwarehouse' && !empty($user->rights->produit->creer) // Create $pse->fk_entrepot = GETPOST('fk_entrepot'); - $pse->fk_product = GETPOST('id'); + $pse->fk_product = $id; $pse->seuil_stock_alerte = GETPOST('seuil_stock_alerte'); $pse->desiredstock = GETPOST('desiredstock'); if($pse->create($user) > 0) setEventMessage($langs->trans('ProductStockWarehouseCreated')); @@ -150,7 +153,7 @@ if ($action == 'addlimitstockwarehouse' && !empty($user->rights->produit->creer) } - header("Location: ".$_SERVER["PHP_SELF"]."?id=".GETPOST('id')); + header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id); exit; } @@ -951,7 +954,7 @@ if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) if (!empty($user->rights->produit->creer)){ print '
'; print ''; - print ''; + print ''; } print ''; if (!empty($user->rights->produit->creer)){ @@ -968,7 +971,7 @@ if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) } $pse = new ProductStockEntrepot($db); - $lines = $pse->fetchAll(GETPOST('id')); + $lines = $pse->fetchAll($id); if (!empty($lines)) { @@ -981,7 +984,7 @@ if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) print ''; print ''; if (!empty($user->rights->produit->creer)){ - print ''; + print ''; } print ''; } From 8fc2f7441cf340ae2dae1e77b89e7ad82b05d3b1 Mon Sep 17 00:00:00 2001 From: Regis Houssin Date: Wed, 20 Jun 2018 09:06:16 +0200 Subject: [PATCH 07/20] Fix: to avoid deleting line breaks --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 8c3bea14dae..0b0f74c1a09 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -449,7 +449,7 @@ function GETPOST($paramname, $check='', $method=0, $filter=NULL, $options=NULL, if (! is_array($out) || empty($out)) $out=array(); break; case 'nohtml': - $out=dol_string_nohtmltag($out); + $out=dol_string_nohtmltag($out, 0); break; case 'alphanohtml': // Recommended for search params $out=trim($out); From 2fab4d7f76224ed220aa5570824c2839722485cb Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio Date: Wed, 20 Jun 2018 14:56:24 +0200 Subject: [PATCH 08/20] FIX: proposal: missing contact type translation key --- htdocs/langs/en_US/propal.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/langs/en_US/propal.lang b/htdocs/langs/en_US/propal.lang index 7745dde08da..5a7169ac925 100644 --- a/htdocs/langs/en_US/propal.lang +++ b/htdocs/langs/en_US/propal.lang @@ -75,6 +75,7 @@ AvailabilityTypeAV_1M=1 month TypeContact_propal_internal_SALESREPFOLL=Representative following-up proposal TypeContact_propal_external_BILLING=Customer invoice contact TypeContact_propal_external_CUSTOMER=Customer contact following-up proposal +TypeContact_propal_external_SHIPPING=Customer contact for delivery # Document models DocModelAzurDescription=A complete proposal model (logo...) DefaultModelPropalCreate=Default model creation From 5bee3245785a5ab475c463bbd69b85ca5818ccee Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 22 Jun 2018 14:34:59 +0200 Subject: [PATCH 09/20] Update paiement.class.php --- htdocs/compta/paiement/class/paiement.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index 6a8628da6c3..088e14c5543 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -292,7 +292,7 @@ class Paiement extends CommonObject // Insert one discount by VAT rate category $discount = new DiscountAbsolute($this->db); $discount->fetch('',$invoice->id); - if (empty($discount->id)) { + if (empty($discount->id)) { // If the invoice was not yet converted into a discount (this may have been done manually before we come here) $discount->description = '(DEPOSIT)'; From ca04ffe42011b5b156ab1b9e3cd1f9a787a72014 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 22 Jun 2018 17:07:49 +0200 Subject: [PATCH 10/20] Load lang --- htdocs/accountancy/admin/journals_list.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/htdocs/accountancy/admin/journals_list.php b/htdocs/accountancy/admin/journals_list.php index 971fdc20811..f2f862a9cdd 100644 --- a/htdocs/accountancy/admin/journals_list.php +++ b/htdocs/accountancy/admin/journals_list.php @@ -30,9 +30,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php'; -$langs->load("admin"); -$langs->load("compta"); -$langs->load("accountancy"); +$langs->loadLangs(array("admin","compta","accountancy")); $action=GETPOST('action','alpha')?GETPOST('action','alpha'):'view'; $confirm=GETPOST('confirm','alpha'); From edec89ef1e23b0310b77a60b71110a15533110b2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Jun 2018 12:44:30 +0200 Subject: [PATCH 11/20] Prepare 7.0.3 --- ChangeLog | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7e319d3aabe..62bcbb19754 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,43 @@ English Dolibarr ChangeLog -------------------------------------------------------------- +***** ChangeLog for 7.0.3 compared to 7.0.2 ***** +FIX: 7.0 task contact card without withproject parameters +FIX: #8722 +FIX: #8762 +FIX: #8813 +FIX: #8858 #8860 Backport better compatibility fix +FIX: #8893 to get formatted price as substitution vars +FIX: Avoid converting into reduction twice and draft invoice +FIX: bad result on fetch ProductStockEntrepot +FIX: Bad substitution key used for default send proposal email +FIX: button to pay still visible when amount null used +FIX: clause must not be there +FIX: Contact tab not visible when using canvas +FIX: dol_delete_file must work in a context without db handler loaded +FIX: entity test must be on product_fourn_price table and not product table +FIX: Fetch shipping will now fetch project id +FIX: If we enable 3 steps for supplier order approbation, we must not delete all fourn rights def. +FIX: intervention: extrafield error when calling insertExtrafields +FIX: It's not possible to remove a contact which is assigned to an event #8852 +FIX: javascript showempty error +FIX: Keep supplier proposal price for supplier order +FIX: link for projets not linked to a thirdparties +FIX: Missing extrafields in export of stock or products +FIX: missing filters during ordering +FIX: missing filters during reordering +FIX: missing parenthesis +FIX: need to filter on aa.entity for same accounting accounts available in several entities +FIX: picto for type in product link in accountany list is wrong +FIX: Problems in accountancy module when using multicompany module. +FIX: proposal: missing contact type translation key +FIX: pu_ht_devise was not converted to numeric so decimals were lost when calculating total_ht_devise +FIX: Select user on add time spent form +FIX: shipment: fk_proje(c)t not handled in fetch() and update() methods +FIX: sometimes amounts are identical but php find them different. +FIX: supplier order: product supplier ref not saved on addline +FIX: test is_erasable() must be done before call function delete() too to avoid delete invoice with &action=delete in url +FIX: wrong var name $search_month_lim ***** ChangeLog for 7.0.2 compared to 7.0.1 ***** FIX: #8023 From 16f940b637453cdb76361dab71f21ad6285f93c7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 23 Jun 2018 14:55:33 +0200 Subject: [PATCH 12/20] Prepare 7.0.4 --- htdocs/filefunc.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/filefunc.inc.php b/htdocs/filefunc.inc.php index b8126b4fcc8..adfe8cea7e9 100644 --- a/htdocs/filefunc.inc.php +++ b/htdocs/filefunc.inc.php @@ -31,7 +31,7 @@ */ if (! defined('DOL_APPLICATION_TITLE')) define('DOL_APPLICATION_TITLE','Dolibarr'); -if (! defined('DOL_VERSION')) define('DOL_VERSION','7.0.3'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c +if (! defined('DOL_VERSION')) define('DOL_VERSION','7.0.4'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c if (! defined('EURO')) define('EURO',chr(128)); From bc716852583ceaef638ec674b714215737f5084a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jun 2018 08:30:37 +0200 Subject: [PATCH 13/20] Fix migration error --- htdocs/install/mysql/migration/6.0.0-7.0.0.sql | 5 +++++ htdocs/install/mysql/migration/repair.sql | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql index cf0a8c8cc49..ee4fd5f15b4 100644 --- a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql +++ b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql @@ -36,6 +36,11 @@ ALTER TABLE llx_accounting_account DROP FOREIGN KEY fk_accountingaccount_fk_pcg_ -- Drop foreign key, so next alter will be a success -- VMYSQLUTF8UNICODECI ALTER TABLE llx_accounting_account DROP FOREIGN KEY fk_accounting_account_fk_pcg_version; +-- VMYSQL4.1 SET sql_mode = 'ALLOW_INVALID_DATES'; +-- VMYSQL4.1 update llx_accounting_account set tms = datec where DATE(STR_TO_DATE(tms, '%Y-%m-%d')) IS NULL; +-- VMYSQL4.1 SET sql_mode = 'NO_ZERO_DATE'; +-- VMYSQL4.1 update llx_accounting_account set tms = datec where DATE(STR_TO_DATE(tms, '%Y-%m-%d')) IS NULL; + -- VMYSQLUTF8UNICODECI ALTER TABLE llx_accounting_account MODIFY fk_pcg_version VARCHAR(20) CHARACTER SET utf8; -- VMYSQLUTF8UNICODECI ALTER TABLE llx_accounting_account MODIFY fk_pcg_version VARCHAR(20) COLLATE utf8_unicode_ci; -- VMYSQLUTF8UNICODECI ALTER TABLE llx_accounting_system MODIFY pcg_version VARCHAR(20) CHARACTER SET utf8; diff --git a/htdocs/install/mysql/migration/repair.sql b/htdocs/install/mysql/migration/repair.sql index 5f2851fd142..bcf3daaa37f 100755 --- a/htdocs/install/mysql/migration/repair.sql +++ b/htdocs/install/mysql/migration/repair.sql @@ -387,6 +387,11 @@ drop table tmp_bank_url_expense_user; -- where price = 17.5 +-- VMYSQL4.1 SET sql_mode = 'ALLOW_INVALID_DATES'; +-- VMYSQL4.1 update llx_accounting_account set tms = datec where DATE(STR_TO_DATE(tms, '%Y-%m-%d')) IS NULL; +-- VMYSQL4.1 SET sql_mode = 'NO_ZERO_DATE'; +-- VMYSQL4.1 update llx_accounting_account set tms = datec where DATE(STR_TO_DATE(tms, '%Y-%m-%d')) IS NULL; + -- VMYSQL4.1 SET sql_mode = 'ALLOW_INVALID_DATES'; -- VMYSQL4.1 update llx_expensereport set date_debut = date_create where DATE(STR_TO_DATE(date_debut, '%Y-%m-%d')) IS NULL; -- VMYSQL4.1 SET sql_mode = 'NO_ZERO_DATE'; From 97976fbb43a04ce249333407cbf21ac8b567314d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jun 2018 09:19:45 +0200 Subject: [PATCH 14/20] Fix type of parameter must be string --- htdocs/core/class/html.form.class.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 0cce4c21920..57783c09885 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1428,12 +1428,12 @@ class Form * @param int $disabled If select list must be disabled * @param array $include Array list of users id to include * @param int $enableonly Array list of users id to be enabled. All other must be disabled - * @param int $force_entity 0 or Id of environment to force + * @param string $force_entity '0' or Ids of environment to force * @return void * @deprecated Use select_dolusers instead * @see select_dolusers() */ - function select_users($selected='',$htmlname='userid',$show_empty=0,$exclude=null,$disabled=0,$include='',$enableonly='',$force_entity=0) + function select_users($selected='',$htmlname='userid',$show_empty=0,$exclude=null,$disabled=0,$include='',$enableonly='',$force_entity='0') { print $this->select_dolusers($selected,$htmlname,$show_empty,$exclude,$disabled,$include,$enableonly,$force_entity); } @@ -1448,7 +1448,7 @@ class Form * @param int $disabled If select list must be disabled * @param array|string $include Array list of users id to include or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me * @param array $enableonly Array list of users id to be enabled. If defined, it means that others will be disabled - * @param int $force_entity 0 or Id of environment to force + * @param string $force_entity '0' or Ids of environment to force * @param int $maxlength Maximum length of string into list (0=no limit) * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status * @param string $morefilter Add more filters into sql request (Example: 'employee = 1') @@ -1459,7 +1459,7 @@ class Form * @return string HTML select string * @see select_dolgroups */ - function select_dolusers($selected='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include='', $enableonly='', $force_entity=0, $maxlength=0, $showstatus=0, $morefilter='', $show_every=0, $enableonlytext='', $morecss='', $noactive=0) + function select_dolusers($selected='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include='', $enableonly='', $force_entity='0', $maxlength=0, $showstatus=0, $morefilter='', $show_every=0, $enableonlytext='', $morecss='', $noactive=0) { global $conf,$user,$langs; @@ -1595,13 +1595,13 @@ class Form } if (! empty($conf->multicompany->enabled) && empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) && $conf->entity == 1 && $user->admin && ! $user->entity) { - if ($obj->admin && ! $obj->entity) + if (! $obj->entity) { $out.=($moreinfo?' - ':' (').$langs->trans("AllEntities"); $moreinfo++; } else - { + { $out.=($moreinfo?' - ':' (').($obj->label?$obj->label:$langs->trans("EntityNameNotDefined")); $moreinfo++; } @@ -1643,7 +1643,7 @@ class Form * @param int $disabled If select list must be disabled * @param array $include Array list of users id to include or 'hierarchy' to have only supervised users * @param array $enableonly Array list of users id to be enabled. All other must be disabled - * @param int $force_entity 0 or Id of environment to force + * @param int $force_entity '0' or Ids of environment to force * @param int $maxlength Maximum length of string into list (0=no limit) * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status * @param string $morefilter Add more filters into sql request @@ -1654,7 +1654,7 @@ class Form * @return string HTML select string * @see select_dolgroups */ - function select_dolusers_forevent($action='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include='', $enableonly='', $force_entity=0, $maxlength=0, $showstatus=0, $morefilter='', $showproperties=0, $listofuserid=array(), $listofcontactid=array(), $listofotherid=array()) + function select_dolusers_forevent($action='', $htmlname='userid', $show_empty=0, $exclude=null, $disabled=0, $include='', $enableonly='', $force_entity='0', $maxlength=0, $showstatus=0, $morefilter='', $showproperties=0, $listofuserid=array(), $listofcontactid=array(), $listofotherid=array()) { global $conf, $user, $langs; @@ -6531,11 +6531,11 @@ class Form * @param int $disabled If select list must be disabled * @param string $include Array list of groups id to include * @param int $enableonly Array list of groups id to be enabled. All other must be disabled - * @param int $force_entity 0 or Id of environment to force + * @param string $force_entity '0' or Ids of environment to force * @return string * @see select_dolusers */ - function select_dolgroups($selected='', $htmlname='groupid', $show_empty=0, $exclude='', $disabled=0, $include='', $enableonly='', $force_entity=0) + function select_dolgroups($selected='', $htmlname='groupid', $show_empty=0, $exclude='', $disabled=0, $include='', $enableonly='', $force_entity='0') { global $conf,$user,$langs; From d9fc1e0b5dacae0a2b4ad6cd986411e9c741d22d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jun 2018 10:09:01 +0200 Subject: [PATCH 15/20] Fix param to avoid to create holiday or expense report in wrong entity. --- htdocs/expensereport/card.php | 2 +- htdocs/holiday/card.php | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index 2c63101b6fd..5883a207a1d 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -1360,7 +1360,7 @@ if ($action == 'create') if (GETPOST('fk_user_author', 'int') > 0) $defaultselectuser=GETPOST('fk_user_author', 'int'); $include_users = 'hierarchyme'; if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expensereport->writeall_advance)) $include_users=array(); - $s=$form->select_dolusers($defaultselectuser, "fk_user_author", 0, "", 0, $include_users); + $s=$form->select_dolusers($defaultselectuser, "fk_user_author", 0, "", 0, $include_users, '', '0,'.$conf->entity); print $s; print ''; print ''; diff --git a/htdocs/holiday/card.php b/htdocs/holiday/card.php index 1305a6b25f0..b19f63e0ab3 100644 --- a/htdocs/holiday/card.php +++ b/htdocs/holiday/card.php @@ -868,12 +868,13 @@ if (empty($id) || $action == 'add' || $action == 'request' || $action == 'create print ''; print ''; print ''; print ''; From 36402c22eef49d60edd73a2f312f8e28fe0bd1cb Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jun 2018 14:06:09 +0200 Subject: [PATCH 16/20] FIX SQL Injections reported by mu shcor (ADLab of Venustech) --- htdocs/core/class/html.form.class.php | 5 +++- htdocs/main.inc.php | 16 +++++++---- htdocs/product/card.php | 40 +++++++++++++-------------- htdocs/societe/ajax/company.php | 2 +- 4 files changed, 35 insertions(+), 28 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 57783c09885..547bd8ad4e4 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1044,7 +1044,7 @@ class Form * * @param string $selected Preselected type * @param string $htmlname Name of field in form - * @param string $filter optional filters criteras (example: 's.rowid <> x', 's.client in (1,3)') + * @param string $filter Optional filters criteras (example: 's.rowid <> x', 's.client in (1,3)') * @param string $showempty Add an empty field (Can be '1' or text to use on empty line like 'SelectThirdParty') * @param int $showtype Show third party type in combolist (customer, prospect or supplier) * @param int $forcecombo Force to use standard HTML select component without beautification @@ -1064,6 +1064,9 @@ class Form $num=0; $outarray=array(); + // Clean $filter that may contains sql conditions so sql code + if (function_exists('test_sql_and_script_inject')) $filter = test_sql_and_script_inject($filter, 3); + // On recherche les societes $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.client, s.fournisseur, s.code_client, s.code_fournisseur"; $sql.= " FROM ".MAIN_DB_PREFIX ."societe as s"; diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index e9b17ed23ba..daa0dda21a5 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -72,24 +72,30 @@ if (function_exists('get_magic_quotes_gpc')) // magic_quotes_* deprecated in PHP * Security: SQL Injection and XSS Injection (scripts) protection (Filters on GET, POST, PHP_SELF). * * @param string $val Value - * @param string $type 1=GET, 0=POST, 2=PHP_SELF + * @param string $type 1=GET, 0=POST, 2=PHP_SELF, 3=GET without sql reserved keywords (the less tolerant test) * @return int >0 if there is an injection, 0 if none */ function test_sql_and_script_inject($val, $type) { $inj = 0; // For SQL Injection (only GET are used to be included into bad escaped SQL requests) - if ($type == 1) + if ($type == 1 || $type == 3) { - $inj += preg_match('/updatexml\(/i', $val); $inj += preg_match('/delete\s+from/i', $val); $inj += preg_match('/create\s+table/i', $val); $inj += preg_match('/insert\s+into/i', $val); $inj += preg_match('/select\s+from/i', $val); $inj += preg_match('/into\s+(outfile|dumpfile)/i', $val); + $inj += preg_match('/user\s*\(/i', $val); // avoid to use function user() that return current database login + $inj += preg_match('/information_schema/i', $val); // avoid to use request that read information_schema database } - if ($type != 2) // Not common, we can check on POST + if ($type == 3) { + $inj += preg_match('/select|update|delete|replace|group\s+by|concat|count|from/i', $val); + } + if ($type != 2) // Not common key strings, so we can check them both on GET and POST + { + $inj += preg_match('/updatexml\(/i', $val); $inj += preg_match('/update.+set.+=/i', $val); $inj += preg_match('/union.+select/i', $val); $inj += preg_match('/(\.\.%2f)+/i', $val); @@ -1558,8 +1564,6 @@ function top_menu($head, $title='', $target='', $disablejs=0, $disablehead=0, $a print "\n"; print ''; - //unset($form); - print '
'; print "\n\n"; } diff --git a/htdocs/product/card.php b/htdocs/product/card.php index e06d2c4569d..1e6995fff35 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -289,8 +289,8 @@ if (empty($reshook)) $object->url = GETPOST('url'); $object->note_private = dol_htmlcleanlastbr(GETPOST('note_private','none')); $object->note = $object->note_private; // deprecated - $object->customcode = GETPOST('customcode'); - $object->country_id = GETPOST('country_id'); + $object->customcode = GETPOST('customcode','alpha'); + $object->country_id = GETPOST('country_id','int'); $object->duration_value = $duration_value; $object->duration_unit = $duration_unit; $object->seuil_stock_alerte = GETPOST('seuil_stock_alerte')?GETPOST('seuil_stock_alerte'):0; @@ -306,13 +306,13 @@ if (empty($reshook)) $object->surface_units = GETPOST('surface_units'); $object->volume = GETPOST('volume'); $object->volume_units = GETPOST('volume_units'); - $object->finished = GETPOST('finished'); - $object->fk_unit = GETPOST('units'); + $object->finished = GETPOST('finished','alpha'); + $object->fk_unit = GETPOST('units','alpha'); - $accountancy_code_sell = GETPOST('accountancy_code_sell'); - $accountancy_code_sell_intra = GETPOST('accountancy_code_sell_intra'); - $accountancy_code_sell_export = GETPOST('accountancy_code_sell_export'); - $accountancy_code_buy = GETPOST('accountancy_code_buy'); + $accountancy_code_sell = GETPOST('accountancy_code_sell','alpha'); + $accountancy_code_sell_intra = GETPOST('accountancy_code_sell_intra','alpha'); + $accountancy_code_sell_export = GETPOST('accountancy_code_sell_export','alpha'); + $accountancy_code_buy = GETPOST('accountancy_code_buy','alpha'); if ($accountancy_code_sell <= 0) { $object->accountancy_code_sell = ''; } else { $object->accountancy_code_sell = $accountancy_code_sell; } if ($accountancy_code_sell_intra <= 0) { $object->accountancy_code_sell_intra = ''; } else { $object->accountancy_code_sell_intra = $accountancy_code_sell_intra; } @@ -385,11 +385,11 @@ if (empty($reshook)) $object->note_private = dol_htmlcleanlastbr(GETPOST('note_private','none')); $object->note = $object->note_private; } - $object->customcode = GETPOST('customcode'); - $object->country_id = GETPOST('country_id'); - $object->status = GETPOST('statut'); - $object->status_buy = GETPOST('statut_buy'); - $object->status_batch = GETPOST('status_batch'); + $object->customcode = GETPOST('customcode','alpha'); + $object->country_id = GETPOST('country_id','int'); + $object->status = GETPOST('statut','int'); + $object->status_buy = GETPOST('statut_buy','int'); + $object->status_batch = GETPOST('status_batch','aZ09'); // removed from update view so GETPOST always empty /* $object->seuil_stock_alerte = GETPOST('seuil_stock_alerte'); @@ -410,7 +410,7 @@ if (empty($reshook)) $object->surface_units = GETPOST('surface_units'); $object->volume = GETPOST('volume'); $object->volume_units = GETPOST('volume_units'); - $object->finished = GETPOST('finished'); + $object->finished = GETPOST('finished','alpha'); $units = GETPOST('units', 'int'); @@ -437,10 +437,10 @@ if (empty($reshook)) $object->barcode_type_coder = $stdobject->barcode_type_coder; $object->barcode_type_label = $stdobject->barcode_type_label; - $accountancy_code_sell = GETPOST('accountancy_code_sell'); - $accountancy_code_sell_intra = GETPOST('accountancy_code_sell_intra'); - $accountancy_code_sell_export = GETPOST('accountancy_code_sell_export'); - $accountancy_code_buy = GETPOST('accountancy_code_buy'); + $accountancy_code_sell = GETPOST('accountancy_code_sell','alpha'); + $accountancy_code_sell_intra = GETPOST('accountancy_code_sell_intra','alpha'); + $accountancy_code_sell_export = GETPOST('accountancy_code_sell_export','alpha'); + $accountancy_code_buy = GETPOST('accountancy_code_buy','alpha'); if ($accountancy_code_sell <= 0) { $object->accountancy_code_sell = ''; } else { $object->accountancy_code_sell = $accountancy_code_sell; } if ($accountancy_code_sell_intra <= 0) { $object->accountancy_code_sell_intra = ''; } else { $object->accountancy_code_sell_intra = $accountancy_code_sell_intra; } @@ -1303,7 +1303,7 @@ else print ''; // Batch number managment - if ($conf->productbatch->enabled) + if ($conf->productbatch->enabled) { if ($object->isProduct() || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) { @@ -1723,7 +1723,7 @@ else print ''; // Batch number management (to batch) - if (! empty($conf->productbatch->enabled)) + if (! empty($conf->productbatch->enabled)) { if ($object->isProduct() || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) { diff --git a/htdocs/societe/ajax/company.php b/htdocs/societe/ajax/company.php index 349e19b0c26..d62c8a445d6 100644 --- a/htdocs/societe/ajax/company.php +++ b/htdocs/societe/ajax/company.php @@ -87,7 +87,7 @@ else if (! $searchkey) return; - $form = new Form($db); + if (! is_object($form)) $form = new Form($db); $arrayresult=$form->select_thirdparty_list(0, $htmlname, $filter, 1, $showtype, 0, null, $searchkey, $outjson); $db->close(); From 9b46ae50f01e78e8cdef2f474cbf32630be399e2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jun 2018 16:25:37 +0200 Subject: [PATCH 17/20] Fix left join on expensereport lines --- htdocs/expensereport/class/expensereport.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/expensereport/class/expensereport.class.php b/htdocs/expensereport/class/expensereport.class.php index c50b4ce2cb3..c6debbe60ff 100644 --- a/htdocs/expensereport/class/expensereport.class.php +++ b/htdocs/expensereport/class/expensereport.class.php @@ -2428,7 +2428,7 @@ class ExpenseReportLine $sql.= ' ctf.code as type_fees_code, ctf.label as type_fees_libelle,'; $sql.= ' pjt.rowid as projet_id, pjt.title as projet_title, pjt.ref as projet_ref'; $sql.= ' FROM '.MAIN_DB_PREFIX.'expensereport_det as fde'; - $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'c_type_fees as ctf ON fde.fk_c_type_fees=ctf.id'; + $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_type_fees as ctf ON fde.fk_c_type_fees=ctf.id'; // Sometimes type of expense report has been removed, so we use a left join here. $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'projet as pjt ON fde.fk_projet=pjt.rowid'; $sql.= ' WHERE fde.rowid = '.$rowid; From 9f77ea0ece8d9ecf427fc4862127e80cd1fdc612 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 25 Jun 2018 17:01:37 +0200 Subject: [PATCH 18/20] Code comment --- htdocs/core/lib/company.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index b38f770e071..b79f4f7d806 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -398,7 +398,7 @@ function societe_admin_prepare_head() * @param Translate $outputlangs Langs object for output translation * @param int $entconv 0=Return value without entities and not converted to output charset, 1=Ready for html output * @param int $searchlabel Label of country to search (warning: searching on label is not reliable) - * @return mixed String with country code or translated country name or Array('id','code','label') + * @return mixed Integer with country id or String with country code or translated country name or Array('id','code','label') or 'NotDefined' */ function getCountry($searchkey, $withcode='', $dbtouse=0, $outputlangs='', $entconv=1, $searchlabel='') { From 52eddbf809d0976c11ff6b57d1dba877b7c38e86 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 26 Jun 2018 00:29:50 +0200 Subject: [PATCH 19/20] Sync transifex --- htdocs/langs/fr_FR/other.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/fr_FR/other.lang b/htdocs/langs/fr_FR/other.lang index b39175a16c3..cb8bf69a4e3 100644 --- a/htdocs/langs/fr_FR/other.lang +++ b/htdocs/langs/fr_FR/other.lang @@ -82,7 +82,7 @@ PredefinedMailTest=__(Hello)__,\nCeci est un mail de test envoyé à __EMAIL__.\ PredefinedMailTestHtml=__(Hello)__\nCeci est un message de test (le mot test doit être en gras).
Les 2 lignes sont séparées par un retour à la ligne.

__SIGNATURE__ PredefinedMailContentSendInvoice=__(Hello)__\n\nVous trouverez ci-joint la facture __REF__\n\nVoici le lien pour effectuer votre paiement en ligne si elle n'est pas déjà été payée:\n__ONLINE_PAYMENT_URL__\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ PredefinedMailContentSendInvoiceReminder=__(Hello)__\n\nNous souhaitons vous prévenir que la facture __REF__ ne semble pas avoir été payée. Voici donc la facture en pièce jointe, à titre de rappel.\n\nVoici le lien pour effectuer votre paiement en ligne:\n__ONLINE_PAYMENT_URL__\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ -PredefinedMailContentSendProposal=__(Hello)__\n\nVeuillez trouver, ci-joint, la proposition commerciale __PREF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ +PredefinedMailContentSendProposal=__(Hello)__\n\nVeuillez trouver, ci-joint, la proposition commerciale __REF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ PredefinedMailContentSendSupplierProposal=__(Hello)__\n\nVeuillez trouver, ci-joint, une demande de prix avec la référence __REF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ PredefinedMailContentSendOrder=__(Hello)__\n\nVeuillez trouver, ci-joint, la commande __REF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ PredefinedMailContentSendSupplierOrder=__(Hello)__\n\nVeuillez trouver, ci-joint, notre commande __REF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ From 7f8570f7202da188aa581fa1ef731987b6a16c11 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 26 Jun 2018 00:48:43 +0200 Subject: [PATCH 20/20] Fix lang loading --- htdocs/compta/facture/fiche-rec.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/htdocs/compta/facture/fiche-rec.php b/htdocs/compta/facture/fiche-rec.php index bb6358ed160..4519fd24f6a 100644 --- a/htdocs/compta/facture/fiche-rec.php +++ b/htdocs/compta/facture/fiche-rec.php @@ -43,10 +43,7 @@ require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php'; require_once DOL_DOCUMENT_ROOT . '/core/lib/invoice.lib.php'; require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php'; -$langs->load('bills'); -$langs->load('compta'); -$langs->load('admin'); -$langs->load('other'); +$langs->loadLangs(array('bills','compta','admin','other','products')); $action = GETPOST('action','alpha'); $massaction = GETPOST('massaction','alpha');
'.$line['seuil_stock_alerte'].''.$line['desiredstock'].''.img_delete().''.img_delete().'
'.$langs->trans("User").''; + if (empty($user->rights->holiday->write_all)) { - print $form->select_dolusers(($fuserid?$fuserid:$user->id), 'fuserid', 0, '', 0, 'hierarchyme', '', 0, 0, 0, $morefilter, 0, '', 'maxwidth300'); + print $form->select_dolusers(($fuserid?$fuserid:$user->id), 'fuserid', 0, '', 0, 'hierarchyme', '', '0,'.$conf->entity, 0, 0, $morefilter, 0, '', 'maxwidth300'); //print ''; } - else print $form->select_dolusers(GETPOST('fuserid','int')?GETPOST('fuserid','int'):$user->id, 'fuserid', 0, '', 0, '', '', 0, 0, 0, $morefilter, 0, '', 'maxwidth300'); + else print $form->select_dolusers(GETPOST('fuserid','int')?GETPOST('fuserid','int'):$user->id, 'fuserid', 0, '', 0, '', '', '0,'.$conf->entity, 0, 0, $morefilter, 0, '', 'maxwidth300'); print '