From e31a93929a0c26724bda4000571fbd4d2e18ee28 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Wed, 29 Jan 2020 14:01:48 +0100 Subject: [PATCH 01/36] FIX doc of dictionnary API --- htdocs/api/class/api_setup.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/api/class/api_setup.class.php b/htdocs/api/class/api_setup.class.php index a42888aad27..f5ed406a2a1 100644 --- a/htdocs/api/class/api_setup.class.php +++ b/htdocs/api/class/api_setup.class.php @@ -53,7 +53,7 @@ class Setup extends DolibarrApi * @param int $limit Number of items per page * @param int $page Page number {@min 0} * @param int $active Payment type is active or not {@min 0} {@max 1} - * @param string $sqlfilters SQL criteria to filter with. Syntax example "(t.code:=:'CHQ')" + * @param string $sqlfilters SQL criteria to filter with. Syntax example "(t.code:=:'OrderByWWW')" * * @url GET dictionary/ordering_methods * @@ -911,7 +911,7 @@ class Setup extends DolibarrApi * @throws 400 RestException * @throws 200 OK */ - public function getPaymentTerms($sortfield = "sortorder", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '') + public function getPaymentTerms($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '') { $list = array(); From 314456f812b425f2b6162e6fa85784405b4f177b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 30 Jan 2020 13:03:33 +0100 Subject: [PATCH 02/36] Fix var not defined --- htdocs/resource/class/dolresource.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/resource/class/dolresource.class.php b/htdocs/resource/class/dolresource.class.php index 4af42ea8ff2..bf9acde2d50 100644 --- a/htdocs/resource/class/dolresource.class.php +++ b/htdocs/resource/class/dolresource.class.php @@ -948,7 +948,7 @@ class Dolresource extends CommonObject */ public function getNomUrl($withpicto = 0, $option = '', $get_params = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) { - global $langs; + global $conf, $langs; $result = ''; $label = ''.$langs->trans("ShowResource").''; From 8f2c87b0d4af8d557b881a13e6dc902ca624b807 Mon Sep 17 00:00:00 2001 From: ptibogxiv Date: Thu, 30 Jan 2020 13:52:13 +0100 Subject: [PATCH 03/36] Update api_setup.class.php --- htdocs/api/class/api_setup.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/api/class/api_setup.class.php b/htdocs/api/class/api_setup.class.php index f5ed406a2a1..66c4c1358cb 100644 --- a/htdocs/api/class/api_setup.class.php +++ b/htdocs/api/class/api_setup.class.php @@ -911,7 +911,7 @@ class Setup extends DolibarrApi * @throws 400 RestException * @throws 200 OK */ - public function getPaymentTerms($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '') + public function getPaymentTerms($sortfield = "sortorder", $sortorder = 'ASC', $limit = 100, $page = 0, $active = 1, $sqlfilters = '') { $list = array(); From d60ce8a2c3e318abb397b06da51146a6d89f5c08 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 30 Jan 2020 20:00:41 +0100 Subject: [PATCH 04/36] Fix showoncombobox --- htdocs/contact/class/contact.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 038cb82845e..56ba2e24def 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -72,8 +72,8 @@ class Contact extends CommonObject 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>0, 'notnull'=>1, 'position'=>30, 'index'=>1), 'ref_ext' =>array('type'=>'varchar(255)', 'label'=>'Ref ext', 'enabled'=>1, 'visible'=>0, 'position'=>35), 'civility' =>array('type'=>'varchar(6)', 'label'=>'Civility', 'enabled'=>1, 'visible'=>-1, 'position'=>40), - 'lastname' =>array('type'=>'varchar(50)', 'label'=>'Lastname', 'enabled'=>1, 'visible'=>-1, 'position'=>45), - 'firstname' =>array('type'=>'varchar(50)', 'label'=>'Firstname', 'enabled'=>1, 'visible'=>-1, 'position'=>50), + 'lastname' =>array('type'=>'varchar(50)', 'label'=>'Lastname', 'enabled'=>1, 'visible'=>-1, 'position'=>45, 'showoncombobox'=>1), + 'firstname' =>array('type'=>'varchar(50)', 'label'=>'Firstname', 'enabled'=>1, 'visible'=>-1, 'position'=>50, 'showoncombobox'=>1), 'address' =>array('type'=>'varchar(255)', 'label'=>'Address', 'enabled'=>1, 'visible'=>-1, 'position'=>55), 'zip' =>array('type'=>'varchar(25)', 'label'=>'Zip', 'enabled'=>1, 'visible'=>-1, 'position'=>60), 'town' =>array('type'=>'text', 'label'=>'Town', 'enabled'=>1, 'visible'=>-1, 'position'=>65), From 1c24bcc7248fda053f60913e4e665d05c3e8d362 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 31 Jan 2020 10:29:41 +0100 Subject: [PATCH 05/36] FIX CVE Need permission to be able to develop modules --- htdocs/core/modules/modModuleBuilder.class.php | 16 ++++++++++++++++ htdocs/modulebuilder/index.php | 3 +++ 2 files changed, 19 insertions(+) diff --git a/htdocs/core/modules/modModuleBuilder.class.php b/htdocs/core/modules/modModuleBuilder.class.php index 16ee16984d8..1c52ad866c2 100644 --- a/htdocs/core/modules/modModuleBuilder.class.php +++ b/htdocs/core/modules/modModuleBuilder.class.php @@ -45,6 +45,7 @@ class modModuleBuilder extends DolibarrModules // Family can be 'crm','financial','hr','projects','products','ecm','technic','other' // It is used to group modules in module setup page $this->family = "technic"; + $this->module_position = '90'; // Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module) $this->name = preg_replace('/^mod/i', '', get_class($this)); $this->description = "A RAD (Rapid Application Development) tool to help developers to build their own module."; @@ -82,6 +83,21 @@ class modModuleBuilder extends DolibarrModules //------ $this->boxes = array(); + // Permissions + //------------ + $this->rights = array(); // Permission array used by this module + $this->rights_class = 'modulebuilder'; + + $r=0; + + $r++; + $this->rights[$r][0] = 3301; + $this->rights[$r][1] = 'Generate new modules'; + $this->rights[$r][2] = 'a'; + $this->rights[$r][3] = 0; + $this->rights[$r][4] = 'run'; + + // Main menu entries //------------------ $this->menu = array(); diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 51e35ab050a..0afcd403406 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -90,6 +90,9 @@ if (empty($newmask)) // This should no happen $newmask = '0664'; } +$result = restrictedArea($user, 'modulebuilder', null); + + /* * Actions From 8e18a08377d550d1a177c0403c71055ef5b1ed9d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 31 Jan 2020 16:59:10 +0100 Subject: [PATCH 06/36] Fix log of proxy forward only if it differs from remote_addr --- 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 e4a200fceff..17fa72e43b0 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1059,7 +1059,7 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename = ); // This is when server run behind a reverse proxy - if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) $data['ip'] = $_SERVER['HTTP_X_FORWARDED_FOR'].(empty($_SERVER["REMOTE_ADDR"]) ? '' : '->'.$_SERVER['REMOTE_ADDR']); + if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) $data['ip'] = $_SERVER['HTTP_X_FORWARDED_FOR'].((empty($_SERVER["REMOTE_ADDR"]) || ($_SERVER['HTTP_X_FORWARDED_FOR'] == $_SERVER['REMOTE_ADDR'])) ? '' : '->'.$_SERVER['REMOTE_ADDR']); // This is when server run normally on a server elseif (!empty($_SERVER["REMOTE_ADDR"])) $data['ip'] = $_SERVER['REMOTE_ADDR']; // This is when PHP session is ran inside a web server but not inside a client request (example: init code of apache) From b81d223ab3eb4f05a698bbe07a44181378e45f72 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 31 Jan 2020 17:27:48 +0100 Subject: [PATCH 07/36] Do no retry ping after error the same month --- htdocs/core/ajax/pingresult.php | 4 +- htdocs/main.inc.php | 121 +++++++++++++++++--------------- 2 files changed, 67 insertions(+), 58 deletions(-) diff --git a/htdocs/core/ajax/pingresult.php b/htdocs/core/ajax/pingresult.php index 0dbb5167f9e..7e9fad309d4 100644 --- a/htdocs/core/ajax/pingresult.php +++ b/htdocs/core/ajax/pingresult.php @@ -53,8 +53,8 @@ print ''; $hash_unique_id = md5('dolibarr'.$conf->file->instance_unique_id); if (empty($conf->global->MAIN_FIRST_PING_OK_DATE) || (!empty($conf->file->instance_unique_id) && ($hash_unique_id != $conf->global->MAIN_FIRST_PING_OK_ID) && ($conf->global->MAIN_FIRST_PING_OK_ID != 'disabled')) - || GETPOST('forceping', 'alpha')) + || $forceping) { - if (strpos('alpha', DOL_VERSION) > 0) { + // No ping done if we are into an alpha version + if (strpos('alpha', DOL_VERSION) > 0 && ! $forceping) { print "\n\n"; } - elseif (empty($_COOKIE['DOLINSTALLNOPING_'.$hash_unique_id])) // Cookie is set when we uncheck the checkbox in the installation wizard. + elseif (empty($_COOKIE['DOLINSTALLNOPING_'.$hash_unique_id]) || $forceping) // Cookie is set when we uncheck the checkbox in the installation wizard. { - include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + // MAIN_LAST_PING_KO_DATE + // TODO Disable ping if MAIN_LAST_PING_KO_DATE is set and is recent + if (! empty($conf->global->MAIN_LAST_PING_KO_DATE) && substr($conf->global->MAIN_LAST_PING_KO_DATE, 0, 6) == dol_print_date(dol_now(), '%Y%m') && ! $forceping) { + print "\n\n"; + } else { - print "\n".''."\n"; - print "\n\n"; - $url_for_ping = (empty($conf->global->MAIN_URL_FOR_PING) ? "https://ping.dolibarr.org/" : $conf->global->MAIN_URL_FOR_PING); - // Try to guess the distrib used - $distrib = 'standard'; - if ($_SERVER["SERVER_ADMIN"] == 'doliwamp@localhost') $distrib = 'doliwamp'; - if (! empty($dolibarr_distrib)) $distrib = $dolibarr_distrib; - ?> - - global->MAIN_FIRST_PING_OK_DATE.' MAIN_FIRST_PING_OK_ID='.$conf->global->MAIN_FIRST_PING_OK_ID.' MAIN_LAST_PING_KO_DATE='.$conf->global->MAIN_LAST_PING_KO_DATE.' -->'."\n"; + print "\n\n"; + $url_for_ping = (empty($conf->global->MAIN_URL_FOR_PING) ? "https://ping.dolibarr.org/" : $conf->global->MAIN_URL_FOR_PING); + // Try to guess the distrib used + $distrib = 'standard'; + if ($_SERVER["SERVER_ADMIN"] == 'doliwamp@localhost') $distrib = 'doliwamp'; + if (! empty($dolibarr_distrib)) $distrib = $dolibarr_distrib; + ?> + + Date: Fri, 31 Jan 2020 17:51:30 +0100 Subject: [PATCH 08/36] Fix log through proxy --- htdocs/core/lib/functions.lib.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 17fa72e43b0..5bc3ad0056c 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -1058,10 +1058,13 @@ function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename = 'ip' => false ); - // This is when server run behind a reverse proxy - if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) $data['ip'] = $_SERVER['HTTP_X_FORWARDED_FOR'].((empty($_SERVER["REMOTE_ADDR"]) || ($_SERVER['HTTP_X_FORWARDED_FOR'] == $_SERVER['REMOTE_ADDR'])) ? '' : '->'.$_SERVER['REMOTE_ADDR']); - // This is when server run normally on a server - elseif (!empty($_SERVER["REMOTE_ADDR"])) $data['ip'] = $_SERVER['REMOTE_ADDR']; + $remoteip = getUserRemoteIP(); // Get ip when page run on a web server + if (! empty($remoteip)) { + $data['ip'] = $remoteip; + // This is when server run behind a reverse proxy + if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] != $remoteip) $data['ip'] = $_SERVER['HTTP_X_FORWARDED_FOR'].' -> '.$data['ip']; + elseif (!empty($_SERVER['HTTP_CLIENT_IP']) && $_SERVER['HTTP_CLIENT_IP'] != $remoteip) $data['ip'] = $_SERVER['HTTP_CLIENT_IP'].' -> '.$data['ip']; + } // This is when PHP session is ran inside a web server but not inside a client request (example: init code of apache) elseif (!empty($_SERVER['SERVER_ADDR'])) $data['ip'] = $_SERVER['SERVER_ADDR']; // This is when PHP session is ran outside a web server, like from Windows command line (Not always defined, but useful if OS defined it). From b83c90e348676c2d6bc6da9649b1021bc694acee Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 31 Jan 2020 18:02:18 +0100 Subject: [PATCH 09/36] Fix phpcs --- htdocs/main.inc.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 267d65fd8e1..d396ad4cadc 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -2569,11 +2569,10 @@ if (!function_exists("llxFooter")) elseif (empty($_COOKIE['DOLINSTALLNOPING_'.$hash_unique_id]) || $forceping) // Cookie is set when we uncheck the checkbox in the installation wizard. { // MAIN_LAST_PING_KO_DATE - // TODO Disable ping if MAIN_LAST_PING_KO_DATE is set and is recent + // Disable ping if MAIN_LAST_PING_KO_DATE is set and is recent if (! empty($conf->global->MAIN_LAST_PING_KO_DATE) && substr($conf->global->MAIN_LAST_PING_KO_DATE, 0, 6) == dol_print_date(dol_now(), '%Y%m') && ! $forceping) { print "\n\n"; } else { - include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; print "\n".''."\n"; From d530c7f7089a7344a6ea4d80c7ce3d2f9453831c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 31 Jan 2020 18:16:16 +0100 Subject: [PATCH 10/36] Try fix for #12984 --- htdocs/product/index.php | 332 ++++++++++++++++++++------------------- 1 file changed, 169 insertions(+), 163 deletions(-) diff --git a/htdocs/product/index.php b/htdocs/product/index.php index d885b36a877..49df2b36cc9 100644 --- a/htdocs/product/index.php +++ b/htdocs/product/index.php @@ -40,7 +40,7 @@ if ($type == '' && !$user->rights->service->lire) $type = '0'; // Force global p // Security check if ($type == '0') $result = restrictedArea($user, 'produit'); elseif ($type == '1') $result = restrictedArea($user, 'service'); -else $result = restrictedArea($user, 'produit|service'); +else $result = restrictedArea($user, 'produit|service|expedition'); // Load translation files required by the page $langs->loadLangs(array('products', 'stocks')); @@ -117,77 +117,80 @@ if (!empty($conf->global->MAIN_SEARCH_FORM_ON_HOME_AREAS)) // This is useles /* * Number of products and/or services */ -$prodser = array(); -$prodser[0][0] = $prodser[0][1] = $prodser[0][2] = $prodser[0][3] = 0; -$prodser[1][0] = $prodser[1][1] = $prodser[1][2] = $prodser[1][3] = 0; - -$sql = "SELECT COUNT(p.rowid) as total, p.fk_product_type, p.tosell, p.tobuy"; -$sql .= " FROM ".MAIN_DB_PREFIX."product as p"; -$sql .= ' WHERE p.entity IN ('.getEntity($product_static->element, 1).')'; -// Add where from hooks -$parameters = array(); -$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook -$sql .= $hookmanager->resPrint; -$sql .= " GROUP BY p.fk_product_type, p.tosell, p.tobuy"; -$result = $db->query($sql); -while ($objp = $db->fetch_object($result)) +if ((!empty($conf->product->enabled) || !empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { - $status = 3; // On sale + On purchase - if (!$objp->tosell && !$objp->tobuy) $status = 0; // Not on sale, not on purchase - if ($objp->tosell && !$objp->tobuy) $status = 1; // On sale only - if (!$objp->tosell && $objp->tobuy) $status = 2; // On purchase only - $prodser[$objp->fk_product_type][$status] = $objp->total; - if ($objp->tosell) $prodser[$objp->fk_product_type]['sell'] += $objp->total; - if ($objp->tobuy) $prodser[$objp->fk_product_type]['buy'] += $objp->total; - if (!$objp->tosell && !$objp->tobuy) $prodser[$objp->fk_product_type]['none'] += $objp->total; -} + $prodser = array(); + $prodser[0][0] = $prodser[0][1] = $prodser[0][2] = $prodser[0][3] = 0; + $prodser[1][0] = $prodser[1][1] = $prodser[1][2] = $prodser[1][3] = 0; -if ($conf->use_javascript_ajax) -{ - print '
'; - print ''; - print ''; - print ''; + print '
'.$langs->trans("Statistics").'
'; - - $SommeA = $prodser[0]['sell']; - $SommeB = $prodser[0]['buy']; - $SommeC = $prodser[0]['none']; - $SommeD = $prodser[1]['sell']; - $SommeE = $prodser[1]['buy']; - $SommeF = $prodser[1]['none']; - $total = 0; - $dataval = array(); - $datalabels = array(); - $i = 0; - - $total = $SommeA + $SommeB + $SommeC + $SommeD + $SommeE + $SommeF; - $dataseries = array(); - if (!empty($conf->product->enabled)) + $sql = "SELECT COUNT(p.rowid) as total, p.fk_product_type, p.tosell, p.tobuy"; + $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; + $sql .= ' WHERE p.entity IN ('.getEntity($product_static->element, 1).')'; + // Add where from hooks + $parameters = array(); + $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook + $sql .= $hookmanager->resPrint; + $sql .= " GROUP BY p.fk_product_type, p.tosell, p.tobuy"; + $result = $db->query($sql); + while ($objp = $db->fetch_object($result)) { - $dataseries[] = array($langs->trans("ProductsOnSale"), round($SommeA)); - $dataseries[] = array($langs->trans("ProductsOnPurchase"), round($SommeB)); - $dataseries[] = array($langs->trans("ProductsNotOnSell"), round($SommeC)); - } - if (!empty($conf->service->enabled)) - { - $dataseries[] = array($langs->trans("ServicesOnSale"), round($SommeD)); - $dataseries[] = array($langs->trans("ServicesOnPurchase"), round($SommeE)); - $dataseries[] = array($langs->trans("ServicesNotOnSell"), round($SommeF)); + $status = 3; // On sale + On purchase + if (!$objp->tosell && !$objp->tobuy) $status = 0; // Not on sale, not on purchase + if ($objp->tosell && !$objp->tobuy) $status = 1; // On sale only + if (!$objp->tosell && $objp->tobuy) $status = 2; // On purchase only + $prodser[$objp->fk_product_type][$status] = $objp->total; + if ($objp->tosell) $prodser[$objp->fk_product_type]['sell'] += $objp->total; + if ($objp->tobuy) $prodser[$objp->fk_product_type]['buy'] += $objp->total; + if (!$objp->tosell && !$objp->tobuy) $prodser[$objp->fk_product_type]['none'] += $objp->total; } - include_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php'; - $dolgraph = new DolGraph(); - $dolgraph->SetData($dataseries); - $dolgraph->setShowLegend(1); - $dolgraph->setShowPercent(0); - $dolgraph->SetType(array('pie')); - $dolgraph->setWidth('100%'); - $dolgraph->draw('idgraphstatus'); - print $dolgraph->show($total ? 0 : 1); + if ($conf->use_javascript_ajax) + { + print '
'; + print ''; + print ''; + print ''; - print '
'.$langs->trans("Statistics").'
'; - print '
'; - print '
'; + $SommeA = $prodser[0]['sell']; + $SommeB = $prodser[0]['buy']; + $SommeC = $prodser[0]['none']; + $SommeD = $prodser[1]['sell']; + $SommeE = $prodser[1]['buy']; + $SommeF = $prodser[1]['none']; + $total = 0; + $dataval = array(); + $datalabels = array(); + $i = 0; + + $total = $SommeA + $SommeB + $SommeC + $SommeD + $SommeE + $SommeF; + $dataseries = array(); + if (!empty($conf->product->enabled)) + { + $dataseries[] = array($langs->trans("ProductsOnSale"), round($SommeA)); + $dataseries[] = array($langs->trans("ProductsOnPurchase"), round($SommeB)); + $dataseries[] = array($langs->trans("ProductsNotOnSell"), round($SommeC)); + } + if (!empty($conf->service->enabled)) + { + $dataseries[] = array($langs->trans("ServicesOnSale"), round($SommeD)); + $dataseries[] = array($langs->trans("ServicesOnPurchase"), round($SommeE)); + $dataseries[] = array($langs->trans("ServicesNotOnSell"), round($SommeF)); + } + + include_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php'; + $dolgraph = new DolGraph(); + $dolgraph->SetData($dataseries); + $dolgraph->setShowLegend(1); + $dolgraph->setShowPercent(0); + $dolgraph->SetType(array('pie')); + $dolgraph->setWidth('100%'); + $dolgraph->draw('idgraphstatus'); + print $dolgraph->show($total ? 0 : 1); + + print '
'; + print '
'; + } } @@ -270,120 +273,123 @@ print '
'; /* * Latest modified products */ -$max = 15; -$sql = "SELECT p.rowid, p.label, p.price, p.ref, p.fk_product_type, p.tosell, p.tobuy, p.tobatch, p.fk_price_expression,"; -$sql .= " p.entity,"; -$sql .= " p.tms as datem"; -$sql .= " FROM ".MAIN_DB_PREFIX."product as p"; -$sql .= " WHERE p.entity IN (".getEntity($product_static->element, 1).")"; -if ($type != '') $sql .= " AND p.fk_product_type = ".$type; -// Add where from hooks -$parameters = array(); -$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook -$sql .= $hookmanager->resPrint; -$sql .= $db->order("p.tms", "DESC"); -$sql .= $db->plimit($max, 0); - -//print $sql; -$result = $db->query($sql); -if ($result) +if ((!empty($conf->product->enabled) || !empty($conf->service->enabled)) && ($user->rights->produit->lire || $user->rights->service->lire)) { - $num = $db->num_rows($result); + $max = 15; + $sql = "SELECT p.rowid, p.label, p.price, p.ref, p.fk_product_type, p.tosell, p.tobuy, p.tobatch, p.fk_price_expression,"; + $sql .= " p.entity,"; + $sql .= " p.tms as datem"; + $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; + $sql .= " WHERE p.entity IN (".getEntity($product_static->element, 1).")"; + if ($type != '') $sql .= " AND p.fk_product_type = ".$type; + // Add where from hooks + $parameters = array(); + $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook + $sql .= $hookmanager->resPrint; + $sql .= $db->order("p.tms", "DESC"); + $sql .= $db->plimit($max, 0); - $i = 0; - - if ($num > 0) + //print $sql; + $result = $db->query($sql); + if ($result) { - $transRecordedType = $langs->trans("LastModifiedProductsAndServices", $max); - if (isset($_GET["type"]) && $_GET["type"] == 0) $transRecordedType = $langs->trans("LastRecordedProducts", $max); - if (isset($_GET["type"]) && $_GET["type"] == 1) $transRecordedType = $langs->trans("LastRecordedServices", $max); + $num = $db->num_rows($result); - print '
'; - print ''; + $i = 0; - $colnb = 2; - if (empty($conf->global->PRODUIT_MULTIPRICES)) $colnb++; - - print ''; - print ''; - - while ($i < $num) + if ($num > 0) { - $objp = $db->fetch_object($result); + $transRecordedType = $langs->trans("LastModifiedProductsAndServices", $max); + if (isset($_GET["type"]) && $_GET["type"] == 0) $transRecordedType = $langs->trans("LastRecordedProducts", $max); + if (isset($_GET["type"]) && $_GET["type"] == 1) $transRecordedType = $langs->trans("LastRecordedServices", $max); - $product_static->id = $objp->rowid; - $product_static->ref = $objp->ref; - $product_static->label = $objp->label; - $product_static->type = $objp->fk_product_type; - $product_static->entity = $objp->entity; - $product_static->status = $objp->tosell; - $product_static->status_buy = $objp->tobuy; - $product_static->status_batch = $objp->tobatch; + print '
'; + print '
'.$transRecordedType.''.$langs->trans("FullList").''; - print '
'; - //Multilangs - if (!empty($conf->global->MAIN_MULTILANGS)) + $colnb = 2; + if (empty($conf->global->PRODUIT_MULTIPRICES)) $colnb++; + + print ''; + print ''; + + while ($i < $num) { - $sql = "SELECT label"; - $sql .= " FROM ".MAIN_DB_PREFIX."product_lang"; - $sql .= " WHERE fk_product=".$objp->rowid; - $sql .= " AND lang='".$langs->getDefaultLang()."'"; + $objp = $db->fetch_object($result); - $resultd = $db->query($sql); - if ($resultd) + $product_static->id = $objp->rowid; + $product_static->ref = $objp->ref; + $product_static->label = $objp->label; + $product_static->type = $objp->fk_product_type; + $product_static->entity = $objp->entity; + $product_static->status = $objp->tosell; + $product_static->status_buy = $objp->tobuy; + $product_static->status_batch = $objp->tobatch; + + //Multilangs + if (!empty($conf->global->MAIN_MULTILANGS)) { - $objtp = $db->fetch_object($resultd); - if ($objtp && $objtp->label != '') $objp->label = $objtp->label; + $sql = "SELECT label"; + $sql .= " FROM ".MAIN_DB_PREFIX."product_lang"; + $sql .= " WHERE fk_product=".$objp->rowid; + $sql .= " AND lang='".$langs->getDefaultLang()."'"; + + $resultd = $db->query($sql); + if ($resultd) + { + $objtp = $db->fetch_object($resultd); + if ($objtp && $objtp->label != '') $objp->label = $objtp->label; + } } - } - print ''; - print '\n"; - print ''; - print ""; - // Sell price - if (empty($conf->global->PRODUIT_MULTIPRICES)) - { - if (!empty($conf->dynamicprices->enabled) && !empty($objp->fk_price_expression)) - { - $product = new Product($db); - $product->fetch($objp->rowid); - $priceparser = new PriceParser($db); - $price_result = $priceparser->parseProduct($product); - if ($price_result >= 0) { - $objp->price = $price_result; - } - } - print ''; + print ''; + print '\n"; + print ''; + print ""; + // Sell price + if (empty($conf->global->PRODUIT_MULTIPRICES)) + { + if (!empty($conf->dynamicprices->enabled) && !empty($objp->fk_price_expression)) + { + $product = new Product($db); + $product->fetch($objp->rowid); + $priceparser = new PriceParser($db); + $price_result = $priceparser->parseProduct($product); + if ($price_result >= 0) { + $objp->price = $price_result; + } + } + print ''; + } + print '"; + print '"; + print "\n"; + $i++; } - print '"; - print '"; - print "\n"; - $i++; + + $db->free($result); + + print "
'.$transRecordedType.''.$langs->trans("FullList").''; + print '
'; - print $product_static->getNomUrl(1, '', 16); - print "'.dol_trunc($objp->label, 32).'"; - print dol_print_date($db->jdate($objp->datem), 'day'); - print "'; - if (isset($objp->price_base_type) && $objp->price_base_type == 'TTC') print price($objp->price_ttc).' '.$langs->trans("TTC"); - else print price($objp->price).' '.$langs->trans("HT"); - print '
'; + print $product_static->getNomUrl(1, '', 16); + print "'.dol_trunc($objp->label, 32).'"; + print dol_print_date($db->jdate($objp->datem), 'day'); + print "'; + if (isset($objp->price_base_type) && $objp->price_base_type == 'TTC') print price($objp->price_ttc).' '.$langs->trans("TTC"); + else print price($objp->price).' '.$langs->trans("HT"); + print ''; + print $product_static->LibStatut($objp->tosell, 3, 0); + print "'; + print $product_static->LibStatut($objp->tobuy, 3, 1); + print "
'; - print $product_static->LibStatut($objp->tosell, 3, 0); - print "'; - print $product_static->LibStatut($objp->tobuy, 3, 1); - print "
"; + print '
'; + print '
'; } - - $db->free($result); - - print ""; - print '
'; - print '
'; } -} -else -{ - dol_print_error($db); + else + { + dol_print_error($db); + } } From aa54aaeb01274dcabc972d2e4456533ad4c73827 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 31 Jan 2020 19:46:03 +0100 Subject: [PATCH 11/36] FIX search filter on extrafields were not restored avec "Back to list" --- htdocs/core/lib/functions.lib.php | 49 ++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 5bc3ad0056c..a0db5c8333d 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -224,7 +224,54 @@ function dol_shutdown() */ function GETPOSTISSET($paramname) { - return (isset($_POST[$paramname]) || isset($_GET[$paramname])); + $isset = 0; + + $relativepathstring = $_SERVER["PHP_SELF"]; + // Clean $relativepathstring + if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'), '/').'/', '', $relativepathstring); + $relativepathstring = preg_replace('/^\//', '', $relativepathstring); + $relativepathstring = preg_replace('/^custom\//', '', $relativepathstring); + //var_dump($relativepathstring); + //var_dump($user->default_values); + + // Code for search criteria persistence. + // Retrieve values if restore_lastsearch_values + if (!empty($_GET['restore_lastsearch_values'])) // Use $_GET here and not GETPOST + { + if (!empty($_SESSION['lastsearch_values_'.$relativepathstring])) // If there is saved values + { + $tmp = json_decode($_SESSION['lastsearch_values_'.$relativepathstring], true); + if (is_array($tmp)) + { + foreach ($tmp as $key => $val) + { + if ($key == $paramname) // We are on the requested parameter + { + $isset = 1; + break; + } + } + } + } + // If there is saved contextpage, page or limit + if ($paramname == 'contextpage' && !empty($_SESSION['lastsearch_contextpage_'.$relativepathstring])) + { + $isset = 1; + } + elseif ($paramname == 'page' && !empty($_SESSION['lastsearch_page_'.$relativepathstring])) + { + $isset = 1; + } + elseif ($paramname == 'limit' && !empty($_SESSION['lastsearch_limit_'.$relativepathstring])) + { + $isset = 1; + } + } + else { + $isset = (isset($_POST[$paramname]) || isset($_GET[$paramname])); + } + + return $isset; } /** From 0229cd3c6587720f210faa5ecacc07c597170cd6 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sat, 1 Feb 2020 08:18:48 +0100 Subject: [PATCH 12/36] FIX: FEC export have specific name --- htdocs/accountancy/tpl/export_journal.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/tpl/export_journal.tpl.php b/htdocs/accountancy/tpl/export_journal.tpl.php index 97f0da548ca..d2961670923 100644 --- a/htdocs/accountancy/tpl/export_journal.tpl.php +++ b/htdocs/accountancy/tpl/export_journal.tpl.php @@ -35,7 +35,7 @@ $endaccountingperiod = dol_print_date(dol_now(), '%Y%m%d'); header('Content-Type: text/csv'); -if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == "11" && $type_export == "general_ledger") // Specific filename for FEC model export into the general ledger +if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == "1000" && $type_export == "general_ledger") // Specific filename for FEC model export into the general ledger { // FEC format is defined here: https://www.legifrance.gouv.fr/affichCodeArticle.do?idArticle=LEGIARTI000027804775&cidTexte=LEGITEXT000006069583&dateTexte=20130802&oldAction=rechCodeArticle if (empty($search_date_end)) From e8b9ca3276bfb3f2fc72fa01ba4ff5fa09c60c45 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Sat, 1 Feb 2020 08:23:19 +0100 Subject: [PATCH 13/36] FIX: FEC export have specific name --- htdocs/accountancy/tpl/export_journal.tpl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/accountancy/tpl/export_journal.tpl.php b/htdocs/accountancy/tpl/export_journal.tpl.php index 5c9f7ad48ed..0dec55630d3 100644 --- a/htdocs/accountancy/tpl/export_journal.tpl.php +++ b/htdocs/accountancy/tpl/export_journal.tpl.php @@ -35,7 +35,7 @@ $endaccountingperiod = dol_print_date(dol_now(), '%Y%m%d'); header('Content-Type: text/csv'); -if ($conf->global->ACCOUNTING_EXPORT_MODELCSV == "11" && $type_export == "general_ledger") // Specific filename for FEC model export into the general ledger +if ($this->getFormatCode($formatexportset) == "fec" && $type_export == "general_ledger") // Specific filename for FEC model export into the general ledger { // FEC format is defined here: https://www.legifrance.gouv.fr/affichCodeArticle.do?idArticle=LEGIARTI000027804775&cidTexte=LEGITEXT000006069583&dateTexte=20130802&oldAction=rechCodeArticle if (empty($search_date_end)) From ec649bc0a3554ad7fcb4e4cc413be3397f260432 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 1 Feb 2020 10:09:31 +0100 Subject: [PATCH 14/36] Fix CSS --- htdocs/support/default.css | 20 ++++++++++++++++++-- htdocs/support/inc.php | 13 +++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/htdocs/support/default.css b/htdocs/support/default.css index c0d99f56657..735224254d3 100644 --- a/htdocs/support/default.css +++ b/htdocs/support/default.css @@ -23,6 +23,22 @@ background: #f9f9f9; margin: 5px 5px; } +.center { + text-align: center; +} + +.centpercent { + width: 100%; +} + +.valignmiddle { + vertical-align: middle; +} + +inline-block { + display: inline-block; +} + div.titre { padding: 5px 5px 5px 5px; margin: 0 0 0 0; @@ -147,10 +163,10 @@ padding: 4px 4px 4px 4px; tr.title { -background: #DDDFDD; +background: #EEEEEE; } -table.login { border: 1px solid #C0C0C0; background: #FFF; } +table.login { border: 1px solid #E0E0E0; background: #FFF; } .tablesupport { padding: 6px; diff --git a/htdocs/support/inc.php b/htdocs/support/inc.php index dd369e233b9..941bf6bb0d3 100644 --- a/htdocs/support/inc.php +++ b/htdocs/support/inc.php @@ -223,15 +223,12 @@ function pHeader($soutitre, $next, $action = 'none') print ''.$langs->trans("DolibarrHelpCenter").''."\n"; print ''."\n"; - print ''."\n"; + print ''."\n"; - print ''; - print ''; - print '
'; - print 'logohelpcenter'; - print ''; - print ''.$soutitre.''."\n"; - print '
'; + print '
'; + print 'logohelpcenter

'; + print ''.$soutitre.''."\n"; + print '

'; } /** From e59d118b8cfb3d7b9f6a83634c5f0189370d3d80 Mon Sep 17 00:00:00 2001 From: ATM john Date: Sun, 2 Feb 2020 06:36:06 +0100 Subject: [PATCH 15/36] Fix project loan data --- htdocs/loan/class/loan.class.php | 2 +- htdocs/projet/element.php | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/htdocs/loan/class/loan.class.php b/htdocs/loan/class/loan.class.php index 586b6b59036..f655b3adcb2 100644 --- a/htdocs/loan/class/loan.class.php +++ b/htdocs/loan/class/loan.class.php @@ -556,7 +556,7 @@ class Loan extends CommonObject $table = 'payment_loan'; $field = 'fk_loan'; - $sql = 'SELECT sum(amount) as amount'; + $sql = 'SELECT sum(amount_capital) as amount'; $sql .= ' FROM '.MAIN_DB_PREFIX.$table; $sql .= ' WHERE '.$field.' = '.$this->id; diff --git a/htdocs/projet/element.php b/htdocs/projet/element.php index 9be63cad242..9b49f2814a9 100644 --- a/htdocs/projet/element.php +++ b/htdocs/projet/element.php @@ -829,11 +829,13 @@ foreach ($listofreferent as $key => $value) // Amount HT //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print ''.$langs->trans("AmountHT").''; //elseif (empty($value['disableamount']) && in_array($tablename, array('projet_task'))) print ''.$langs->trans("Amount").''; - if (empty($value['disableamount'])) print ''.$langs->trans("AmountHT").''; + if ($key == 'loan') print ''.$langs->trans("LoanCapital").''; + elseif (empty($value['disableamount'])) print ''.$langs->trans("AmountHT").''; else print ''; // Amount TTC //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print ''.$langs->trans("AmountTTC").''; - if (empty($value['disableamount'])) print ''.$langs->trans("AmountTTC").''; + if ($key == 'loan') print ''.$langs->trans("RemainderToPay").''; + elseif (empty($value['disableamount'])) print ''.$langs->trans("AmountTTC").''; else print ''; // Status if (in_array($tablename, array('projet_task'))) print ''.$langs->trans("ProgressDeclared").''; @@ -928,6 +930,10 @@ foreach ($listofreferent as $key => $value) print $element->getNomUrl(1, 'withproject', 'time'); print ' - '.dol_trunc($element->label, 48); } + elseif ($key == 'loan'){ + print $element->getNomUrl(1); + print ' - '.dol_trunc($element->label, 48); + } else print $element->getNomUrl(1); $element_doc = $element->element; @@ -977,6 +983,10 @@ foreach ($listofreferent as $key => $value) if (empty($date)) $date = $element->datev; } } + elseif ($key == 'loan'){ + $date = $element->datestart; + } + print ''; if ($tablename == 'actioncomm') { @@ -1050,6 +1060,7 @@ foreach ($listofreferent as $key => $value) $othermessage = $form->textwithpicto($langs->trans("NotAvailable"), $langs->trans("ModuleSalaryToDefineHourlyRateMustBeEnabled")); } } + elseif ($key == 'loan') $total_ht_by_line = $element->capital; else { $total_ht_by_line = $element->total_ht; @@ -1097,6 +1108,7 @@ foreach ($listofreferent as $key => $value) $othermessage = $form->textwithpicto($langs->trans("NotAvailable"), $langs->trans("ModuleSalaryToDefineHourlyRateMustBeEnabled")); } } + elseif ($key == 'loan') $total_ttc_by_line = $element->capital - $element->getSumPayment(); else { $total_ttc_by_line = $element->total_ttc; @@ -1204,7 +1216,8 @@ foreach ($listofreferent as $key => $value) print ''; if (empty($value['disableamount'])) { - if ($tablename != 'projet_task' || !empty($conf->salaries->enabled)) print ''.$langs->trans("TotalHT").' : '.price($total_ht); + if ($key == 'loan') print $langs->trans("Total").' '.$langs->trans("LoanCapital").' : '.price($total_ttc); + elseif ($tablename != 'projet_task' || !empty($conf->salaries->enabled)) print ''.$langs->trans("TotalHT").' : '.price($total_ht); } print ''; //if (empty($value['disableamount']) && ! in_array($tablename, array('projet_task'))) print ''.$langs->trans("TotalTTC").' : '.price($total_ttc).''; @@ -1212,7 +1225,8 @@ foreach ($listofreferent as $key => $value) print ''; if (empty($value['disableamount'])) { - if ($tablename != 'projet_task' || !empty($conf->salaries->enabled)) print $langs->trans("TotalTTC").' : '.price($total_ttc); + if ($key == 'loan') print $langs->trans("Total").' '.$langs->trans("RemainderToPay").' : '.price($total_ttc); + elseif ($tablename != 'projet_task' || !empty($conf->salaries->enabled)) print $langs->trans("TotalTTC").' : '.price($total_ttc); } print ''; print ' '; From fe009c384251396429c75adebf35beda0339df95 Mon Sep 17 00:00:00 2001 From: ATM john Date: Sun, 2 Feb 2020 09:06:02 +0100 Subject: [PATCH 16/36] Fix project profit for loan part --- htdocs/projet/class/project.class.php | 15 ++++++++++++-- htdocs/projet/element.php | 30 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 54d13a51549..746fdacd381 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -607,18 +607,29 @@ class Project extends CommonObject { $sql = 'SELECT ms.rowid, ms.fk_user_author as fk_user FROM '.MAIN_DB_PREFIX."stock_mouvement as ms, ".MAIN_DB_PREFIX."entrepot as e WHERE e.rowid = ms.fk_entrepot AND e.entity IN (".getEntity('stock').") AND ms.origintype = 'project' AND ms.fk_origin IN (".$ids.") AND ms.type_mouvement = 1"; } + elseif ($type == 'loan') + { + $sql = 'SELECT l.rowid, l.fk_user_author as fk_user FROM '.MAIN_DB_PREFIX."loan as l WHERE l.entity IN (".getEntity('loan').")"; + } else { $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX.$tablename." WHERE ".$projectkey." IN (".$ids.") AND entity IN (".getEntity($type).")"; } - if ($dates > 0 && ($type != 'project_task')) // For table project_taks, we want the filter on date apply on project_time_spent table + if($dates > 0 && $type == 'loan'){ + $sql .= " AND (dateend > '".$this->db->idate($dates)."' OR dateend IS NULL)"; + } + elseif ($dates > 0 && ($type != 'project_task')) // For table project_taks, we want the filter on date apply on project_time_spent table { if (empty($datefieldname) && !empty($this->table_element_date)) $datefieldname = $this->table_element_date; if (empty($datefieldname)) return 'Error this object has no date field defined'; $sql .= " AND (".$datefieldname." >= '".$this->db->idate($dates)."' OR ".$datefieldname." IS NULL)"; } - if ($datee > 0 && ($type != 'project_task')) // For table project_taks, we want the filter on date apply on project_time_spent table + + if($datee > 0 && $type == 'loan'){ + $sql .= " AND (datestart < '".$this->db->idate($datee)."' OR datestart IS NULL)"; + } + elseif ($datee > 0 && ($type != 'project_task')) // For table project_taks, we want the filter on date apply on project_time_spent table { if (empty($datefieldname) && !empty($this->table_element_date)) $datefieldname = $this->table_element_date; if (empty($datefieldname)) return 'Error this object has no date field defined'; diff --git a/htdocs/projet/element.php b/htdocs/projet/element.php index 9b49f2814a9..2aa112bd722 100644 --- a/htdocs/projet/element.php +++ b/htdocs/projet/element.php @@ -49,6 +49,7 @@ if (! empty($conf->expensereport->enabled)) require_once DOL_DOCUMENT_ROOT.'/exp if (! empty($conf->agenda->enabled)) require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; if (! empty($conf->don->enabled)) require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php'; if (! empty($conf->loan->enabled)) require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php'; +if (! empty($conf->loan->enabled)) require_once DOL_DOCUMENT_ROOT.'/loan/class/loanschedule.class.php'; if (! empty($conf->stock->enabled)) require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php'; if (! empty($conf->tax->enabled)) require_once DOL_DOCUMENT_ROOT.'/compta/sociales/class/chargesociales.class.php'; if (! empty($conf->banque->enabled)) require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php'; @@ -650,6 +651,32 @@ foreach ($listofreferent as $key => $value) $total_ht_by_line = price2num($tmp['amount'], 'MT'); } } + elseif ($key == 'loan'){ + if((empty($dates) && empty($datee)) || (intval($dates) <= $element->datestart && intval($datee) >= $element->dateend)){ + // Get total loan + $total_ht_by_line = -$element->capital; + } + else{ + // Get loan schedule according to date filter + $total_ht_by_line = 0; + $loanScheduleStatic = new LoanSchedule($element->db); + $loanScheduleStatic->fetchAll($element->id); + if(!empty($loanScheduleStatic->lines)){ + foreach($loanScheduleStatic->lines as $loanSchedule){ + /** + * @var $loanSchedule LoanSchedule + */ + if( ($loanSchedule->datep >= $dates && $loanSchedule->datep <= $datee) // dates filter is defined + || !empty($dates) && empty($datee) && $loanSchedule->datep >= $dates && $loanSchedule->datep <= dol_now() + || empty($dates) && !empty($datee) && $loanSchedule->datep <= $datee + ){ + $total_ht_by_line = -$loanSchedule->amount_capital; + } + } + } + } + + } else $total_ht_by_line = $element->total_ht; // Define $total_ttc_by_line @@ -661,6 +688,9 @@ foreach ($listofreferent as $key => $value) $defaultvat = get_default_tva($mysoc, $mysoc); $total_ttc_by_line = price2num($total_ht_by_line * (1 + ($defaultvat / 100)), 'MT'); } + elseif ($key == 'loan'){ + $total_ttc_by_line = $total_ht_by_line; // For loan there is actually no taxe managed in Dolibarr + } else $total_ttc_by_line = $element->total_ttc; // Change sign of $total_ht_by_line and $total_ttc_by_line for some cases From 01b1667eedc9683a7fa36a9a6a4d585cd4d13823 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Sun, 2 Feb 2020 08:13:09 +0000 Subject: [PATCH 17/36] Fixing style errors. --- htdocs/projet/element.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/projet/element.php b/htdocs/projet/element.php index 2aa112bd722..dd89b3ca9c4 100644 --- a/htdocs/projet/element.php +++ b/htdocs/projet/element.php @@ -675,7 +675,6 @@ foreach ($listofreferent as $key => $value) } } } - } else $total_ht_by_line = $element->total_ht; From bd322dc12e43d955d74d28f6e8957cd4950d271d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 2 Feb 2020 12:59:11 +0100 Subject: [PATCH 18/36] Fix search on country --- htdocs/admin/dict.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index af07dc9bfc6..d634f547ff9 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -58,6 +58,7 @@ if ($id == 10 && !empty($user->rights->accounting->chartofaccount)) $allowed = 1 if ($id == 17 && !empty($user->rights->accounting->chartofaccount)) $allowed = 1; // Dictionary with type of expense report and accounting account allowed to manager of chart account if (!$allowed) accessforbidden(); +$acts =array(); $actl =array(); $acts[0] = "activate"; $acts[1] = "disable"; $actl[0] = img_picto($langs->trans("Disabled"), 'switch_off'); @@ -76,7 +77,7 @@ $pageprev = $page - 1; $pagenext = $page + 1; $search_country_id = GETPOST('search_country_id', 'int'); -if ($search_country_id == '' && ($id == 2 || $id == 3 || $id == 10)) // Not a so good idea to force on current country for all dictionaries. Some tables have entries that are for all countries, we must be able to see them, so this is done for dedicated dictionaries only. +if (! GETPOSTISSET('search_country_id') && $search_country_id == '' && ($id == 2 || $id == 3 || $id == 10)) // Not a so good idea to force on current country for all dictionaries. Some tables have entries that are for all countries, we must be able to see them, so this is done for dedicated dictionaries only. { $search_country_id = $mysoc->country_id; } @@ -178,7 +179,7 @@ $tablib[38] = "DictionarySocialNetworks"; $tabsql = array(); $tabsql[1] = "SELECT f.rowid as rowid, f.code, f.libelle, c.code as country_code, c.label as country, f.active FROM ".MAIN_DB_PREFIX."c_forme_juridique as f, ".MAIN_DB_PREFIX."c_country as c WHERE f.fk_pays=c.rowid"; $tabsql[2] = "SELECT d.rowid as rowid, d.code_departement as code, d.nom as libelle, d.fk_region as region_id, r.nom as region, c.code as country_code, c.label as country, d.active FROM ".MAIN_DB_PREFIX."c_departements as d, ".MAIN_DB_PREFIX."c_regions as r, ".MAIN_DB_PREFIX."c_country as c WHERE d.fk_region=r.code_region and r.fk_pays=c.rowid and r.active=1 and c.active=1"; -$tabsql[3] = "SELECT r.rowid as rowid, r.code_region as code, r.nom as libelle, r.fk_pays as country_id, c.code as country_code, c.label as country, r.active FROM ".MAIN_DB_PREFIX."c_regions as r, ".MAIN_DB_PREFIX."c_country as c WHERE r.fk_pays=c.rowid and c.active=1"; +$tabsql[3] = "SELECT r.rowid as rowid, r.code_region as state_code, r.nom as libelle, r.fk_pays as country_id, c.code as country_code, c.label as country, r.active FROM ".MAIN_DB_PREFIX."c_regions as r, ".MAIN_DB_PREFIX."c_country as c WHERE r.fk_pays=c.rowid and c.active=1"; $tabsql[4] = "SELECT c.rowid as rowid, c.code, c.label, c.active, c.favorite FROM ".MAIN_DB_PREFIX."c_country AS c"; $tabsql[5] = "SELECT c.rowid as rowid, c.code as code, c.label, c.active FROM ".MAIN_DB_PREFIX."c_civility AS c"; $tabsql[6] = "SELECT a.id as rowid, a.code as code, a.libelle AS libelle, a.type, a.active, a.module, a.color, a.position FROM ".MAIN_DB_PREFIX."c_actioncomm AS a"; @@ -759,12 +760,13 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) $_POST[$listfieldvalue[$i]] = getEntity($tabname[$id]); } if ($i) $sql .= ","; + if ($listfieldvalue[$i] == 'sortorder') // For column name 'sortorder', we use the field name 'position' { - $sql .= "'".(int) $db->escape($_POST['position'])."'"; + $sql .= "'".(int) $db->escape(GETPOST('position'))."'"; } elseif ($_POST[$listfieldvalue[$i]] == '' && !($listfieldvalue[$i] == 'code' && $id == 10)) $sql .= "null"; // For vat, we want/accept code = '' - else $sql .= "'".$db->escape($_POST[$listfieldvalue[$i]])."'"; + else $sql .= "'".$db->escape(GETPOST($listfieldvalue[$i], 'nohtml'))."'"; $i++; } $sql .= ",1)"; @@ -1011,6 +1013,7 @@ if ($id) if ($search_code != '' && $id == 9) $sql .= natural_search("code_iso", $search_code); elseif ($search_code != '' && $id == 28) $sql .= natural_search("h.code", $search_code); elseif ($search_code != '' && $id == 32) $sql .= natural_search("a.code", $search_code); + elseif ($search_code != '' && $id == 3) $sql .= natural_search("r.code_region", $search_code); elseif ($search_code != '' && $id != 9) $sql .= natural_search("code", $search_code); if ($sortfield) @@ -1146,7 +1149,7 @@ if ($id) if ($fieldlist[$field] == 'revenuestamp_type') { $valuetoshow = $langs->trans('TypeOfRevenueStamp'); } if ($fieldlist[$field] == 'use_default') { $valuetoshow = $langs->trans('Default'); } - if ($id == 2) // Special cas for state page + if ($id == 2) // Special case for state page { if ($fieldlist[$field] == 'region_id') { $valuetoshow = ' '; $showfield = 1; } if ($fieldlist[$field] == 'region') { $valuetoshow = $langs->trans("Country").'/'.$langs->trans("Region"); $showfield = 1; } @@ -1228,6 +1231,7 @@ if ($id) // List of available record in database dol_syslog("htdocs/admin/dict", LOG_DEBUG); + $resql = $db->query($sql); if ($resql) { @@ -1620,7 +1624,9 @@ if ($id) $key = $langs->trans($obj->label); $valuetoshow = ($obj->label && $key != strtoupper($obj->label) ? $key : $obj->{$fieldlist[$field]}); } - + elseif ($fieldlist[$field] == 'code' && $id == 3) { + $valuetoshow = $obj->state_code; + } $class .= ($class ? ' ' : '').'tddict'; if ($fieldlist[$field] == 'note' && $id == 10) $class .= ' tdoverflowmax200'; if ($fieldlist[$field] == 'tracking') $class .= ' tdoverflowauto'; From 967d97ccd74935a65db7d04cbc6d5a8b1012dd28 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 2 Feb 2020 15:01:57 +0100 Subject: [PATCH 19/36] FIX CVE-2020-7994 --- htdocs/admin/company.php | 14 +++++++------- htdocs/admin/const.php | 2 +- htdocs/admin/defaultvalues.php | 24 ++++++++++++------------ htdocs/admin/translation.php | 19 +++++++++---------- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/htdocs/admin/company.php b/htdocs/admin/company.php index ce75d83505a..df72e1bde04 100644 --- a/htdocs/admin/company.php +++ b/htdocs/admin/company.php @@ -95,15 +95,15 @@ if (($action == 'update' && !GETPOST("cancel", 'alpha')) dolibarr_set_const($db, "MAIN_INFO_SOCIETE_NOM", GETPOST("nom", 'nohtml'), 'chaine', 0, '', $conf->entity); dolibarr_set_const($db, "MAIN_INFO_SOCIETE_ADDRESS", GETPOST("MAIN_INFO_SOCIETE_ADDRESS", 'nohtml'), 'chaine', 0, '', $conf->entity); dolibarr_set_const($db, "MAIN_INFO_SOCIETE_TOWN", GETPOST("MAIN_INFO_SOCIETE_TOWN", 'nohtml'), 'chaine', 0, '', $conf->entity); - dolibarr_set_const($db, "MAIN_INFO_SOCIETE_ZIP", GETPOST("MAIN_INFO_SOCIETE_ZIP", 'alpha'), 'chaine', 0, '', $conf->entity); - dolibarr_set_const($db, "MAIN_INFO_SOCIETE_REGION", GETPOST("region_code", 'alpha'), 'chaine', 0, '', $conf->entity); + dolibarr_set_const($db, "MAIN_INFO_SOCIETE_ZIP", GETPOST("MAIN_INFO_SOCIETE_ZIP", 'alphanohtml'), 'chaine', 0, '', $conf->entity); + dolibarr_set_const($db, "MAIN_INFO_SOCIETE_REGION", GETPOST("region_code", 'alphanohtml'), 'chaine', 0, '', $conf->entity); dolibarr_set_const($db, "MAIN_MONNAIE", GETPOST("currency", 'aZ09'), 'chaine', 0, '', $conf->entity); - dolibarr_set_const($db, "MAIN_INFO_SOCIETE_TEL", GETPOST("tel", 'alpha'), 'chaine', 0, '', $conf->entity); - dolibarr_set_const($db, "MAIN_INFO_SOCIETE_FAX", GETPOST("fax", 'alpha'), 'chaine', 0, '', $conf->entity); - dolibarr_set_const($db, "MAIN_INFO_SOCIETE_MAIL", GETPOST("mail", 'alpha'), 'chaine', 0, '', $conf->entity); - dolibarr_set_const($db, "MAIN_INFO_SOCIETE_WEB", GETPOST("web", 'alpha'), 'chaine', 0, '', $conf->entity); + dolibarr_set_const($db, "MAIN_INFO_SOCIETE_TEL", GETPOST("tel", 'alphanohtml'), 'chaine', 0, '', $conf->entity); + dolibarr_set_const($db, "MAIN_INFO_SOCIETE_FAX", GETPOST("fax", 'alphanohtml'), 'chaine', 0, '', $conf->entity); + dolibarr_set_const($db, "MAIN_INFO_SOCIETE_MAIL", GETPOST("mail", 'alphanohtml'), 'chaine', 0, '', $conf->entity); + dolibarr_set_const($db, "MAIN_INFO_SOCIETE_WEB", GETPOST("web", 'alphanohtml'), 'chaine', 0, '', $conf->entity); dolibarr_set_const($db, "MAIN_INFO_SOCIETE_NOTE", GETPOST("note", 'none'), 'chaine', 0, '', $conf->entity); - dolibarr_set_const($db, "MAIN_INFO_SOCIETE_GENCOD", GETPOST("barcode", 'alpha'), 'chaine', 0, '', $conf->entity); + dolibarr_set_const($db, "MAIN_INFO_SOCIETE_GENCOD", GETPOST("barcode", 'alphanohtml'), 'chaine', 0, '', $conf->entity); $dirforimage = $conf->mycompany->dir_output.'/logos/'; diff --git a/htdocs/admin/const.php b/htdocs/admin/const.php index eed7f40910c..baeac243ce0 100644 --- a/htdocs/admin/const.php +++ b/htdocs/admin/const.php @@ -40,7 +40,7 @@ $update=GETPOST('update', 'alpha'); $delete=GETPOST('delete', 'none'); // Do not use alpha here $debug=GETPOST('debug', 'int'); $consts=GETPOST('const', 'array'); -$constname=GETPOST('constname', 'alpha'); +$constname=GETPOST('constname', 'alphanohtml'); $constvalue=GETPOST('constvalue', 'none'); // We shoul dbe able to send everything here $constnote=GETPOST('constnote', 'alpha'); diff --git a/htdocs/admin/defaultvalues.php b/htdocs/admin/defaultvalues.php index 29043720dee..d6981448ea6 100644 --- a/htdocs/admin/defaultvalues.php +++ b/htdocs/admin/defaultvalues.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2017-2020 Laurent Destailleur * Copyright (C) 2017-2018 Regis Houssin * * This program is free software; you can redistribute it and/or modify @@ -52,15 +52,15 @@ $pagenext = $page + 1; if (!$sortfield) $sortfield = 'page,param'; if (!$sortorder) $sortorder = 'ASC'; -$defaulturl = GETPOST('defaulturl'); -$defaultkey = GETPOST('defaultkey', 'alpha'); -$defaultvalue = GETPOST('defaultvalue'); +$defaulturl = GETPOST('defaulturl', 'alphanohtml'); +$defaultkey = GETPOST('defaultkey', 'alphanohtml'); +$defaultvalue = GETPOST('defaultvalue', 'none'); $defaulturl = preg_replace('/^\//', '', $defaulturl); -$urlpage = GETPOST('urlpage'); -$key = GETPOST('key'); -$value = GETPOST('value'); +$urlpage = GETPOST('urlpage', 'alphanohtml'); +$key = GETPOST('key', 'alphanohtml'); +$value = GETPOST('value', 'none'); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('admindefaultvalues', 'globaladmin')); @@ -210,9 +210,9 @@ print load_fiche_titre($langs->trans("DefaultValues"), $enabledisablehtml, 'titl print ''.$langs->trans("DefaultValuesDesc")."
\n"; print "
\n"; -if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&contextpage='.$contextpage; -if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&limit='.$limit; -if ($optioncss != '') $param .= '&optioncss='.$optioncss; +if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&contextpage='.urlencode($contextpage); +if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&limit='.urlencode($limit); +if ($optioncss != '') $param .= '&optioncss='.urlencode($optioncss); if ($defaulturl) $param .= '&defaulturl='.urlencode($defaulturl); if ($defaultkey) $param .= '&defaultkey='.urlencode($defaultkey); if ($defaultvalue) $param .= '&defaultvalue='.urlencode($defaultvalue); @@ -359,7 +359,7 @@ if ($result) // Page print ''; - if ($action != 'edit' || GETPOST('rowid') != $obj->rowid) print $obj->page; + if ($action != 'edit' || GETPOST('rowid', 'int') != $obj->rowid) print $obj->page; else print ''; print ''."\n"; @@ -378,7 +378,7 @@ if ($result) print ''; print ''; */ - if ($action != 'edit' || GETPOST('rowid') != $obj->rowid) print $obj->value; + if ($action != 'edit' || GETPOST('rowid') != $obj->rowid) print dol_escape_htmltag($obj->value); else print ''; print ''; } diff --git a/htdocs/admin/translation.php b/htdocs/admin/translation.php index 5e98d7c5503..c641be11a59 100644 --- a/htdocs/admin/translation.php +++ b/htdocs/admin/translation.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2007-2020 Laurent Destailleur * Copyright (C) 2009-2017 Regis Houssin * Copyright (C) 2017 Frédéric France * @@ -35,9 +35,9 @@ if (!$user->admin) accessforbidden(); $id = GETPOST('rowid', 'int'); $action = GETPOST('action', 'alpha'); -$langcode = GETPOST('langcode', 'alpha'); -$transkey = GETPOST('transkey', 'alpha'); -$transvalue = GETPOST('transvalue', 'alpha'); +$langcode = GETPOST('langcode', 'alphanohtml'); +$transkey = GETPOST('transkey', 'alphanohtml'); +$transvalue = GETPOST('transvalue', 'none'); $mode = GETPOST('mode', 'aZ09') ?GETPOST('mode', 'aZ09') : 'overwrite'; @@ -190,7 +190,6 @@ if ($action == 'delete') - /* * View */ @@ -231,9 +230,9 @@ print ''.$form->textwithpicto($langs->trans("Current print '
'; -if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; -if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit; -if ($optioncss != '') $param.='&optioncss='.$optioncss; +if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.urlencode($contextpage); +if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.urlencode($limit); +if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss); if ($langcode) $param.='&langcode='.urlencode($langcode); if ($transkey) $param.='&transkey='.urlencode($transkey); if ($transvalue) $param.='&transvalue='.urlencode($transvalue); @@ -348,11 +347,11 @@ if ($mode == 'overwrite') */ if ($action == 'edit' && $obj->rowid == GETPOST('rowid', 'int')) { - print ''; + print ''; } else { - print $obj->transvalue; + print dol_escape_htmltag($obj->transvalue); } print ''; From 71b5e1daf9cf62c548d3c1f12d425164ba12cbb1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 2 Feb 2020 15:57:41 +0100 Subject: [PATCH 20/36] FIX Log of authentication ko or ko --- htdocs/admin/system/browser.php | 7 +++++-- htdocs/core/lib/security2.lib.php | 2 +- htdocs/core/login/functions_dolibarr.php | 8 ++++---- htdocs/core/login/functions_ldap.php | 8 ++++---- htdocs/main.inc.php | 2 +- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/htdocs/admin/system/browser.php b/htdocs/admin/system/browser.php index 5035c6c4a7d..cae6e568d65 100644 --- a/htdocs/admin/system/browser.php +++ b/htdocs/admin/system/browser.php @@ -49,12 +49,15 @@ $tmp=getBrowserInfo($_SERVER["HTTP_USER_AGENT"]); print '
'; print ''; print ''."\n"; -print ''."\n"; +print ''."\n"; print ''."\n"; print ''."\n"; print ''."\n"; print ''."\n"; -print ''."\n"; +print ''."\n"; print ''."\n"; print ''."\n"; diff --git a/htdocs/core/lib/security2.lib.php b/htdocs/core/lib/security2.lib.php index 26e97499482..8d3adfa2df7 100644 --- a/htdocs/core/lib/security2.lib.php +++ b/htdocs/core/lib/security2.lib.php @@ -104,7 +104,7 @@ function checkLoginPassEntity($usertotest, $passwordtotest, $entitytotest, $auth } else { - dol_syslog("Authentification ko - failed to load file '".$authfile."'", LOG_ERR); + dol_syslog("Authentication KO - failed to load file '".$authfile."'", LOG_ERR); sleep(1); // Load translation files required by the page $langs->loadLangs(array('other', 'main', 'errors')); diff --git a/htdocs/core/login/functions_dolibarr.php b/htdocs/core/login/functions_dolibarr.php index 7e5439fa66a..861c31a0e37 100644 --- a/htdocs/core/login/functions_dolibarr.php +++ b/htdocs/core/login/functions_dolibarr.php @@ -110,7 +110,7 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes else { sleep(2); // Anti brut force protection - dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ko bad password for '".$usertotest."', cryptType=".$cryptType); + dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentication KO bad password for '".$usertotest."', cryptType=".$cryptType, LOG_NOTICE); // Load translation files required by the page $langs->loadLangs(array('main', 'errors')); @@ -129,7 +129,7 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes $ret = $mc->checkRight($obj->rowid, $entitytotest); if ($ret < 0) { - dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ko entity '" . $entitytotest . "' not allowed for user '" . $obj->rowid . "'"); + dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentication KO entity '" . $entitytotest . "' not allowed for user '" . $obj->rowid . "'", LOG_NOTICE); $login = ''; // force authentication failure } } @@ -137,7 +137,7 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes } else { - dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ko user not found for '".$usertotest."'"); + dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentication KO user not found for '".$usertotest."'", LOG_NOTICE); sleep(1); // Load translation files required by the page @@ -148,7 +148,7 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes } else { - dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ko db error for '".$usertotest."' error=".$db->lasterror()); + dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentication KO db error for '".$usertotest."' error=".$db->lasterror(), LOG_ERR); sleep(1); $_SESSION["dol_loginmesg"]=$db->lasterror(); } diff --git a/htdocs/core/login/functions_ldap.php b/htdocs/core/login/functions_ldap.php index 63a4c6d01e6..81bbfdf5b84 100644 --- a/htdocs/core/login/functions_ldap.php +++ b/htdocs/core/login/functions_ldap.php @@ -52,7 +52,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) if (! function_exists("ldap_connect")) { - dol_syslog("functions_ldap::check_user_password_ldap Authentification ko failed to connect to LDAP. LDAP functions are disabled on this PHP"); + dol_syslog("functions_ldap::check_user_password_ldap Authentication KO failed to connect to LDAP. LDAP functions are disabled on this PHP", LOG_ERR); sleep(1); // Load translation files required by the page @@ -202,7 +202,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) $ret=$mc->checkRight($usertmp->id, $entitytotest); if ($ret < 0) { - dol_syslog("functions_ldap::check_user_password_ldap Authentification ko entity '".$entitytotest."' not allowed for user '".$usertmp->id."'"); + dol_syslog("functions_ldap::check_user_password_ldap Authentication KO entity '".$entitytotest."' not allowed for user '".$usertmp->id."'", LOG_NOTICE); $login=''; // force authentication failure } unset($usertmp); @@ -210,7 +210,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) } if ($result == 1) { - dol_syslog("functions_ldap::check_user_password_ldap Authentification ko bad user/password for '".$usertotest."'"); + dol_syslog("functions_ldap::check_user_password_ldap Authentication KO bad user/password for '".$usertotest."'", LOG_NOTICE); sleep(1); // Load translation files required by the page @@ -229,7 +229,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) ** 49 - Wrong password ** 53 - Account inactive (manually locked out by administrator) */ - dol_syslog("functions_ldap::check_user_password_ldap Authentification ko failed to connect to LDAP for '".$usertotest."'"); + dol_syslog("functions_ldap::check_user_password_ldap Authentication KO failed to connect to LDAP for '".$usertotest."'", LOG_NOTICE); if (is_resource($ldap->connection)) // If connection ok but bind ko { $ldap->ldapErrorCode = ldap_errno($ldap->connection); diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index d396ad4cadc..4e1745413ce 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -957,7 +957,7 @@ if (!defined('NOLOGIN')) { // If not active, we refuse the user $langs->load("other"); - dol_syslog("Authentification ko as login is disabled"); + dol_syslog("Authentication KO as login is disabled", LOG_NOTICE); accessforbidden($langs->trans("ErrorLoginDisabled")); exit; } From 075b1ea7443d9dd17b5bfd5c0e8da160c88307ad Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 2 Feb 2020 15:57:41 +0100 Subject: [PATCH 21/36] FIX Log of authentication ko or ko + CVE-2020-7996 --- htdocs/admin/system/browser.php | 7 +++++-- htdocs/core/lib/security2.lib.php | 2 +- htdocs/core/login/functions_dolibarr.php | 8 ++++---- htdocs/core/login/functions_ldap.php | 8 ++++---- htdocs/main.inc.php | 2 +- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/htdocs/admin/system/browser.php b/htdocs/admin/system/browser.php index 5035c6c4a7d..cae6e568d65 100644 --- a/htdocs/admin/system/browser.php +++ b/htdocs/admin/system/browser.php @@ -49,12 +49,15 @@ $tmp=getBrowserInfo($_SERVER["HTTP_USER_AGENT"]); print '
'; print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'.$langs->trans("UserAgent").''.$_SERVER['HTTP_USER_AGENT'].'
'.$langs->trans("UserAgent").''.dol_escape_htmltag($_SERVER['HTTP_USER_AGENT']).'
'.$langs->trans("BrowserName").''.$tmp['browsername'].'
'.$langs->trans("BrowserOS").''.$tmp['browseros'].'
'.$langs->trans("Version").''.$tmp['browserversion'].'
'.$langs->trans("Layout").' (phone/tablet/classic)'.$tmp['layout'].'
'.$langs->trans("IPAddress").''.$_SERVER['REMOTE_ADDR'].'
'.$langs->trans("IPAddress").''.dol_escape_htmltag($_SERVER['REMOTE_ADDR']); +if (! empty($_SERVER['HTTP_CLIENT_IP'])) print ' (HTTP_CLIENT_IP='.dol_escape_htmltag($_SERVER['HTTP_CLIENT_IP']).')'; +if (! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) print ' (HTTP_X_FORWARDED_FOR='.dol_escape_htmltag($_SERVER['HTTP_X_FORWARDED_FOR']).')'; +print '
'.$langs->trans("SessionName").''.session_name().'
'.$langs->trans("SessionId").''.session_id().'
'; print ''."\n"; -print ''."\n"; +print ''."\n"; print ''."\n"; print ''."\n"; print ''."\n"; print ''."\n"; -print ''."\n"; +print ''."\n"; print ''."\n"; print ''."\n"; diff --git a/htdocs/core/lib/security2.lib.php b/htdocs/core/lib/security2.lib.php index 26e97499482..8d3adfa2df7 100644 --- a/htdocs/core/lib/security2.lib.php +++ b/htdocs/core/lib/security2.lib.php @@ -104,7 +104,7 @@ function checkLoginPassEntity($usertotest, $passwordtotest, $entitytotest, $auth } else { - dol_syslog("Authentification ko - failed to load file '".$authfile."'", LOG_ERR); + dol_syslog("Authentication KO - failed to load file '".$authfile."'", LOG_ERR); sleep(1); // Load translation files required by the page $langs->loadLangs(array('other', 'main', 'errors')); diff --git a/htdocs/core/login/functions_dolibarr.php b/htdocs/core/login/functions_dolibarr.php index 7e5439fa66a..861c31a0e37 100644 --- a/htdocs/core/login/functions_dolibarr.php +++ b/htdocs/core/login/functions_dolibarr.php @@ -110,7 +110,7 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes else { sleep(2); // Anti brut force protection - dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ko bad password for '".$usertotest."', cryptType=".$cryptType); + dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentication KO bad password for '".$usertotest."', cryptType=".$cryptType, LOG_NOTICE); // Load translation files required by the page $langs->loadLangs(array('main', 'errors')); @@ -129,7 +129,7 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes $ret = $mc->checkRight($obj->rowid, $entitytotest); if ($ret < 0) { - dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ko entity '" . $entitytotest . "' not allowed for user '" . $obj->rowid . "'"); + dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentication KO entity '" . $entitytotest . "' not allowed for user '" . $obj->rowid . "'", LOG_NOTICE); $login = ''; // force authentication failure } } @@ -137,7 +137,7 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes } else { - dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ko user not found for '".$usertotest."'"); + dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentication KO user not found for '".$usertotest."'", LOG_NOTICE); sleep(1); // Load translation files required by the page @@ -148,7 +148,7 @@ function check_user_password_dolibarr($usertotest, $passwordtotest, $entitytotes } else { - dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentification ko db error for '".$usertotest."' error=".$db->lasterror()); + dol_syslog("functions_dolibarr::check_user_password_dolibarr Authentication KO db error for '".$usertotest."' error=".$db->lasterror(), LOG_ERR); sleep(1); $_SESSION["dol_loginmesg"]=$db->lasterror(); } diff --git a/htdocs/core/login/functions_ldap.php b/htdocs/core/login/functions_ldap.php index 63a4c6d01e6..81bbfdf5b84 100644 --- a/htdocs/core/login/functions_ldap.php +++ b/htdocs/core/login/functions_ldap.php @@ -52,7 +52,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) if (! function_exists("ldap_connect")) { - dol_syslog("functions_ldap::check_user_password_ldap Authentification ko failed to connect to LDAP. LDAP functions are disabled on this PHP"); + dol_syslog("functions_ldap::check_user_password_ldap Authentication KO failed to connect to LDAP. LDAP functions are disabled on this PHP", LOG_ERR); sleep(1); // Load translation files required by the page @@ -202,7 +202,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) $ret=$mc->checkRight($usertmp->id, $entitytotest); if ($ret < 0) { - dol_syslog("functions_ldap::check_user_password_ldap Authentification ko entity '".$entitytotest."' not allowed for user '".$usertmp->id."'"); + dol_syslog("functions_ldap::check_user_password_ldap Authentication KO entity '".$entitytotest."' not allowed for user '".$usertmp->id."'", LOG_NOTICE); $login=''; // force authentication failure } unset($usertmp); @@ -210,7 +210,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) } if ($result == 1) { - dol_syslog("functions_ldap::check_user_password_ldap Authentification ko bad user/password for '".$usertotest."'"); + dol_syslog("functions_ldap::check_user_password_ldap Authentication KO bad user/password for '".$usertotest."'", LOG_NOTICE); sleep(1); // Load translation files required by the page @@ -229,7 +229,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) ** 49 - Wrong password ** 53 - Account inactive (manually locked out by administrator) */ - dol_syslog("functions_ldap::check_user_password_ldap Authentification ko failed to connect to LDAP for '".$usertotest."'"); + dol_syslog("functions_ldap::check_user_password_ldap Authentication KO failed to connect to LDAP for '".$usertotest."'", LOG_NOTICE); if (is_resource($ldap->connection)) // If connection ok but bind ko { $ldap->ldapErrorCode = ldap_errno($ldap->connection); diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index d396ad4cadc..4e1745413ce 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -957,7 +957,7 @@ if (!defined('NOLOGIN')) { // If not active, we refuse the user $langs->load("other"); - dol_syslog("Authentification ko as login is disabled"); + dol_syslog("Authentication KO as login is disabled", LOG_NOTICE); accessforbidden($langs->trans("ErrorLoginDisabled")); exit; } From 7cb2c21dc2fe32b856c8e0e4eba91e3fce3270e6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 2 Feb 2020 19:50:53 +0100 Subject: [PATCH 22/36] FIX #12974 --- htdocs/core/menus/standard/eldy.lib.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/htdocs/core/menus/standard/eldy.lib.php b/htdocs/core/menus/standard/eldy.lib.php index 5a5a2c5628d..0428f5e1dba 100644 --- a/htdocs/core/menus/standard/eldy.lib.php +++ b/htdocs/core/menus/standard/eldy.lib.php @@ -239,11 +239,20 @@ function print_eldy_menu($db, $atarget, $type_user, &$tabMenu, &$menu, $noout = !empty($user->rights->contrat->lire) || !empty($user->rights->ficheinter->lire) ), - 'module'=>'propal|commande|supplier_order|contrat|ficheinter' + 'module'=>'propal|commande|supplier_order|supplier_proposal|contrat|ficheinter' ); + + $onlysupplierorder = ! empty($user->rights->fournisseur->commande->lire) && + empty($user->rights->propal->lire) && + empty($user->rights->commande->lire) && + empty($user->rights->supplier_order->lire) && + empty($user->rights->supplier_proposal->lire) && + empty($user->rights->contrat->lire) && + empty($user->rights->ficheinter->lire); + $menu_arr[] = array( 'name' => 'Commercial', - 'link' => '/comm/index.php?mainmenu=commercial&leftmenu=', + 'link' => ($onlysupplierorder ? '/fourn/commande/index.php?mainmenu=commercial&leftmenu=' : '/comm/index.php?mainmenu=commercial&leftmenu='), 'title' => "Commercial", 'level' => 0, 'enabled' => $showmode = isVisibleToUserType($type_user, $tmpentry, $listofmodulesforexternal), From a0e3c5292f11a6839848d9bd960ce4b88844e087 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 02:20:38 +0100 Subject: [PATCH 23/36] FIX #12992 --- htdocs/install/upgrade2.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index dd9e3b1ed95..c5d1d7837e9 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -4978,16 +4978,16 @@ function migrate_users_socialnetworks() $db->begin(); print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'.$langs->trans("UserAgent").''.$_SERVER['HTTP_USER_AGENT'].'
'.$langs->trans("UserAgent").''.dol_escape_htmltag($_SERVER['HTTP_USER_AGENT']).'
'.$langs->trans("BrowserName").''.$tmp['browsername'].'
'.$langs->trans("BrowserOS").''.$tmp['browseros'].'
'.$langs->trans("Version").''.$tmp['browserversion'].'
'.$langs->trans("Layout").' (phone/tablet/classic)'.$tmp['layout'].'
'.$langs->trans("IPAddress").''.$_SERVER['REMOTE_ADDR'].'
'.$langs->trans("IPAddress").''.dol_escape_htmltag($_SERVER['REMOTE_ADDR']); +if (! empty($_SERVER['HTTP_CLIENT_IP'])) print ' (HTTP_CLIENT_IP='.dol_escape_htmltag($_SERVER['HTTP_CLIENT_IP']).')'; +if (! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) print ' (HTTP_X_FORWARDED_FOR='.dol_escape_htmltag($_SERVER['HTTP_X_FORWARDED_FOR']).')'; +print '
'.$langs->trans("SessionName").''.session_name().'
'.$langs->trans("SessionId").''.session_id().'
'; $sql = 'SELECT rowid, socialnetworks'; - $sql .= ', skype, twitter, facebook, linkedin, instagram, snapchat, googleplus, youtube, whatsapp FROM '.MAIN_DB_PREFIX.'user WHERE '; - $sql .= ' skype IS NOT NULL OR skype !=""'; - $sql .= ' OR twitter IS NOT NULL OR twitter !=""'; - $sql .= ' OR facebook IS NOT NULL OR facebook!=""'; - $sql .= ' OR linkedin IS NOT NULL OR linkedin!=""'; - $sql .= ' OR instagram IS NOT NULL OR instagram!=""'; - $sql .= ' OR snapchat IS NOT NULL OR snapchat!=""'; - $sql .= ' OR googleplus IS NOT NULL OR googleplus!=""'; - $sql .= ' OR youtube IS NOT NULL OR youtube!=""'; - $sql .= ' OR whatsapp IS NOT NULL OR whatsapp!=""'; + $sql .= ', skype, twitter, facebook, linkedin, instagram, snapchat, googleplus, youtube, whatsapp FROM '.MAIN_DB_PREFIX.'user WHERE'; + $sql .= " skype IS NOT NULL OR skype <> ''"; + $sql .= " OR twitter IS NOT NULL OR twitter <> ''"; + $sql .= " OR facebook IS NOT NULL OR facebook <> ''"; + $sql .= " OR linkedin IS NOT NULL OR linkedin <> ''"; + $sql .= " OR instagram IS NOT NULL OR instagram <> ''"; + $sql .= " OR snapchat IS NOT NULL OR snapchat <> ''"; + $sql .= " OR googleplus IS NOT NULL OR googleplus <> ''"; + $sql .= " OR youtube IS NOT NULL OR youtube <> ''"; + $sql .= " OR whatsapp IS NOT NULL OR whatsapp <> ''"; //print $sql; $resql = $db->query($sql); if ($resql) { From 69a0a1410eca32287634e461759b7c92491c2c7a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 02:28:23 +0100 Subject: [PATCH 24/36] FIX #12991 --- htdocs/install/mysql/migration/10.0.0-11.0.0.sql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index 350e3d2065a..9f3d092e846 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -206,7 +206,9 @@ ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_c_type_co ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe(rowid); ALTER TABLE llx_societe_contacts ADD CONSTRAINT fk_societe_contacts_fk_socpeople FOREIGN KEY (fk_socpeople) REFERENCES llx_socpeople(rowid); -ALTER TABLE llx_accounting_account MODIFY COLUMN rowid bigint AUTO_INCREMENT; +-- VMYSQL4.3 ALTER TABLE llx_accounting_account MODIFY COLUMN rowid bigint AUTO_INCREMENT; +-- VPGSQL8.2 ALTER TABLE llx_accounting_account MODIFY COLUMN rowid bigint; + ALTER TABLE llx_supplier_proposaldet ADD COLUMN date_start datetime DEFAULT NULL; From 90cde17bdbe6f6c65e9fb2ecb6502608aadce813 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 02:48:05 +0100 Subject: [PATCH 25/36] FIX #12986 --- htdocs/projet/class/project.class.php | 19 +++++++++++++------ htdocs/user/perms.php | 16 ++++++++++++---- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 54d13a51549..bb1ca3e1d2e 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -1211,7 +1211,7 @@ class Project extends CommonObject * Return array of projects a user has permission on, is affected to, or all projects * * @param User $user User object - * @param int $mode 0=All project I have permission on (assigned to me and public), 1=Projects assigned to me only, 2=Will return list of all projects with no test on contacts + * @param int $mode 0=All project I have permission on (assigned to me or public), 1=Projects assigned to me only, 2=Will return list of all projects with no test on contacts * @param int $list 0=Return array, 1=Return string list * @param int $socid 0=No filter on third party, id of third party * @param string $filter additionnal filter on project (statut, ref, ...) @@ -1224,9 +1224,17 @@ class Project extends CommonObject $sql = "SELECT ".(($mode == 0 || $mode == 1) ? "DISTINCT " : "")."p.rowid, p.ref"; $sql.= " FROM " . MAIN_DB_PREFIX . "projet as p"; - if ($mode == 0 || $mode == 1) + if ($mode == 0) { - $sql.= ", " . MAIN_DB_PREFIX . "element_contact as ec"; + $sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "element_contact as ec ON ec.element_id = p.rowid"; + } + elseif ($mode == 1) + { + $sql.= ", " . MAIN_DB_PREFIX . "element_contact as ec"; + } + elseif ($mode == 2) + { + // No filter. Use this if user has permission to see all project } $sql.= " WHERE p.entity IN (".getEntity('project').")"; // Internal users must see project he is contact to even if project linked to a third party he can't see. @@ -1251,13 +1259,12 @@ class Project extends CommonObject if ($mode == 0) { - $sql.= " AND ec.element_id = p.rowid"; $sql.= " AND ( p.public = 1"; $sql.= " OR ( ec.fk_c_type_contact IN (".join(',', array_keys($listofprojectcontacttype)).")"; $sql.= " AND ec.fk_socpeople = ".$user->id.")"; $sql.= " )"; } - if ($mode == 1) + elseif ($mode == 1) { $sql.= " AND ec.element_id = p.rowid"; $sql.= " AND ("; @@ -1265,7 +1272,7 @@ class Project extends CommonObject $sql.= " AND ec.fk_socpeople = ".$user->id.")"; $sql.= " )"; } - if ($mode == 2) + elseif ($mode == 2) { // No filter. Use this if user has permission to see all project } diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index 26758f52ab0..62070e3b31e 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -89,9 +89,13 @@ if (empty($reshook)) { if ($action == 'addrights' && $caneditperms) { $edituser = new User($db); $edituser->fetch($object->id); - $edituser->addrights($rights, $module, '', $entity); + $result = $edituser->addrights($rights, $module, '', $entity); + if ($result < 0) + { + setEventMessages($edituser->error, $edituser->errors, 'errors'); + } - // Si on a touche a ses propres droits, on recharge + // If we are changing our own permissions, we reload if ($object->id == $user->id) { $user->clearrights(); $user->getrights(); @@ -105,9 +109,13 @@ if (empty($reshook)) { if ($action == 'delrights' && $caneditperms) { $edituser = new User($db); $edituser->fetch($object->id); - $edituser->delrights($rights, $module, '', $entity); + $result = $edituser->delrights($rights, $module, '', $entity); + if ($result < 0) + { + setEventMessages($edituser->error, $edituser->errors, 'errors'); + } - // Si on a touche a ses propres droits, on recharge + // If we are changing our own permissions, we reload if ($object->id == $user->id) { $user->clearrights(); $user->getrights(); From ff6bcbdcf883f96a6e5f1da0b5236bf4c2f0011c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 03:01:23 +0100 Subject: [PATCH 26/36] Fix trans --- htdocs/core/modules/modLabel.class.php | 2 +- htdocs/langs/en_US/admin.lang | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/core/modules/modLabel.class.php b/htdocs/core/modules/modLabel.class.php index c387ed69e6e..c6f2c5267b5 100644 --- a/htdocs/core/modules/modLabel.class.php +++ b/htdocs/core/modules/modLabel.class.php @@ -47,7 +47,7 @@ class modLabel extends DolibarrModules $this->module_position = '75'; // Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module) $this->name = preg_replace('/^mod/i', '', get_class($this)); - $this->description = "Gestion des etiquettes"; + $this->description = "Management of stickers"; // Possible values for version are: 'development', 'experimental', 'dolibarr' or version $this->version = 'development'; $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 5cac95078c0..0bf914d0e22 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -545,6 +545,8 @@ Module58Name=ClickToDial Module58Desc=Integration of a ClickToDial system (Asterisk, ...) Module59Name=Bookmark4u Module59Desc=Add function to generate Bookmark4u account from a Dolibarr account +Module60Name=Stickers +Module60Desc=Management of stickers Module70Name=Interventions Module70Desc=Intervention management Module75Name=Expense and trip notes From ccf8e81f93779264198ae6cd5857eb16b52012b6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 03:08:54 +0100 Subject: [PATCH 27/36] FIX #12975 --- htdocs/core/modules/facture/doc/pdf_crabe.modules.php | 2 ++ htdocs/core/modules/facture/doc/pdf_sponge.modules.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index 64aa3c52e25..fa661610d3b 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -903,6 +903,8 @@ class pdf_crabe extends ModelePDFFactures $i++; } + + return $tab3_top + $y + 3; } else { diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php index 3e00e2cab68..2911cf5d5bc 100644 --- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php @@ -1021,6 +1021,8 @@ class pdf_sponge extends ModelePDFFactures $i++; } + + return $tab3_top + $y + 3; } else { From 5633f584770ca81de3f82d3739050006cf1a4063 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 03:25:41 +0100 Subject: [PATCH 28/36] FIX #12978 --- htdocs/core/modules/modStock.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/modules/modStock.class.php b/htdocs/core/modules/modStock.class.php index 6b2dc11605c..bc1971ee3ed 100644 --- a/htdocs/core/modules/modStock.class.php +++ b/htdocs/core/modules/modStock.class.php @@ -348,6 +348,7 @@ class modStock extends DolibarrModules $this->import_examplevalues_array[$r]=array( 'ps.fk_product'=>"PREF123456",'ps.fk_entrepot'=>"ALM001",'ps.reel'=>"10" ); + $this->import_updatekeys_array[$r]=array('ps.fk_product'=>'Product', 'ps.fk_entrepot'=>"Warehouse"); $this->import_run_sql_after_array[$r]=array( // Because we may change data that are denormalized, we must update dernormalized data after. 'UPDATE '.MAIN_DB_PREFIX.'product p SET p.stock= (SELECT SUM(ps.reel) FROM '.MAIN_DB_PREFIX.'product_stock ps WHERE ps.fk_product = p.rowid);' ); From a30da7860f2cfc4afecd606668fb838886669ee7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 03:32:31 +0100 Subject: [PATCH 29/36] FIX #12892 --- htdocs/compta/facture/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 15200582ced..e0c63ca0a8f 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3889,7 +3889,7 @@ elseif ($id > 0 || !empty($ref)) } // Call Hook formConfirm - $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid); + $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid, 'remainingtopay' => &$resteapayer); $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook if (empty($reshook)) $formconfirm .= $hookmanager->resPrint; elseif ($reshook > 0) $formconfirm = $hookmanager->resPrint; From b3a50bd4b0e701bb68bd2ed6654f061bae344c91 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 03:47:45 +0100 Subject: [PATCH 30/36] FIX #12874 --- htdocs/user/class/api_users.class.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/htdocs/user/class/api_users.class.php b/htdocs/user/class/api_users.class.php index be768a3e15a..fa139e2c69f 100644 --- a/htdocs/user/class/api_users.class.php +++ b/htdocs/user/class/api_users.class.php @@ -132,15 +132,15 @@ class Users extends DolibarrApi /** * Get properties of an user object - * * Return an array with user informations * - * @param int $id ID of user + * @param int $id ID of user + * @param int $includepermissions Set this to 1 to have the array of permissions loaded (not done by default for performance purpose) * @return array|mixed data without useless information * * @throws RestException */ - public function get($id) + public function get($id, $includepermissions = 0) { //if (!DolibarrApiAccess::$user->rights->user->user->lire) { //throw new RestException(401); @@ -157,6 +157,10 @@ class Users extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } + if ($includepermissions) { + $this->useraccount->getRights(); + } + return $this->_cleanObjectDatas($this->useraccount); } @@ -544,6 +548,12 @@ class Users extends DolibarrApi unset($object->clicktodial_password); unset($object->openid); + unset($object->lines); + unset($object->modelpdf); + unset($object->skype); + unset($object->twitter); + unset($object->facebook); + unset($object->linkedin); $canreadsalary = ((!empty($conf->salaries->enabled) && !empty(DolibarrApiAccess::$user->rights->salaries->read)) || (!empty($conf->hrm->enabled) && !empty(DolibarrApiAccess::$user->rights->hrm->employee->read))); From 1dab308e4a50261e5c83f52a0f55b00c6a1efcac Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 03:55:37 +0100 Subject: [PATCH 31/36] FIX #12932 --- htdocs/core/class/CMailFile.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index c4c0aed1756..e0a1fd35092 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -508,7 +508,7 @@ class CMailFile $res = false; - if (empty($conf->global->MAIN_DISABLE_ALL_MAILS) || !empty($conf->global->MAIN_MAIL_FORCE_SENDTO)) + if (empty($conf->global->MAIN_DISABLE_ALL_MAILS)) { require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; $hookmanager = new HookManager($db); From 7c35e9aaa862f7b8b50c2f22aa0af2e830c8a9ac Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 03:55:37 +0100 Subject: [PATCH 32/36] FIX #12932 --- htdocs/core/class/CMailFile.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 4d796bbcd07..402b19701d7 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -485,7 +485,7 @@ class CMailFile $res=false; - if (empty($conf->global->MAIN_DISABLE_ALL_MAILS) || !empty($conf->global->MAIN_MAIL_FORCE_SENDTO)) + if (empty($conf->global->MAIN_DISABLE_ALL_MAILS)) { require_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php'; $hookmanager = new HookManager($db); From e5808e3335591c32ec87628a3f9b6b65b30698fe Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 04:48:17 +0100 Subject: [PATCH 33/36] FIX #12995 --- htdocs/bom/bom_card.php | 8 ++++++++ htdocs/core/class/commonobject.class.php | 7 +++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 87396dccb30..3f1be6c7e4c 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -155,6 +155,8 @@ if (empty($reshook)) if (!$error) { + $lastposition = 0; + $bomline = new BOMLine($db); $bomline->fk_bom = $id; $bomline->fk_product = $idprod; @@ -163,6 +165,12 @@ if (empty($reshook)) $bomline->disable_stock_change = (int) $disable_stock_change; $bomline->efficiency = $efficiency; + // Rang to use + $rangmax = $object->line_max(0); + $ranktouse = $rangmax + 1; + + $bomline->position = ($ranktouse + 1); + $result = $bomline->create($user); if ($result <= 0) { diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 14433ff79db..dd2973cb1fb 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2744,10 +2744,13 @@ abstract class CommonObject public function line_max($fk_parent_line = 0) { // phpcs:enable + $positionfield = 'rang'; + if ($this->table_element = 'bom') $positionfield = 'position'; + // Search the last rang with fk_parent_line if ($fk_parent_line) { - $sql = 'SELECT max(rang) FROM '.MAIN_DB_PREFIX.$this->table_element_line; + $sql = 'SELECT max('.$positionfield.') FROM '.MAIN_DB_PREFIX.$this->table_element_line; $sql .= ' WHERE '.$this->fk_element.' = '.$this->id; $sql .= ' AND fk_parent_line = '.$fk_parent_line; @@ -2769,7 +2772,7 @@ abstract class CommonObject // If not, search the last rang of element else { - $sql = 'SELECT max(rang) FROM '.MAIN_DB_PREFIX.$this->table_element_line; + $sql = 'SELECT max('.$positionfield.') FROM '.MAIN_DB_PREFIX.$this->table_element_line; $sql .= ' WHERE '.$this->fk_element.' = '.$this->id; dol_syslog(get_class($this)."::line_max", LOG_DEBUG); From d8ed62ea330edc42990e4e76c2ee668017f62d5e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 06:28:51 +0100 Subject: [PATCH 34/36] Fix line_max for BOM --- htdocs/core/class/commonobject.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index dd2973cb1fb..750fbc59135 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -2745,7 +2745,7 @@ abstract class CommonObject { // phpcs:enable $positionfield = 'rang'; - if ($this->table_element = 'bom') $positionfield = 'position'; + if ($this->table_element == 'bom') $positionfield = 'position'; // Search the last rang with fk_parent_line if ($fk_parent_line) From 87f84e5b17cdac337aeedb9c2b1ad525aea154de Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 06:28:04 +0100 Subject: [PATCH 35/36] FIX #12973 --- dev/dolibarr_changes.txt | 43 +++++++++++++++++++++- htdocs/includes/tecnickcom/tcpdf/tcpdf.php | 6 ++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/dev/dolibarr_changes.txt b/dev/dolibarr_changes.txt index 51eeef8af31..107f561eca6 100644 --- a/dev/dolibarr_changes.txt +++ b/dev/dolibarr_changes.txt @@ -63,10 +63,49 @@ with if (isset($this->imagekeys)) { foreach($this->imagekeys as $file) { -// unlink($file); + // DOL CHANGE If we keep this, source image files are physically destroyed + // unlink($file); } } +* Replace in tcpdf.php + + $preserve = array( + 'file_id', + 'internal_encoding', + 'state', + 'bufferlen', + 'buffer', + 'cached_files', + +with + + $preserve = array( + 'file_id', + 'internal_encoding', + 'state', + 'bufferlen', + 'buffer', + 'cached_files', + // @CHANGE DOL + 'imagekeys', + +* Replace in tcpdf.php + + if (!@TCPDF_STATIC::file_exists($file)) { + return false; + } + +with + + if (!@TCPDF_STATIC::file_exists($file)) { + // DOL CHANGE If we keep this, the image is not visible on pages after the first one. + //var_dump($file.' '.(!@TCPDF_STATIC::file_exists($file))); + //return false; + } + + + * In tecnickcom/tcpdf/include/tcpdf_static, in function fopenLocal, replace if (strpos($filename, '://') === false) { @@ -102,7 +141,7 @@ In htdocs/includes/tecnickcom/tcpdf/tcpdf.php + protected $default_monospaced_font = 'freemono'; - + TCPDI: ------ diff --git a/htdocs/includes/tecnickcom/tcpdf/tcpdf.php b/htdocs/includes/tecnickcom/tcpdf/tcpdf.php index aa66879f7a1..dd20e957d5b 100644 --- a/htdocs/includes/tecnickcom/tcpdf/tcpdf.php +++ b/htdocs/includes/tecnickcom/tcpdf/tcpdf.php @@ -6878,7 +6878,9 @@ class TCPDF { } // check if file exist and it is valid if (!@TCPDF_STATIC::file_exists($file)) { - return false; + // DOL CHANGE If we keep this, the image is not visible on pages after the first one. + //var_dump($file.' '.(!@TCPDF_STATIC::file_exists($file))); + //return false; } if (($imsize = @getimagesize($file)) === FALSE) { if (in_array($file, $this->imagekeys)) { @@ -7810,6 +7812,8 @@ class TCPDF { 'bufferlen', 'buffer', 'cached_files', +// @CHANGE DOL +// 'imagekeys', 'sign', 'signature_data', 'signature_max_length', From 2813c9d4b4a663265b5c45a858bc3265b8bc5b6a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 3 Feb 2020 06:31:40 +0100 Subject: [PATCH 36/36] FIX #12973 --- htdocs/includes/tecnickcom/tcpdf/tcpdf.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/includes/tecnickcom/tcpdf/tcpdf.php b/htdocs/includes/tecnickcom/tcpdf/tcpdf.php index 24ef434ab8a..f5a6b9aa931 100644 --- a/htdocs/includes/tecnickcom/tcpdf/tcpdf.php +++ b/htdocs/includes/tecnickcom/tcpdf/tcpdf.php @@ -6846,7 +6846,7 @@ class TCPDF { } // check if file exist and it is valid if (!@TCPDF_STATIC::file_exists($file)) { - return false; + //return false; } if (($imsize = @getimagesize($file)) === FALSE) { if (in_array($file, $this->imagekeys)) {