From f37a62b1d45e185a949184a7b28672bcb85433b9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 4 Jul 2021 21:40:30 +0200 Subject: [PATCH 1/8] CSS v14 --- htdocs/theme/md/style.css.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index aa87a36f01d..8a642a0e170 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -3091,8 +3091,8 @@ div.tabsElem a { div.tabBar { color: #; padding-top: 21px; - padding-left: 18px; - padding-right: 18px; + padding-left: 24px; + padding-right: 24px; padding-bottom: 18px; margin: 0px 0px 18px 0px; -webkit-border-radius: 3px; @@ -3439,9 +3439,9 @@ tr.liste_titre_filter td.liste_titre { } .liste_titre_create td, .liste_titre_create th, .liste_titre_create .tagtd { - /*border-top-width: 1px; + border-top-width: 1px; border-top-color: rgb(); - border-top-style: solid;*/ + border-top-style: solid; } .liste_titre_add td, .liste_titre_add th, .liste_titre_add .tagtd { @@ -3830,7 +3830,7 @@ div.liste_titre_bydiv, .liste_titre div.tagtr, tr.liste_titre, tr.liste_titre_se { background: rgb(); font-weight: ; - border-bottom: 1px solid #FDFFFF; + /* border-bottom: 1px solid #FDFFFF; */ color: rgb(); font-family: ; From dfee489e7e1650fab9c187406a40c4275a0ff731 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 5 Jul 2021 11:33:32 +0200 Subject: [PATCH 2/8] Fix sanitizing entity --- htdocs/user/class/user.class.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 37ce6544cd0..ef530cbe6f5 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -442,7 +442,7 @@ class User extends CommonObject if ($entity < 0) { if ((empty($conf->multicompany->enabled) || empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) && (!empty($user->entity))) { - $sql .= " WHERE u.entity IN (0, ".$this->db->sanitize($conf->entity).")"; + $sql .= " WHERE u.entity IN (0, ".((int) $conf->entity).")"; } else { $sql .= " WHERE u.entity IS NOT NULL"; // multicompany is on in transverse mode or user making fetch is on entity 0, so user is allowed to fetch anywhere into database } @@ -451,7 +451,7 @@ class User extends CommonObject if (!empty($conf->multicompany->enabled) && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { $sql .= " WHERE u.entity IS NOT NULL"; // multicompany is on in transverse mode or user making fetch is on entity 0, so user is allowed to fetch anywhere into database } else { - $sql .= " WHERE u.entity IN (0, ".$this->db->sanitize(($entity != '' && $entity >= 0) ? $entity : $conf->entity).")"; // search in entity provided in parameter + $sql .= " WHERE u.entity IN (0, ".((int) (($entity != '' && $entity >= 0) ? $entity : $conf->entity)).")"; // search in entity provided in parameter } } @@ -2109,8 +2109,8 @@ class User extends CommonObject $outputlangs = new Translate("", $conf); if (isset($this->conf->MAIN_LANG_DEFAULT) - && $this->conf->MAIN_LANG_DEFAULT != 'auto') { // If user has defined its own language (rare because in most cases, auto is used) - $outputlangs->getDefaultLang($this->conf->MAIN_LANG_DEFAULT); + && $this->conf->MAIN_LANG_DEFAULT != 'auto') { // If user has defined its own language (rare because in most cases, auto is used) + $outputlangs->getDefaultLang($this->conf->MAIN_LANG_DEFAULT); } if ($this->conf->MAIN_LANG_DEFAULT) { @@ -2184,7 +2184,7 @@ class User extends CommonObject '', '', $trackid - ); + ); if ($mailfile->sendfile()) { return 1; @@ -3222,8 +3222,8 @@ class User extends CommonObject foreach ($this->users as $key => $val) { if (preg_match('/'.$keyfilter1.'/', $val['fullpath']) || preg_match('/'.$keyfilter2.'/', $val['fullpath']) || preg_match('/'.$keyfilter3.'/', $val['fullpath']) || preg_match('/'.$keyfilter4.'/', $val['fullpath'])) { - unset($this->users[$key]); - } + unset($this->users[$key]); + } } } From b7c86f3aeccf5b935de5e213608b2c5e5388a96f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 5 Jul 2021 11:41:55 +0200 Subject: [PATCH 3/8] Fix ldap --- htdocs/core/login/functions_ldap.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/htdocs/core/login/functions_ldap.php b/htdocs/core/login/functions_ldap.php index 9de95be506b..0f3927709eb 100644 --- a/htdocs/core/login/functions_ldap.php +++ b/htdocs/core/login/functions_ldap.php @@ -29,7 +29,7 @@ * * @param string $usertotest Login * @param string $passwordtotest Password - * @param int $entitytotest Number of instance (always 1 if module multicompany not enabled) + * @param int $entitytotest Numero of instance (always 1 if module multicompany not enabled) * @return string Login if OK, '' if KO */ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) @@ -151,10 +151,13 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) if ($result > 0) { if ($result == 2) { // Connection is ok for user/pass into LDAP $login = $usertotest; - if (!empty($conf->global->LDAP_FIELD_LOGIN)) { - $login = $ldap->login; - } dol_syslog("functions_ldap::check_user_password_ldap $login authentication ok"); + // For the case, we search the user id using a search key without the login (but using other fields like id), + // we need to get the real login to use in the ldap answer. + if (!empty($conf->global->LDAP_FIELD_LOGIN) && !empty($ldap->login)) { + $login = $ldap->login; + dol_syslog("functions_ldap::check_user_password_ldap login is now $login (LDAP_FIELD_LOGIN=".$conf->global->LDAP_FIELD_LOGIN.")"); + } require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; @@ -207,7 +210,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) } $usertmp = new User($db); - $resultFetchUser = $usertmp->fetch('', $login, $sid); + $resultFetchUser = $usertmp->fetch('', $login, $sid, 1, ($entitytotest > 0 ? $entitytotest : -1)); if ($resultFetchUser > 0) { dol_syslog("functions_ldap::check_user_password_ldap Sync user found user id=".$usertmp->id); // On verifie si le login a change et on met a jour les attributs dolibarr @@ -215,7 +218,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) if ($usertmp->login != $ldap->login && $ldap->login) { $usertmp->login = $ldap->login; $usertmp->update($usertmp); - // TODO Que faire si update echoue car on update avec un login deja existant. + // TODO Que faire si update echoue car on update avec un login deja existant pour un autre compte. } //$resultUpdate = $usertmp->update_ldap2dolibarr($ldap); @@ -231,7 +234,7 @@ function check_user_password_ldap($usertotest, $passwordtotest, $entitytotest) $usertmp->fetch('', $login); $ret = $mc->checkRight($usertmp->id, $entitytotest); if ($ret < 0) { - dol_syslog("functions_ldap::check_user_password_ldap Authentication KO entity '".$entitytotest."' not allowed for user '".$usertmp->id."'", LOG_NOTICE); + dol_syslog("functions_ldap::check_user_password_ldap Authentication KO entity '".$entitytotest."' not allowed for user id '".$usertmp->id."'", LOG_NOTICE); $login = ''; // force authentication failure } unset($usertmp); From 2eddc02deb6f2eb7f353606f15bb75637a127076 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 5 Jul 2021 11:59:30 +0200 Subject: [PATCH 4/8] Fix selection of Autofill description --- htdocs/product/admin/product.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/product/admin/product.php b/htdocs/product/admin/product.php index b23cfbc5c4c..867876f4631 100644 --- a/htdocs/product/admin/product.php +++ b/htdocs/product/admin/product.php @@ -624,9 +624,10 @@ if (empty($conf->global->PRODUIT_USE_SEARCH_TO_SELECT)) { print ''; print ''.$langs->trans("OnProductSelectAddProductDesc").''; print ''; +print ''; print $form->selectarray( "activate_FillProductDescAuto", - array(1=>'AutoFillFormFieldBeforeSubmit', 0=>'DoNotAutofillButAutoConcat', -1=>'DoNotUseDescriptionOfProdut'), + array(0=>'DoNotAutofillButAutoConcat', 1=>'AutoFillFormFieldBeforeSubmit', 2=>'DoNotUseDescriptionOfProdut'), empty($conf->global->PRODUIT_AUTOFILL_DESC) ? 0 : $conf->global->PRODUIT_AUTOFILL_DESC, 0, 0, From d43e043b48bf531737f2d2dca7c7ed0f2669cb46 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 5 Jul 2021 12:49:10 +0200 Subject: [PATCH 5/8] Fix regression when adding a product with multicompany --- htdocs/product/class/product.class.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index fdc50d5fe87..0ac8cba1391 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2236,7 +2236,7 @@ class Product extends CommonObject // Check parameters if (!$id && !$ref && !$ref_ext && !$barcode) { $this->error = 'ErrorWrongParameters'; - dol_syslog(get_class($this)."::fetch ".$this->error); + dol_syslog(get_class($this)."::fetch ".$this->error, LOG_ERR); return -1; } @@ -2286,7 +2286,7 @@ class Product extends CommonObject $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); } if ($separatedStock) { - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_stock as sp ON sp.fk_product = p.rowid"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_stock as sp ON sp.fk_product = p.rowid AND sp.fk_entrepot IN (SELECT rowid FROM ".MAIN_DB_PREFIX."entrepot WHERE entity IN (".$this->db->sanitize($visibleWarehousesEntities)."))"; } if ($id) { $sql .= " WHERE p.rowid = ".((int) $id); @@ -2300,9 +2300,6 @@ class Product extends CommonObject $sql .= " AND p.barcode = '".$this->db->escape($barcode)."'"; } } - if ($separatedStock) { - $sql .= " AND sp.fk_entrepot IN (SELECT rowid FROM ".MAIN_DB_PREFIX."entrepot WHERE entity IN (".$this->db->sanitize($visibleWarehousesEntities)."))"; - } if ($separatedStock) { $sql .= " GROUP BY p.rowid, p.ref, p.ref_ext, p.label, p.description, p.url, p.note_public, p.note, p.customcode, p.fk_country, p.fk_state, p.lifetime, p.qc_frequency, p.price, p.price_ttc,"; $sql .= " p.price_min, p.price_min_ttc, p.price_base_type, p.cost_price, p.default_vat_code, p.tva_tx, p.recuperableonly, p.localtax1_tx, p.localtax2_tx, p.localtax1_type, p.localtax2_type, p.tosell,"; From 383c6782001f79c7c6950abcbc32aee5d656de09 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 5 Jul 2021 14:09:01 +0200 Subject: [PATCH 6/8] Trans --- htdocs/langs/en_US/admin.lang | 1 + htdocs/product/admin/product.php | 54 +++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 2a726e9eefe..0e357e27577 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -53,6 +53,7 @@ InternalUser=Internal user ExternalUser=External user InternalUsers=Internal users ExternalUsers=External users +UserInterface=User interface GUISetup=Display SetupArea=Setup UploadNewTemplate=Upload new template(s) diff --git a/htdocs/product/admin/product.php b/htdocs/product/admin/product.php index 867876f4631..5a83c685e0f 100644 --- a/htdocs/product/admin/product.php +++ b/htdocs/product/admin/product.php @@ -507,14 +507,16 @@ print "
"; print "
"; -print load_fiche_titre($langs->trans("ProductOtherConf"), '', ''); - print '
'; print ''; print ''; print ''; + +print load_fiche_titre($langs->trans("ProductOtherConf"), '', ''); + + print ''; print ''; print ''."\n"; @@ -592,6 +594,38 @@ print $form->selectPriceBaseType($conf->global->PRODUCT_PRICE_BASE_TYPE, "price_ print ''; print ''; +if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { + print ''; + print ''; + print ''; + print ''; + + print ''; + print ''; + print ''; + print ''; +} + +print '
'.$langs->trans("Parameters").'
'.$langs->trans("UseProductFournDesc").''; + print $form->selectyesno("activate_useProdFournDesc", (!empty($conf->global->PRODUIT_FOURN_TEXTS) ? $conf->global->PRODUIT_FOURN_TEXTS : 0), 1); + print '
'.$langs->trans("UseProductSupplierPackaging").''; + print $form->selectyesno("activate_useProdSupplierPackaging", (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING) ? $conf->global->PRODUCT_USE_SUPPLIER_PACKAGING : 0), 1); + print '
'; + +print '
'; +print ''; +print '
'; + + +print load_fiche_titre($langs->trans("UserInterface"), '', ''); + + +print ''; +print ''; +print ''."\n"; +print ''."\n"; +print ''."\n"; + // Use Ajax form to select a product print ''; @@ -683,22 +717,6 @@ if (!empty($conf->global->MAIN_MULTILANGS)) { print ''; } -if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) { - print ''; - print ''; - print ''; - print ''; - - print ''; - print ''; - print ''; - print ''; -} - if (!empty($conf->global->PRODUCT_CANVAS_ABILITY)) { // Add canvas feature From 87241c94a3e589589c7250a9701c2d2cb29744d0 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 5 Jul 2021 14:41:40 +0200 Subject: [PATCH 7/8] Code comment --- htdocs/install/mysql/tables/llx_actioncomm.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/tables/llx_actioncomm.sql b/htdocs/install/mysql/tables/llx_actioncomm.sql index 9012f6b3a66..2f3f7660698 100644 --- a/htdocs/install/mysql/tables/llx_actioncomm.sql +++ b/htdocs/install/mysql/tables/llx_actioncomm.sql @@ -55,7 +55,7 @@ create table llx_actioncomm durationp real, -- planed duration label varchar(255) NOT NULL, -- label/title of event or topic of email - note text, -- note of event or content of email + note text, -- private note of event or content of email calling_duration integer, -- when event is a phone call, duration of phone call From 8b07e99e05a9ed3c57bdc00c6a469fbbaa5672ef Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 5 Jul 2021 16:08:47 +0200 Subject: [PATCH 8/8] Fix for ' inserted by CKEditor instead of ' --- htdocs/core/lib/functions.lib.php | 6 +++++- test/phpunit/SecurityTest.php | 9 +++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 13358074514..da93b01fc26 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -778,12 +778,16 @@ function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = do { $oldstringtoclean = $out; + // Ckeditor use the numeric entitic for apostrophe so we force it to text entity (all other special chars are correctly + // encoded using text entities). This is a fix for CKeditor. + $out = preg_replace('/'/i', ''', $out); + // We replace chars from a/A to z/Z encoded with numeric HTML entities with the real char so we won't loose the chars at the next step. // No need to use a loop here, this step is not to sanitize (this is done at next step, this is to try to save chars, even if they are // using a non coventionnel way to be encoded, to not have them sanitized just after) $out = preg_replace_callback('/&#(x?[0-9][0-9a-f]+;?)/i', 'realCharForNumericEntities', $out); - // Now we remove all remaining HTML entities staring with a number. We don't want such entities. + // Now we remove all remaining HTML entities starting with a number. We don't want such entities. $out = preg_replace('/&#x?[0-9]+/i', '', $out); // For example if we have javascript with an entities without the ; to hide the 'a' of 'javascript'. $out = dol_string_onlythesehtmltags($out, 0, 1, 1); diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index 08d4ec88703..d75ec962020 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -321,6 +321,10 @@ class SecurityTest extends PHPUnit\Framework\TestCase $test="XSS"; $result=testSqlAndScriptInject($test, 0); $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject lll'); + + $test="Text with ' encoded with the numeric html entity converted into text entity ' (like when submited by CKEditor)"; + $result=testSqlAndScriptInject($test, 0); + $this->assertGreaterThanOrEqual($expectedresult, $result, 'Error on testSqlAndScriptInject mmm'); } /** @@ -358,6 +362,7 @@ class SecurityTest extends PHPUnit\Framework\TestCase $_POST["param12"]='aaa'; $_POST["param13"]='n n > < " XSS'; $_POST["param13b"]='n n > < " XSS'; + $_POST["param14"]="Text with ' encoded with the numeric html entity converted into text entity ' (like when submited by CKEditor)"; //$_POST["param13"]='javascript%26colon%26%23x3B%3Balert(1)'; //$_POST["param14"]='javascripT&javascript#x3a alert(1)'; @@ -494,6 +499,10 @@ class SecurityTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; $this->assertEquals('n n > < " XSS', $result, 'Test 13b that HTML entities are decoded with restricthtml, but only for common alpha chars'); + $result=GETPOST("param14", 'restricthtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals("Text with ' encoded with the numeric html entity converted into text entity ' (like when submited by CKEditor)", $result, 'Test 14'); + // Special test for GETPOST of backtopage, backtolist or backtourl parameter $_POST["backtopage"]='//www.google.com';
'.$langs->trans("Parameters").''.$langs->trans("Value").'
'.$langs->trans("UseProductFournDesc").''; - print $form->selectyesno("activate_useProdFournDesc", (!empty($conf->global->PRODUIT_FOURN_TEXTS) ? $conf->global->PRODUIT_FOURN_TEXTS : 0), 1); - print '
'.$langs->trans("UseProductSupplierPackaging").''; - print $form->selectyesno("activate_useProdSupplierPackaging", (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING) ? $conf->global->PRODUCT_USE_SUPPLIER_PACKAGING : 0), 1); - print '