diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 84770acdaff..99bb64843d8 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -590,7 +590,7 @@ if ($type == Categorie::TYPE_CUSTOMER) { print ''; print ''; print ''; @@ -671,7 +671,7 @@ if ($type == Categorie::TYPE_SUPPLIER) { print '
'; print $langs->trans("AddCustomerIntoCategory").'  '; - $filter = 's.client IN (1,3)'; + $filter = '(s.client:IN:1,3)'; print $form->select_company('', 'elemid', $filter); print '
'; print ''; print ''; diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index d28753632d2..7f28a26fa9b 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1810,7 +1810,7 @@ if ($action == 'create') { //$warehouse_id = $soc->warehouse_id; } else { print ''; // ThirdParty Type diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index d79cc54b907..17ade08b776 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1787,8 +1787,8 @@ if ($action == 'create' && $usercancreate) { print ''; print ''; } else { - print ''; print ''; print '
'; print $langs->trans("AddSupplierIntoCategory").'  '; - $filter ='s.fournisseur = 1'; + $filter ='(s.fournisseur:=:1)'; print $form->select_company('', 'elemid', $filter); print '
'; - $filter = '((s.client = 1 OR s.client = 2 OR s.client = 3) AND status=1)'; + $filter = '((s.client:IN:1,2,3) AND (s.status:=:1))'; print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 1, 0, null, 0, 'minwidth300 maxwidth500 widthcentpercentminusxx'); // reload page to retrieve customer informations if (empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED)) { @@ -2134,7 +2134,7 @@ if ($action == 'create') { // Clone confirmation if ($action == 'clone') { // Create an array for form - $filter = '(s.client=1 OR s.client=2 OR s.client=3)'; + $filter = '(s.client:IN:1,2,3)'; $formquestion = array( // 'text' => $langs->trans("ConfirmClone"), // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), diff --git a/htdocs/comm/propal/stats/index.php b/htdocs/comm/propal/stats/index.php index d8279fdc646..382ccfd55b7 100644 --- a/htdocs/comm/propal/stats/index.php +++ b/htdocs/comm/propal/stats/index.php @@ -264,7 +264,7 @@ print '
'.$langs->tra // Company print '
'.$langs->trans("ThirdParty").''; print img_picto('', 'company', 'class="pictofixedwidth"'); -$filter = 's.client IN (1,2,3)'; +$filter = '(s.client:IN:1,2,3)'; print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300', ''); print '
'; - $filter = '((s.client = 1 OR s.client = 2 OR s.client = 3) AND s.status=1)'; + print ''; + $filter = '((s.client:IN:1,2,3) AND (s.status:=:1))'; print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 1, 0, null, 0, 'minwidth175 maxwidth500 widthcentpercentminusxx'); // reload page to retrieve customer informations if (empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED)) { @@ -2338,7 +2338,7 @@ if ($action == 'create' && $usercancreate) { // Clone confirmation if ($action == 'clone') { - $filter = '(s.client=1 OR s.client = 2 OR s.client=3)'; + $filter = '(s.client:IN:1,2,3)'; // Create an array for form $formquestion = array( array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter, '', 0, 0, null, 0, 'maxwidth300')) diff --git a/htdocs/commande/stats/index.php b/htdocs/commande/stats/index.php index c4c0e5dbf41..51906e2ff70 100644 --- a/htdocs/commande/stats/index.php +++ b/htdocs/commande/stats/index.php @@ -297,10 +297,10 @@ print '
'.$langs->tra print '
'.$langs->trans("ThirdParty").''; $filter = ''; if ($mode == 'customer') { - $filter = 's.client IN (1,2,3)'; + $filter = '(s.client:IN:1,2,3)'; } if ($mode == 'supplier') { - $filter = 's.fournisseur = 1'; + $filter = '(s.fournisseur:=:1)'; } print img_picto('', 'company', 'class="pictofixedwidth"'); print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300'); diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index fdf75498811..afff624102b 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3205,7 +3205,7 @@ if ($action == 'create') { } else { print '
'.$langs->trans('Customer').''; - $filter = '((s.client = 1 OR s.client = 3) AND s.status = 1)'; + $filter = '((s.client:=:1,3) AND (s.status:=:1))'; print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company($soc->id, 'socid', $filter, 'SelectThirdParty', 1, 0, null, 0, 'minwidth300 widthcentpercentminusxx maxwidth500'); // Option to reload page to retrieve customer informations. if (empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED)) { @@ -4320,7 +4320,7 @@ if ($action == 'create') { // Clone confirmation if ($action == 'clone') { - $filter = '(s.client=1 OR s.client=2 OR s.client=3)'; + $filter = '(s.client:IN:1,2,3)'; // Create an array for form $formquestion = array( array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company($object->socid, 'socid', $filter, 1)), diff --git a/htdocs/compta/facture/stats/index.php b/htdocs/compta/facture/stats/index.php index f8d0f1a9f41..b886c5595e1 100644 --- a/htdocs/compta/facture/stats/index.php +++ b/htdocs/compta/facture/stats/index.php @@ -279,10 +279,10 @@ print '
'.$langs->tra print '
'.$langs->trans("ThirdParty").''; $filter = ''; if ($mode == 'customer') { - $filter = 's.client in (1,2,3)'; + $filter = '(s.client:IN:1,2,3)'; } if ($mode == 'supplier') { - $filter = 's.fournisseur = 1'; + $filter = '(s.fournisseur:=:1)'; } print img_picto('', 'company', 'class="pictofixedwidth"'); print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300'); diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 0430f937d1d..0b45cb88215 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -1332,7 +1332,7 @@ if ($action == 'create') { ); $formconfirm = $form->formconfirm($_SERVER['PHP_SELF']."?id=".$object->id, $langs->trans("ActivateAllOnContract"), $langs->trans("ConfirmActivateAllOnContract"), "confirm_activate", $formquestion, 'yes', 1, 280); } elseif ($action == 'clone') { - $filter = '(s.client=1 OR s.client=2 OR s.client=3)'; + $filter = '(s.client:IN:1,2,3)'; // Clone confirmation $formquestion = array(array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter))); $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneContract', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 527dba8eb3d..58e8836852b 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1368,7 +1368,9 @@ class Form * * @param string $selected Preselected type * @param string $htmlname Name of field in form - * @param string $filter Optional filters criteras. WARNING: To avoid SQL injection, only few chars [.a-z0-9 =<>()] are allowed here (example: 's.rowid <> x', 's.client IN (1,3)'). Do not use a filter coming from input of users. + * @param string $filter Optional filters criteras. WARNING: To avoid SQL injection, only few chars [.a-z0-9 =<>] are allowed here, example: 's.rowid <> x' + * If you need parenthesis, use the Universal Filter Syntax, example: '(s.client:in:(1,3))' + * Do not use a filter coming from input of users. * @param string $showempty Add an empty field (Can be '1' or text to use on empty line like 'SelectThirdParty') * @param int $showtype Show third party type in combolist (customer, prospect or supplier) * @param int $forcecombo Force to use standard HTML select component without beautification @@ -1407,8 +1409,23 @@ class Form } } - //$errormsg = ''; - //$filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg); + if (preg_match('/[\(\)]/', $filter)) { + // If there is one parenthesis inside the criteria, we assume it is an Universal Filter Syntax. + $errormsg = ''; + $filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg, 1); + + // Redo clean $filter that may contains sql conditions so sql code + if (function_exists('testSqlAndScriptInject')) { + if (testSqlAndScriptInject($filter, 3) > 0) { + $filter = ''; + return 'SQLInjectionTryDetected'; + } + } + } else { + // If not, we do nothing. We already no that there is no parenthesis + // TODO Disallow this case in a future. + dol_syslog("Warning, select_thirdparty_list was called with a filter criteria not using the Universal Search Syntax.", LOG_WARNING); + } // We search companies $sql = "SELECT s.rowid, s.nom as name, s.name_alias, s.tva_intra, s.client, s.fournisseur, s.code_client, s.code_fournisseur"; @@ -1428,6 +1445,8 @@ class Form $sql .= " AND s.rowid = " . ((int) $user->socid); } if ($filter) { + // $filter is safe because, if it contains '(' or ')', it has been sanitized by testSqlAndScriptInject() and forgeSQLFromUniversalSearchCriteria() + // if not, by testSqlAndScriptInject() only. $sql .= " AND (" . $filter . ")"; } if (empty($user->rights->societe->client->voir) && !$user->socid) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index fad1f6266c3..7bf81f84e2c 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -11789,9 +11789,10 @@ function jsonOrUnserialize($stringtodecode) * aaa is a field name (with alias or not) and * bbb is one of this operator '=', '<', '>', '<=', '>=', '!=', 'in', 'notin', 'like', 'notlike', 'is', 'isnot'. * @param string $error Error message + * @param int $noand 0=Default, 1=Do not add the AND before the condition string. * @return string Return forged SQL string */ -function forgeSQLFromUniversalSearchCriteria($filter, &$error = '') +function forgeSQLFromUniversalSearchCriteria($filter, &$error = '', $noand = 0) { $regexstring = '\(([a-zA-Z0-9_\.]+:[<>!=insotlke]+:[^\(\)]+)\)'; // Must be (aaa:bbb:...) with aaa is a field name (with alias or not) and bbb is one of this operator '=', '<', '>', '<=', '>=', '!=', 'in', 'notin', 'like', 'notlike', 'is', 'isnot' @@ -11808,7 +11809,7 @@ function forgeSQLFromUniversalSearchCriteria($filter, &$error = '') return 'Filter syntax error'; // Bad syntax of the search string, we force a SQL not found } - return " AND (".preg_replace_callback('/'.$regexstring.'/i', 'dolForgeCriteriaCallback', $filter).")"; + return ($noand ? "" : " AND ")."(".preg_replace_callback('/'.$regexstring.'/i', 'dolForgeCriteriaCallback', $filter).")"; } /** diff --git a/htdocs/don/card.php b/htdocs/don/card.php index f396b5d386f..9ad6f04f545 100644 --- a/htdocs/don/card.php +++ b/htdocs/don/card.php @@ -440,7 +440,7 @@ if ($action == 'create') { } else { print ''.$langs->trans('ThirdParty').''; - $filter = '(s.client = 1 OR s.client = 3) AND status=1'; + $filter = '((s.client:IN:1,3) AND (status:=:1))'; print $form->select_company($soc->id, 'socid', $filter, 'SelectThirdParty', 0, 0, null, 0, 'minwidth300'); // Option to reload page to retrieve customer informations. Note, this clear other input if (!empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED)) { diff --git a/htdocs/fichinter/stats/index.php b/htdocs/fichinter/stats/index.php index cec740fdd9c..39dcdd9589d 100644 --- a/htdocs/fichinter/stats/index.php +++ b/htdocs/fichinter/stats/index.php @@ -220,7 +220,7 @@ print ''; print ''; // Company print ''; diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index ed89b13bd77..a3f9e8e234e 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -1694,7 +1694,7 @@ if ($action == 'create') { print $societe->getNomUrl(1, 'supplier'); print ''; } else { - $filter = '(s.fournisseur=1 AND s.status=1)'; + $filter = '((s.fournisseur:=:1) AND (s.status:=:1))'; print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company((empty($socid) ? '' : $socid), 'socid', $filter, 'SelectThirdParty', 1, 0, null, 0, 'minwidth175 maxwidth500 widthcentpercentminusxx'); // reload page to retrieve customer informations if (empty($conf->global->RELOAD_PAGE_ON_SUPPLIER_CHANGE_DISABLED)) { @@ -1899,7 +1899,7 @@ if ($action == 'create') { // Clone confirmation if ($action == 'clone') { - $filter = '(s.fournisseur=1)'; + $filter = '(s.fournisseur:=:1)'; // Create an array for form $formquestion = array( array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter)) @@ -2036,7 +2036,7 @@ if ($action == 'create') { $morehtmlref .= ''; $morehtmlref .= ''; $morehtmlref .= ''; - $filter = 's.fournisseur=1'; + $filter = '(s.fournisseur:=:1)'; $morehtmlref .= $form->select_company($object->thirdparty->id, 'new_socid', $filter, '', 0, 0, array(), 0, 'minwidth300'); $morehtmlref .= ''; $morehtmlref .= ''; diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 29eb57d47bd..e43b25b26f1 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -2199,7 +2199,7 @@ if ($action == 'create') { print $societe->getNomUrl(1, 'supplier'); print ''; } else { - $filter = '(s.fournisseur = 1 AND s.status = 1)'; + $filter = '((s.fournisseur:=:1) AND (s.status:=:1))'; print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(empty($societe->id) ? 0 : $societe->id, 'socid', $filter, 'SelectThirdParty', 1, 0, null, 0, 'minwidth175 widthcentpercentminusxx maxwidth500'); // reload page to retrieve supplier informations if (empty($conf->global->RELOAD_PAGE_ON_SUPPLIER_CHANGE_DISABLED)) { diff --git a/htdocs/margin/customerMargins.php b/htdocs/margin/customerMargins.php index d9cff924622..2d574ae6653 100644 --- a/htdocs/margin/customerMargins.php +++ b/htdocs/margin/customerMargins.php @@ -110,7 +110,7 @@ if ($socid > 0) { if ($soc->client) { print ''; print ''; diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index 779ee68d5a5..2a4217f5810 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -501,7 +501,7 @@ if ($id > 0 || $ref) { } else { $events = array(); $events[] = array('method' => 'getVatRates', 'url' => dol_buildpath('/core/ajax/vatrates.php', 1), 'htmlname' => 'tva_tx', 'params' => array()); - $filter = 'fournisseur=1'; + $filter = '(fournisseur:=:1)'; print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(GETPOST("id_fourn", 'alpha'), 'id_fourn', $filter, 'SelectThirdParty', 0, 0, $events); $parameters = array('filtre'=>"fournisseur=1", 'html_name'=>'id_fourn', 'selected'=>GETPOST("id_fourn"), 'showempty'=>1, 'prod_id'=>$object->id); diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 0a47a076834..172ca4a5e54 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -1944,7 +1944,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print ''; print ''; print ''; print ''; diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 7dfbf3c2385..63d44bbc284 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -615,7 +615,7 @@ if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) { print ''; } print '
'; -$filter = 'fournisseur=1'; +$filter = '(fournisseur:=:1)'; print $langs->trans('Supplier').' '.$form->select_company($fk_supplier, 'fk_supplier', $filter, 1); print '
'; diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 0a0578e5990..80c144f43ba 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1273,7 +1273,7 @@ if ($action == 'create') { print ''; } else { print ''; print ''; print '';
'.$langs->trans("Filter").'
'.$langs->trans("ThirdParty").''; -$filter = 's.client IN (1,2,3)'; +$filter = '(s.client:IN:1,2,3)'; print img_picto('', 'company', 'class="pictofixedwidth"'); print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300', ''); print '
'.$langs->trans('ThirdPartyName').''; - $filter = '(client=1 OR client=3)'; + $filter = '(client:IN:1,3)'; print img_picto('', 'company').$form->select_company($socid, 'socid', $filter, 1, 0, 0); print '
'.$langs->trans('ThirdParty').''; - $filter = 's.client IN (1,2,3)'; + $filter = '(s.client:IN:1,2,3)'; print img_picto('', 'company').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 0, 0, array(), 0, 'minwidth300'); print '
'; - $filter = 's.fournisseur=1'; + $filter = '(s.fournisseur:=:1)'; print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 0, 0, null, 0, 'minwidth300'); // reload page to retrieve customer informations if (!empty($conf->global->RELOAD_PAGE_ON_SUPPLIER_CHANGE)) { @@ -1526,7 +1526,7 @@ if ($action == 'create') { // Clone confirmation if ($action == 'clone') { - $filter = 's.fournisseur=1'; + $filter = '(s.fournisseur:=:1)'; // Create an array for form $formquestion = array( // 'text' => $langs->trans("ConfirmClone"), diff --git a/htdocs/takepos/admin/terminal.php b/htdocs/takepos/admin/terminal.php index 9fc4df7e662..6b1a5cd4a97 100644 --- a/htdocs/takepos/admin/terminal.php +++ b/htdocs/takepos/admin/terminal.php @@ -159,7 +159,7 @@ print '
'.$langs->trans("CashDeskThirdPartyForSell").''; -$filter = '(s.client IN (1, 3) AND s.status = 1)'; +$filter = '((s.client:IN:1,3) AND (s.status:=:1))'; print $form->select_company(getDolGlobalInt('CASHDESK_ID_THIRDPARTY'.$terminaltouse), 'socid', $filter, 1, 0, 0, array(), 0); print '