CVE-2023-4198 (published 2023-11-01T09:15Z)

Improper Access Control in Dolibarr ERP CRM <= v17.0.3 allows an unauthorized authenticated user to read a database table containing customer data

CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N)

Weakness information:
cwe_id: CWE-862
cwe_name: Missing Authorization
description: The product does not perform an authorization check when an actor attempts to access a resource or perform an action.
extended_description: 
            Assuming a user with a given identity, authorization is the process of determining whether that user can access a given resource, based on the user's privileges and any permissions or other access-control specifications that apply to the resource.
            When access control checks are not applied, users are able to access data or perform actions that they should not be allowed to perform. This can lead to a wide range of problems, including information exposures, denial of service, and arbitrary code execution.
         
         

Fix information:
repo_url: https://github.com/Dolibarr/dolibarr
commit_details: repo_url: https://github.com/Dolibarr/dolibarr
author: Laurent Destailleur
author_date: 2023-04-27 19:30:34+02:00
msg: Clean code
repository: repo_url: https://github.com/Dolibarr/dolibarr
repo_name: Dolibarr/dolibarr
description: Dolibarr ERP CRM is a modern software package to manage your company or foundation's activity (contacts, suppliers, invoices, orders, stocks, agenda, accounting, ...). it's an open source Web application (written in PHP) designed for businesses of any sizes, foundations and freelancers.
repo_language: PHP
owner: Dolibarr
file_changes: filename: viewcat.php
change_type: ModificationType.MODIFY
diff: @@ -590,7 +590,8 @@ if ($type == Categorie::TYPE_CUSTOMER) {
 				print '<table class="noborder centpercent">';
 				print '<tr class="liste_titre"><td>';
 				print $langs->trans("AddCustomerIntoCategory").' &nbsp;';
-				print $form->select_company('', 'elemid', 's.client IN (1,3)');
+				$filter = 's.client IN (1,3)';
+				print $form->select_company('', 'elemid', $filter);
 				print '<input type="submit" class="button buttongen" value="'.$langs->trans("ClassifyInCategory").'"></td>';
 				print '</tr>';
 				print '</table>';
@@ -670,7 +671,8 @@ if ($type == Categorie::TYPE_SUPPLIER) {
 				print '<table class="noborder centpercent">';
 				print '<tr class="liste_titre"><td>';
 				print $langs->trans("AddSupplierIntoCategory").' &nbsp;';
-				print $form->select_company('', 'elemid', 's.fournisseur = 1');
+				$filter ='s.fournisseur = 1';
+				print $form->select_company('', 'elemid', $filter);
 				print '<input type="submit" class="button buttongen" value="'.$langs->trans("ClassifyInCategory").'"></td>';
 				print '</tr>';
 				print '</table>';

programming_language: PHP
filename: card.php
change_type: ModificationType.MODIFY
diff: @@ -1810,7 +1810,8 @@ if ($action == 'create') {
 		//$warehouse_id       = $soc->warehouse_id;
 	} else {
 		print '<td class="valuefieldcreate">';
-		print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', '((s.client = 1 OR s.client = 2 OR s.client = 3) AND status=1)', 'SelectThirdParty', 1, 0, null, 0, 'minwidth300 maxwidth500 widthcentpercentminusxx');
+		$filter = '((s.client = 1 OR s.client = 2 OR s.client = 3) AND 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)) {
 			print '<script>
@@ -2133,10 +2134,11 @@ 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)';
 		$formquestion = array(
 			// 'text' => $langs->trans("ConfirmClone"),
 			// array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
-			array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', '(s.client=1 OR s.client=2 OR s.client=3)', '', 0, 0, null, 0, 'maxwidth300')),
+			array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter, '', 0, 0, null, 0, 'maxwidth300')),
 			array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans('PuttingPricesUpToDate'), 'value' => 0),
 			array('type' => 'checkbox', 'name' => 'update_desc', 'label' => $langs->trans('PuttingDescUpToDate'), 'value' => 0),
 		);

programming_language: PHP
filename: index.php
change_type: ModificationType.MODIFY
diff: @@ -263,8 +263,8 @@ print '<table class="noborder centpercent">';
 print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
 // Company
 print '<tr><td class="left">'.$langs->trans("ThirdParty").'</td><td class="left">';
-$filter = 's.client IN (1,2,3)';
 print img_picto('', 'company', 'class="pictofixedwidth"');
+$filter = 's.client IN (1,2,3)';
 print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300', '');
 print '</td></tr>';
 // ThirdParty Type

programming_language: PHP
filename: card.php
change_type: ModificationType.MODIFY
diff: @@ -1788,7 +1788,8 @@ if ($action == 'create' && $usercancreate) {
 		print '</td>';
 	} else {
 		print '<td>';
-		print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', '((s.client = 1 OR s.client = 2 OR s.client = 3) AND s.status=1)', 'SelectThirdParty', 1, 0, null, 0, 'minwidth175 maxwidth500 widthcentpercentminusxx');
+		$filter = '((s.client = 1 OR s.client = 2 OR s.client = 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)) {
 			print '<script>
@@ -2337,9 +2338,10 @@ if ($action == 'create' && $usercancreate) {
 
 		// Clone confirmation
 		if ($action == 'clone') {
+			$filter = '(s.client=1 OR s.client = 2 OR s.client=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', '(s.client=1 OR s.client = 2 OR s.client=3)', '', 0, 0, null, 0, 'maxwidth300'))
+				array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter, '', 0, 0, null, 0, 'maxwidth300'))
 			);
 			$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneOrder', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
 		}

programming_language: PHP
filename: index.php
change_type: ModificationType.MODIFY
diff: @@ -295,6 +295,7 @@ print '<table class="noborder centpercent">';
 print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
 // Company
 print '<tr><td class="left">'.$langs->trans("ThirdParty").'</td><td class="left">';
+$filter = '';
 if ($mode == 'customer') {
 	$filter = 's.client IN (1,2,3)';
 }

programming_language: PHP
filename: index.php
change_type: ModificationType.MODIFY
diff: @@ -242,9 +242,8 @@ print '<table class="border centpercent">';
 print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
 // Company
 print '<tr><td>'.$langs->trans("ThirdParty").'</td><td>';
-$filter = '';
 print img_picto('', 'company', 'class="pictofixedwidth"');
-print $form->select_company($socid, 'socid', $filter, 1, 1, 0, array(), 0, 'widthcentpercentminusx maxwidth300', '');
+print $form->select_company($socid, 'socid', '', 1, 1, 0, array(), 0, 'widthcentpercentminusx maxwidth300', '');
 print '</td></tr>';
 // User
 print '<tr><td>'.$langs->trans("User").'</td><td>';

programming_language: PHP
filename: card.php
change_type: ModificationType.MODIFY
diff: @@ -3205,7 +3205,8 @@ if ($action == 'create') {
 	} else {
 		print '<tr><td class="fieldrequired">'.$langs->trans('Customer').'</td>';
 		print '<td colspan="2">';
-		print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company($soc->id, 'socid', '((s.client = 1 OR s.client = 3) AND s.status = 1)', 'SelectThirdParty', 1, 0, null, 0, 'minwidth300 widthcentpercentminusxx maxwidth500');
+		$filter = '((s.client = 1 OR s.client = 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)) {
 			print '<script>
@@ -4319,9 +4320,10 @@ if ($action == 'create') {
 
 	// Clone confirmation
 	if ($action == 'clone') {
+		$filter = '(s.client=1 OR s.client=2 OR s.client=3)';
 		// Create an array for form
 		$formquestion = array(
-			array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company($object->socid, 'socid', '(s.client=1 OR s.client=2 OR s.client=3)', 1)),
+			array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company($object->socid, 'socid', $filter, 1)),
 			array('type' => 'date', 'name' => 'newdate', 'label' => $langs->trans("Date"), 'value' => dol_now())
 		);
 		// Request confirmation to clone

programming_language: PHP
filename: index.php
change_type: ModificationType.MODIFY
diff: @@ -265,15 +265,6 @@ complete_head_from_modules($conf, $langs, null, $head, $h, $type);
 
 print dol_get_fiche_head($head, 'byyear', $langs->trans("Statistics"), -1);
 
-// We use select_thirdparty_list instead of select_company so we can use $filter and share same code for customer and supplier.
-$filter = '';
-if ($mode == 'customer') {
-	$filter = 's.client in (1,2,3)';
-}
-if ($mode == 'supplier') {
-	$filter = 's.fournisseur = 1';
-}
-
 print '<div class="fichecenter"><div class="fichethirdleft">';
 
 
@@ -286,6 +277,13 @@ print '<table class="noborder centpercent">';
 print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
 // Company
 print '<tr><td>'.$langs->trans("ThirdParty").'</td><td>';
+$filter = '';
+if ($mode == 'customer') {
+	$filter = 's.client in (1,2,3)';
+}
+if ($mode == 'supplier') {
+	$filter = 's.fournisseur = 1';
+}
 print img_picto('', 'company', 'class="pictofixedwidth"');
 print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300');
 print '</td></tr>';

programming_language: PHP
filename: cabyprodserv.php
change_type: ModificationType.MODIFY
diff: @@ -418,12 +418,9 @@ if ($modecompta == 'CREANCES-DETTES') {
 
 	print '<td colspan="5" class="right">';
 	print '<input type="image" class="liste_titre" name="button_search" src="'.img_picto($langs->trans("Search"), 'search.png', '', '', 1).'"  value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">';
+	print '</td>';
 
-	$parameters = array();
-	$reshook = $hookmanager->executeHooks('printFieldListeTitle', $parameters);
-	print $hookmanager->resPrint;
-
-	print '</td></tr>';
+	print '</tr>';
 
 	// Array header
 	print "<tr class=\"liste_titre\">";

programming_language: PHP
filename: supplier_turnover_by_prodserv.php
change_type: ModificationType.MODIFY
diff: @@ -377,7 +377,7 @@ if ($modecompta == 'CREANCES-DETTES') {
 	print '</td></tr>';
 
 	// Array header
-	print "<tr class=\"liste_titre\">";
+	print '<tr class="liste_titre">';
 	print_liste_field_titre(
 		$langs->trans("Product"),
 		$_SERVER["PHP_SELF"],

programming_language: PHP
filename: card.php
change_type: ModificationType.MODIFY
diff: @@ -996,7 +996,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 			if (empty($conf->global->SOCIETE_DISABLE_CONTACTS)) {
 				print '<tr><td><label for="socid">'.$langs->trans("ThirdParty").'</label></td>';
 				print '<td colspan="3" class="maxwidthonsmartphone">';
-				print img_picto('', 'company').$form->select_company(GETPOST('socid', 'int') ?GETPOST('socid', 'int') : ($object->socid ? $object->socid : -1), 'socid', '', $langs->trans("SelectThirdParty"));
+				print img_picto('', 'company').$form->select_company(GETPOST('socid', 'int') ? GETPOST('socid', 'int') : ($object->socid ? $object->socid : -1), 'socid', '', $langs->trans("SelectThirdParty"));
 				print '</td>';
 				print '</tr>';
 			}

programming_language: PHP
filename: card.php
change_type: ModificationType.MODIFY
diff: @@ -1332,8 +1332,9 @@ 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)';
 			// Clone confirmation
-			$formquestion = array(array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', '(s.client=1 OR s.client=2 OR s.client=3)')));
+			$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);
 		}
 

programming_language: PHP
filename: ajaxcompanies.php
change_type: ModificationType.DELETE
diff: @@ -1,135 +0,0 @@
-<?php
-/* Copyright (C) 2006      Andre Cianfarani     <acianfa@free.fr>
- * Copyright (C) 2005-2009 Regis Houssin        <regis.houssin@inodbox.com>
- * Copyright (C) 2007-2010 Laurent Destailleur  <eldy@users.sourceforge.net>
- * Copyright (C) 2010      Cyrille de Lambert   <info@auguria.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-/**
- *       \file       htdocs/core/ajax/ajaxcompanies.php
- *       \brief      File to return Ajax response on third parties request
- */
-
-if (!defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', 1); // Disables token renewal
-if (!defined('NOREQUIREMENU'))  define('NOREQUIREMENU', '1');
-if (!defined('NOREQUIREHTML'))  define('NOREQUIREHTML', '1');
-if (!defined('NOREQUIREAJAX'))  define('NOREQUIREAJAX', '1');
-if (!defined('NOREQUIRESOC'))   define('NOREQUIRESOC', '1');
-
-// Load Dolibarr environment
-require '../../main.inc.php';
-require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
-
-$object = new Societe($db);
-
-$usesublevelpermission = '';
-
-// Security check
-restrictedArea($user, $object->module, $object, $object->table_element, $usesublevelpermission);
-
-
-/*
- * View
- */
-
-// Ajout directives pour resoudre bug IE
-//header('Cache-Control: Public, must-revalidate');
-//header('Pragma: public');
-
-//top_htmlhead("", "", 1);  // Replaced with top_httphead. An ajax page does not need html header.
-top_httphead();
-
-//print '<!-- Ajax page called with url '.dol_escape_htmltag($_SERVER["PHP_SELF"]).'?'.dol_escape_htmltag($_SERVER["QUERY_STRING"]).' -->'."\n";
-
-dol_syslog(join(',', $_GET));
-
-
-// Generation liste des societes
-if (GETPOST('newcompany') || GETPOST('socid', 'int') || GETPOST('id_fourn')) {
-	$return_arr = array();
-
-	// Define filter on text typed
-	$socid = GETPOST('newcompany');
-	if (!$socid) $socid = GETPOST('socid');
-	if (!$socid) $socid = GETPOST('id_fourn');
-
-	$sql = "SELECT s.rowid, s.nom, s.name_alias, s.code_client, s.code_fournisseur, s.address, s.zip, s.town, s.email, s.siren, s.siret, s.ape, s.idprof4, s.client, s.fournisseur, s.datec, s.logo";
-	$sql .= " , c.label as country, d.nom as departement";
-	$sql .= " FROM ".MAIN_DB_PREFIX."societe as s";
-	$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON c.rowid = s.fk_pays";
-	$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as d ON d.rowid = s.fk_departement";
-	$sql .= " WHERE s.entity IN (".getEntity('societe').")";
-	if ($socid) {
-		$sql .= " AND (";
-		// Add criteria on name/code
-		if (!empty($conf->global->COMPANY_DONOTSEARCH_ANYWHERE)) {   // Can use index
-			$sql .= "s.nom LIKE '".$db->escape($db->escapeforlike($socid))."%'";
-			$sql .= " OR s.code_client LIKE '".$db->escape($db->escapeforlike($socid))."%'";
-			$sql .= " OR s.code_fournisseur LIKE '".$db->escape($db->escapeforlike($socid))."%'";
-		} else {
-			$sql .= "s.nom LIKE '%".$db->escape($db->escapeforlike($socid))."%'";
-			$sql .= " OR s.code_client LIKE '%".$db->escape($db->escapeforlike($socid))."%'";
-			$sql .= " OR s.code_fournisseur LIKE '%".$db->escape($db->escapeforlike($socid))."%'";
-		}
-		if (!empty($conf->global->SOCIETE_ALLOW_SEARCH_ON_ROWID)) {
-			$sql .= " OR s.rowid = ".((int) $socid);
-		}
-		$sql .= ")";
-	}
-	if ($user->socid > 0) {
-		$sql .= " AND s.rowid = ".((int) $user->socid);
-	}
-	//if (GETPOST("filter")) $sql.= " AND (".GETPOST("filter", "alpha").")"; // Add other filters
-	$sql .= " ORDER BY s.nom ASC";
-
-	//dol_syslog("ajaxcompanies", LOG_DEBUG);
-	$resql = $db->query($sql);
-
-	if ($resql) {
-		while ($row = $db->fetch_array($resql)) {
-			$label = $row['nom'];
-			if ($socid) $label = $label;
-			$row_array['label'] = $label;
-			$row_array['value'] = $row['nom'];
-			$row_array['key'] = $row['rowid'];
-			$row_array['name_alias'] = $row['name_alias'];
-			$row_array['code_client'] = $row['code_client'];
-			$row_array['code_fournisseur'] = $row['code_fournisseur'];
-			$row_array['address'] = $row['address'];
-			$row_array['zip'] = $row['zip'];
-			$row_array['town'] = $row['town'];
-			$row_array['email'] = $row['email'];
-			$row_array['siren'] = $row['siren'];
-			$row_array['siret'] = $row['siret'];
-			$row_array['ape'] = $row['ape'];
-			$row_array['idprof4'] = $row['idprof4'];
-			$row_array['client'] = $row['client'];
-			$row_array['fournisseur'] = $row['fournisseur'];
-			$row_array['datec'] = $row['datec'];
-			$row_array['logo'] = $row['logo'];
-			$row_array['country'] = $row['country'];
-			$row_array['departement'] = $row['departement'];
-
-			array_push($return_arr, $row_array);
-		}
-
-		echo json_encode($return_arr);
-	} else {
-		echo json_encode(array('nom'=>'Error', 'label'=>'Error', 'key'=>'Error', 'value'=>'Error'));
-	}
-} else {
-	echo json_encode(array('nom'=>'ErrorBadParameter', 'label'=>'ErrorBadParameter', 'key'=>'ErrorBadParameter', 'value'=>'ErrorBadParameter'));
-}

programming_language: unknown
filename: html.form.class.php
change_type: ModificationType.MODIFY
diff: @@ -1290,23 +1290,23 @@ class Form
 	/**
 	 *  Output html form to select a third party
 	 *
-	 * @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)')
-	 * @param string $showempty Add an empty field (Can be '1' or text key 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 load all values and output a standard combobox (with no beautification)
-	 * @param array $events Ajax event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
-	 * @param int $limit Maximum number of elements
-	 * @param string $morecss Add more css styles to the SELECT component
-	 * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container
-	 * @param string $selected_input_value Value of preselected input text (for use with ajax)
-	 * @param int $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after)
-	 * @param array $ajaxoptions Options for ajax_autocompleter
-	 * @param bool $multiple add [] in the name of element and add 'multiple' attribut (not working with ajax_autocompleter)
-	 * @param array $excludeids Exclude IDs from the select combo
-	 * @param int $showcode Show code
-	 * @return    string                            HTML string with select box for thirdparty.
+	 * @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 	$showempty 			Add an empty field (Can be '1' or text key 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 load all values and output a standard combobox (with no beautification)
+	 * @param array 	$events 			Ajax event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
+	 * @param int 		$limit 				Maximum number of elements
+	 * @param string 	$morecss 			Add more css styles to the SELECT component
+	 * @param string 	$moreparam 			Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container
+	 * @param string 	$selected_input_value 	Value of preselected input text (for use with ajax)
+	 * @param int 		$hidelabel 			Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after)
+	 * @param array 	$ajaxoptions 		Options for ajax_autocompleter
+	 * @param bool 		$multiple 			add [] in the name of element and add 'multiple' attribut (not working with ajax_autocompleter)
+	 * @param array 	$excludeids 		Exclude IDs from the select combo
+	 * @param int 		$showcode 			Show code
+	 * @return string  		                HTML string with select box for thirdparty.
 	 */
 	public function select_company($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $limit = 0, $morecss = 'minwidth100', $moreparam = '', $selected_input_value = '', $hidelabel = 1, $ajaxoptions = array(), $multiple = false, $excludeids = array(), $showcode = 0)
 	{
@@ -1366,22 +1366,22 @@ class Form
 	 *  Output html form to select a third party.
 	 *  Note, you must use the select_company to get the component to select a third party. This function must only be called by select_company.
 	 *
-	 * @param string $selected Preselected type
-	 * @param string $htmlname Name of field in form
-	 * @param string $filter Optional filters criteras (example: 's.rowid NOT IN (x)', '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
-	 * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
-	 * @param string $filterkey Filter on key value
-	 * @param int $outputmode 0=HTML select string, 1=Array
-	 * @param int $limit Limit number of answers
-	 * @param string $morecss Add more css styles to the SELECT component
-	 * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container
-	 * @param bool $multiple add [] in the name of element and add 'multiple' attribut
-	 * @param array $excludeids Exclude IDs from the select combo
-	 * @param int $showcode Show code in list
-	 * @return    array|string            HTML string with
+	 * @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 	$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
+	 * @param array 	$events 		Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
+	 * @param string 	$filterkey 		Filter on key value
+	 * @param int 		$outputmode 	0=HTML select string, 1=Array
+	 * @param int 		$limit 			Limit number of answers
+	 * @param string 	$morecss 		Add more css styles to the SELECT component
+	 * @param string 	$moreparam 		Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container
+	 * @param bool 		$multiple 		add [] in the name of element and add 'multiple' attribut
+	 * @param array 	$excludeids 	Exclude IDs from the select combo
+	 * @param int 		$showcode 		Show code in list
+	 * @return array|string            	HTML string with
 	 */
 	public function select_thirdparty_list($selected = '', $htmlname = 'socid', $filter = '', $showempty = '', $showtype = 0, $forcecombo = 0, $events = array(), $filterkey = '', $outputmode = 0, $limit = 0, $morecss = 'minwidth100', $moreparam = '', $multiple = false, $excludeids = array(), $showcode = 0)
 	{
@@ -1403,9 +1403,13 @@ class Form
 		if (function_exists('testSqlAndScriptInject')) {
 			if (testSqlAndScriptInject($filter, 3) > 0) {
 				$filter = '';
+				return 'SQLInjectionTryDetected';
 			}
 		}
 
+		//$errormsg = '';
+		//$filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg);
+
 		// 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";
 		if (!empty($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST)) {
@@ -1470,7 +1474,7 @@ class Form
 		$sql .= $this->db->plimit($limit, 0);
 
 		// Build output string
-		dol_syslog(get_class($this) . "::select_thirdparty_list", LOG_DEBUG);
+		dol_syslog(get_class($this)."::select_thirdparty_list", LOG_DEBUG);
 		$resql = $this->db->query($sql);
 		if ($resql) {
 			if (!$forcecombo) {
@@ -6070,18 +6074,18 @@ class Form
 	/**
 	 *  Output html select to select thirdparty
 	 *
-	 * @param string $page Page
-	 * @param string $selected Id preselected
-	 * @param string $htmlname Name of HTML select
-	 * @param string $filter Optional filters criteras. Do not use a filter coming from input of users.
-	 * @param int $showempty Add an empty field
-	 * @param int $showtype Show third party type in combolist (customer, prospect or supplier)
-	 * @param int $forcecombo Force to use combo box
-	 * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
-	 * @param int $nooutput No print output. Return it only.
-	 * @param array $excludeids Exclude IDs from the select combo
-	 * @param string $textifnothirdparty Text to show if no thirdparty
-	 * @return    string                            HTML output or ''
+	 * @param string 	$page 					Page
+	 * @param string 	$selected 				Id preselected
+	 * @param string 	$htmlname 				Name of HTML select
+	 * @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 int 		$showempty 				Add an empty field
+	 * @param int 		$showtype 				Show third party type in combolist (customer, prospect or supplier)
+	 * @param int 		$forcecombo 			Force to use combo box
+	 * @param array 	$events 				Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled')))
+	 * @param int 		$nooutput 				No print output. Return it only.
+	 * @param array 	$excludeids 			Exclude IDs from the select combo
+	 * @param string 	$textifnothirdparty 	Text to show if no thirdparty
+	 * @return    string                        HTML output or ''
 	 */
 	public function form_thirdparty($page, $selected = '', $htmlname = 'socid', $filter = '', $showempty = 0, $showtype = 0, $forcecombo = 0, $events = array(), $nooutput = 0, $excludeids = array(), $textifnothirdparty = '')
 	{
@@ -7825,19 +7829,19 @@ class Form
 	 * Can use autocomplete with ajax after x key pressed or a full combo, depending on setup.
 	 * This is the generic method that will replace all specific existing methods.
 	 *
-	 * @param string $objectdesc ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]
-	 * @param string $htmlname Name of HTML select component
-	 * @param int $preselectedvalue Preselected value (ID of element)
-	 * @param string $showempty ''=empty values not allowed, 'string'=value show if we allow empty values (for example 'All', ...)
-	 * @param string $searchkey Search criteria
-	 * @param string $placeholder Place holder
-	 * @param string $morecss More CSS
-	 * @param string $moreparams More params provided to ajax call
-	 * @param int $forcecombo Force to load all values and output a standard combobox (with no beautification)
-	 * @param int $disabled 1=Html component is disabled
-	 * @param string $selected_input_value Value of preselected input text (for use with ajax)
-	 * @return    string                                Return HTML string
-	 * @see selectForFormsList() select_thirdparty_list()
+	 * @param 	string 	$objectdesc 		ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]
+	 * @param 	string 	$htmlname 			Name of HTML select component
+	 * @param 	int 	$preselectedvalue 	Preselected value (ID of element)
+	 * @param 	string 	$showempty 			''=empty values not allowed, 'string'=value show if we allow empty values (for example 'All', ...)
+	 * @param 	string 	$searchkey 			Search criteria
+	 * @param 	string 	$placeholder 		Place holder
+	 * @param 	string 	$morecss 			More CSS
+	 * @param 	string 	$moreparams 		More params provided to ajax call
+	 * @param 	int 	$forcecombo 		Force to load all values and output a standard combobox (with no beautification)
+	 * @param 	int 	$disabled 			1=Html component is disabled
+	 * @param 	string 	$selected_input_value Value of preselected input text (for use with ajax)
+	 * @return  string                      Return HTML string
+	 * @see selectForFormsList(), select_thirdparty_list()
 	 */
 	public function selectForForms($objectdesc, $htmlname, $preselectedvalue, $showempty = '', $searchkey = '', $placeholder = '', $morecss = '', $moreparams = '', $forcecombo = 0, $disabled = 0, $selected_input_value = '')
 	{

programming_language: PHP
filename: functions.lib.php
change_type: ModificationType.MODIFY
diff: @@ -11785,7 +11785,9 @@ function jsonOrUnserialize($stringtodecode)
 /**
  * forgeSQLFromUniversalSearchCriteria
  *
- * @param 	string		$filter		String with universal search string. 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'.
+ * @param 	string		$filter		String with universal search string. 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'.
  * @param	string		$error		Error message
  * @return	string					Return forged SQL string
  */

programming_language: PHP
filename: card.php
change_type: ModificationType.MODIFY
diff: @@ -440,7 +440,8 @@ if ($action == 'create') {
 		} else {
 			print '<td class="fieldrequired">'.$langs->trans('ThirdParty').'</td>';
 			print '<td>';
-			print $form->select_company($soc->id, 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300');
+			$filter = '(s.client = 1 OR s.client = 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)) {
 				print '<script type="text/javascript">

programming_language: PHP
filename: card.php
change_type: ModificationType.MODIFY
diff: @@ -1694,7 +1694,8 @@ if ($action == 'create') {
 		print $societe->getNomUrl(1, 'supplier');
 		print '<input type="hidden" name="socid" value="'.$societe->id.'">';
 	} else {
-		print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company((empty($socid) ? '' : $socid), 'socid', '(s.fournisseur=1 AND s.status=1)', 'SelectThirdParty', 1, 0, null, 0, 'minwidth175 maxwidth500 widthcentpercentminusxx');
+		$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)) {
 			print '<script>
@@ -1898,9 +1899,10 @@ if ($action == 'create') {
 
 	// Clone confirmation
 	if ($action == 'clone') {
+		$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', '(s.fournisseur=1)'))
+			array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter))
 		);
 		// Paiement incomplet. On demande si motif = escompte ou autre
 		$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneOrder', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
@@ -2034,7 +2036,8 @@ if ($action == 'create') {
 		$morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
 		$morehtmlref .= '<input type="hidden" name="action" value="set_thirdparty">';
 		$morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
-		$morehtmlref .= $form->select_company($object->thirdparty->id, 'new_socid', 's.fournisseur=1', '', 0, 0, array(), 0, 'minwidth300');
+		$filter = 's.fournisseur=1';
+		$morehtmlref .= $form->select_company($object->thirdparty->id, 'new_socid', $filter, '', 0, 0, array(), 0, 'minwidth300');
 		$morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
 		$morehtmlref .= '</form>';
 	}

programming_language: PHP
filename: card.php
change_type: ModificationType.MODIFY
diff: @@ -2199,7 +2199,8 @@ if ($action == 'create') {
 		print $societe->getNomUrl(1, 'supplier');
 		print '<input type="hidden" name="socid" value="'.$societe->id.'">';
 	} else {
-		print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(empty($societe->id) ? 0 : $societe->id, 'socid', '(s.fournisseur = 1 AND s.status = 1)', 'SelectThirdParty', 1, 0, null, 0, 'minwidth175 widthcentpercentminusxx maxwidth500');
+		$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)) {
 			print '<script type="text/javascript">

programming_language: PHP
filename: customerMargins.php
change_type: ModificationType.MODIFY
diff: @@ -110,7 +110,8 @@ if ($socid > 0) {
 	if ($soc->client) {
 		print '<tr><td class="titlefield">'.$langs->trans('ThirdPartyName').'</td>';
 		print '<td class="maxwidthonsmartphone" colspan="4">';
-		print img_picto('', 'company').$form->select_company($socid, 'socid', '(client=1 OR client=3)', 1, 0, 0);
+		$filter = '(client=1 OR client=3)';
+		print img_picto('', 'company').$form->select_company($socid, 'socid', $filter, 1, 0, 0);
 		print '</td></tr>';
 
 		$client = true;

programming_language: PHP
filename: fournisseurs.php
change_type: ModificationType.MODIFY
diff: @@ -501,7 +501,8 @@ if ($id > 0 || $ref) {
 				} else {
 					$events = array();
 					$events[] = array('method' => 'getVatRates', 'url' => dol_buildpath('/core/ajax/vatrates.php', 1), 'htmlname' => 'tva_tx', 'params' => array());
-					print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(GETPOST("id_fourn", 'alpha'), 'id_fourn', 'fournisseur=1', 'SelectThirdParty', 0, 0, $events);
+					$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);
 					$reshook = $hookmanager->executeHooks('formCreateThirdpartyOptions', $parameters, $object, $action);

programming_language: PHP
filename: price.php
change_type: ModificationType.MODIFY
diff: @@ -1944,7 +1944,8 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
 		print '<tr>';
 		print '<td class="fieldrequired">'.$langs->trans('ThirdParty').'</td>';
 		print '<td>';
-		print img_picto('', 'company').$form->select_company('', 'socid', 's.client IN (1,2,3)', 'SelectThirdParty', 0, 0, array(), 0, 'minwidth300');
+		$filter = 's.client IN (1,2,3)';
+		print img_picto('', 'company').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 0, 0, array(), 0, 'minwidth300');
 		print '</td>';
 		print '</tr>';
 

programming_language: PHP
filename: replenish.php
change_type: ModificationType.MODIFY
diff: @@ -615,7 +615,8 @@ if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE)) {
 	print '</div>';
 }
 print '<div class="inline-block valignmiddle" style="padding-right: 20px;">';
-print $langs->trans('Supplier').' '.$form->select_company($fk_supplier, 'fk_supplier', 'fournisseur=1', 1);
+$filter = 'fournisseur=1';
+print $langs->trans('Supplier').' '.$form->select_company($fk_supplier, 'fk_supplier', $filter, 1);
 print '</div>';
 
 $parameters = array();

programming_language: PHP
filename: card.php
change_type: ModificationType.MODIFY
diff: @@ -698,11 +698,11 @@ if ($action == 'create' && $user->rights->projet->creer) {
 		print $langs->trans("ThirdParty");
 		print (empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) ? '' : '</span>');
 		print '</td><td class="maxwidthonsmartphone">';
-		$filteronlist = '';
+		$filter = '';
 		if (!empty($conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST)) {
-			$filteronlist = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
+			$filter = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
 		}
-		$text = img_picto('', 'company').$form->select_company(GETPOST('socid', 'int'), 'socid', $filteronlist, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth300 widthcentpercentminusxx maxwidth500');
+		$text = img_picto('', 'company').$form->select_company(GETPOST('socid', 'int'), 'socid', $filter, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth300 widthcentpercentminusxx maxwidth500');
 		if (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) && empty($conf->dol_use_jmobile)) {
 			$texthelp = $langs->trans("IfNeedToUseOtherObjectKeepEmpty");
 			print $form->textwithtooltip($text.' '.img_help(), $texthelp, 1);
@@ -910,7 +910,7 @@ if ($action == 'create' && $user->rights->projet->creer) {
 	if ($action == 'clone') {
 		$formquestion = array(
 			'text' => $langs->trans("ConfirmClone"),
-			array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int') > 0 ?GETPOST('socid', 'int') : $object->socid, 'socid', '', "None", 0, 0, null, 0, 'minwidth200 maxwidth250')),
+			array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int') > 0 ? GETPOST('socid', 'int') : $object->socid, 'socid', '', "None", 0, 0, null, 0, 'minwidth200 maxwidth250')),
 			array('type' => 'checkbox', 'name' => 'clone_contacts', 'label' => $langs->trans("CloneContacts"), 'value' => true),
 			array('type' => 'checkbox', 'name' => 'clone_tasks', 'label' => $langs->trans("CloneTasks"), 'value' => true),
 			array('type' => 'checkbox', 'name' => 'move_date', 'label' => $langs->trans("CloneMoveDate"), 'value' => true),
@@ -1077,12 +1077,12 @@ if ($action == 'create' && $user->rights->projet->creer) {
 			print $langs->trans("ThirdParty");
 			print (empty($conf->global->PROJECT_THIRDPARTY_REQUIRED) ? '' : '</span>');
 			print '</td><td>';
-			$filteronlist = '';
+			$filter = '';
 			if (!empty($conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST)) {
-				$filteronlist = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
+				$filter = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
 			}
 			$text = img_picto('', 'company', 'class="pictofixedwidth"');
-			$text .= $form->select_company($object->thirdparty->id, 'socid', $filteronlist, 'None', 1, 0, array(), 0, 'minwidth300');
+			$text .= $form->select_company($object->thirdparty->id, 'socid', $filter, 'None', 1, 0, array(), 0, 'minwidth300');
 			if (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) && empty($conf->dol_use_jmobile)) {
 				$texthelp = $langs->trans("IfNeedToUseOtherObjectKeepEmpty");
 				print $form->textwithtooltip($text.' '.img_help(), $texthelp, 1, 0, '', '', 2);

programming_language: PHP
filename: ajaxcompanies.php
change_type: ModificationType.MODIFY
diff: @@ -20,7 +20,7 @@
 
 /**
  *       \file       htdocs/societe/ajax/ajaxcompanies.php
- *       \brief      File to return Ajax response on third parties request
+ *       \brief      File to return Ajax response on third parties request. Search is done on name|name_alias|code_client|code_fournisseur
  */
 
 if (!defined('NOTOKENRENEWAL')) {
@@ -53,107 +53,127 @@ if ($id > 0) {
 // Security check
 if ($user->socid > 0) {
 	$socid = $user->socid;
-	$object->id = $socid;
+	if ($object->socid && $socid != $object->socid) {
+		accessforbidden('Not allowed to access thirdparty id '.$id.' with an external user on id '.$socid);
+	}
 }
-restrictedArea($user, 'societe', $object->id, '&societe');
+restrictedArea($user, 'societe', $object, '&societe');
 
 
 /*
  * View
  */
 
-// Ajout directives pour resoudre bug IE
-//header('Cache-Control: Public, must-revalidate');
-//header('Pragma: public');
-
 //top_htmlhead("", "", 1);  // Replaced with top_httphead. An ajax page does not need html header.
-top_httphead();
+top_httphead('application/json');
 
 //print '<!-- Ajax page called with url '.dol_escape_htmltag($_SERVER["PHP_SELF"]).'?'.dol_escape_htmltag($_SERVER["QUERY_STRING"]).' -->'."\n";
 
 
-// Generate list of companies
-if (GETPOST('newcompany') || GETPOST('socid', 'int') || GETPOST('id_fourn', 'int')) {
-	$return_arr = array();
+$return_arr = array();
 
-	// Define filter on text typed
-	$socid = GETPOST('newcompany');
-	if (!$socid) {
-		$socid = GETPOST('socid', 'int');
-	}
-	if (!$socid) {
-		$socid = GETPOST('id_fourn', 'int');
-	}
+// Define filter on text typed
+$socid = GETPOST('newcompany');
+if (!$socid) {
+	$socid = GETPOST('socid', 'int');
+}
+if (!$socid) {
+	$socid = GETPOST('id_fourn', 'int');
+}
 
-	$sql = "SELECT s.rowid, s.nom";
-	if (!empty($conf->global->SOCIETE_ADD_REF_IN_LIST)) {
-		$sql .= ", s.client, s.fournisseur, s.code_client, s.code_fournisseur";
-	}
-	if (!empty($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST)) {
-		$sql .= ", s.address, s.zip, s.town";
-		$sql .= ", dictp.code as country_code";
-	}
-	$sql .= " FROM ".MAIN_DB_PREFIX."societe as s";
-	if (!empty($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST)) {
-		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as dictp ON dictp.rowid = s.fk_pays";
+// Generate list of companies
+if (! $socid) {
+	echo json_encode(array('nom'=>'ErrorBadParameter', 'label'=>'ErrorBadParameter', 'key'=>'ErrorBadParameter', 'value'=>'ErrorBadParameter'));
+	exit;
+}
+
+$sql = "SELECT s.rowid, s.nom, s.name_alias, s.code_client, s.code_fournisseur, s.address, s.zip, s.town, s.email, s.siren, s.siret, s.ape, s.idprof4, s.idprof5, s.idprof6, s.client, s.fournisseur, s.datec, s.logo";
+if (!empty($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST)) {
+	$sql .= ", dictp.code as country_code";
+}
+$sql .= " FROM ".MAIN_DB_PREFIX."societe as s";
+if (!empty($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST)) {
+	$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as dictp ON dictp.rowid = s.fk_pays";
+}
+$sql .= " WHERE s.entity IN (".getEntity('societe').")";
+if ($socid) {
+	$sql .= " AND (";
+	// Add criteria on name/code
+	if (!empty($conf->global->COMPANY_DONOTSEARCH_ANYWHERE)) {   // Can use index
+		$sql .= "s.nom LIKE '".$db->escape($db->escapeforlike($socid))."%'";
+		$sql .= " OR s.name_alias LIKE '".$db->escape($db->escapeforlike($socid))."%'";
+		$sql .= " OR s.code_client LIKE '".$db->escape($db->escapeforlike($socid))."%'";
+		$sql .= " OR s.code_fournisseur LIKE '".$db->escape($db->escapeforlike($socid))."%'";
+	} else {
+		$sql .= "s.nom LIKE '%".$db->escape($db->escapeforlike($socid))."%'";
+		$sql .= " OR s.name_alias LIKE '%".$db->escape($db->escapeforlike($socid))."%'";
+		$sql .= " OR s.code_client LIKE '%".$db->escape($db->escapeforlike($socid))."%'";
+		$sql .= " OR s.code_fournisseur LIKE '%".$db->escape($db->escapeforlike($socid))."%'";
 	}
-	$sql .= " WHERE s.entity IN (".getEntity('societe').")";
-	if ($socid) {
-		$sql .= " AND (";
-		// Add criteria on name/code
-		if (!empty($conf->global->COMPANY_DONOTSEARCH_ANYWHERE)) {   // Can use index
-			$sql .= "nom LIKE '".$db->escape($socid)."%'";
-			$sql .= " OR code_client LIKE '".$db->escape($socid)."%'";
-			$sql .= " OR code_fournisseur LIKE '".$db->escape($socid)."%'";
-		} else {
-			$sql .= "nom LIKE '%".$db->escape($socid)."%'";
-			$sql .= " OR code_client LIKE '%".$db->escape($socid)."%'";
-			$sql .= " OR code_fournisseur LIKE '%".$db->escape($socid)."%'";
-		}
-		if (!empty($conf->global->SOCIETE_ALLOW_SEARCH_ON_ROWID)) {
-			$sql .= " OR rowid = ".((int) $socid);
-		}
-		$sql .= ")";
+	if (!empty($conf->global->SOCIETE_ALLOW_SEARCH_ON_ROWID)) {
+		$sql .= " OR s.rowid = ".((int) $socid);
 	}
-	//if (GETPOST("filter")) $sql.= " AND (".GETPOST("filter", "alpha").")"; // Add other filters
-	$sql .= " ORDER BY nom ASC";
-
-	//dol_syslog("ajaxcompanies", LOG_DEBUG);
-	$resql = $db->query($sql);
-	if ($resql) {
-		while ($row = $db->fetch_array($resql)) {
-			$label = '';
-			if (!empty($conf->global->SOCIETE_ADD_REF_IN_LIST)) {
-				if (($row['client']) && (!empty($row['code_client']))) {
-					$label = $row['code_client'].' - ';
-				}
-				if (($row['fournisseur']) && (!empty($row['code_fournisseur']))) {
-					$label .= $row['code_fournisseur'].' - ';
-				}
+	$sql .= ")";
+}
+// Protection for external user access
+if ($user->socid > 0) {
+	$sql .= " AND s.rowid = ".((int) $user->socid);
+}
+//if (GETPOST("filter")) $sql.= " AND (".GETPOST("filter", "alpha").")"; // Add other filters
+$sql .= " ORDER BY s.nom ASC";
+
+//dol_syslog("ajaxcompanies", LOG_DEBUG);
+$resql = $db->query($sql);
+if ($resql) {
+	while ($row = $db->fetch_array($resql)) {
+		$label = '';
+		if (!empty($conf->global->SOCIETE_ADD_REF_IN_LIST)) {
+			if (($row['client']) && (!empty($row['code_client']))) {
+				$label = $row['code_client'].' - ';
 			}
+			if (($row['fournisseur']) && (!empty($row['code_fournisseur']))) {
+				$label .= $row['code_fournisseur'].' - ';
+			}
+		}
 
-			$label .= $row['nom'];
+		$label .= $row['nom'];
 
-			if (!empty($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST)) {
-				$label .= ($row['address'] ? ' - '.$row['address'] : '').($row['zip'] ? ' - '.$row['zip'] : '').($row['town'] ? ' '.$row['town'] : '');
-				if (!empty($row['country_code'])) {
-					$label .= ', '.$langs->trans('Country'.$row['country_code']);
-				}
+		if (!empty($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST)) {
+			$label .= ($row['address'] ? ' - '.$row['address'] : '').($row['zip'] ? ' - '.$row['zip'] : '').($row['town'] ? ' '.$row['town'] : '');
+			if (!empty($row['country_code'])) {
+				$label .= ', '.$langs->trans('Country'.$row['country_code']);
 			}
-			if ($socid) {
-				$label = preg_replace('/('.preg_quote($socid, '/').')/i', '<strong>$1</strong>', $label, 1);
-			}
-			$row_array['label'] = $label;
-			$row_array['value'] = $row['nom'];
-			$row_array['key'] = $row['rowid'];
-
-			array_push($return_arr, $row_array);
 		}
-
-		echo json_encode($return_arr);
-	} else {
-		echo json_encode(array('nom'=>'Error', 'label'=>'Error', 'key'=>'Error', 'value'=>'Error'));
+		if ($socid) {
+			$label = preg_replace('/('.preg_quote($socid, '/').')/i', '<strong>$1</strong>', $label, 1);
+		}
+		$row_array['label'] = $label;
+
+		$row_array['value'] = $row['nom'];
+		$row_array['key'] = $row['rowid'];
+
+		$row_array['name_alias'] = $row['name_alias'];
+		$row_array['client'] = $row['client'];
+		$row_array['fournisseur'] = $row['fournisseur'];
+		$row_array['code_client'] = $row['code_client'];
+		$row_array['code_fournisseur'] = $row['code_fournisseur'];
+		$row_array['address'] = $row['address'];
+		$row_array['zip'] = $row['zip'];
+		$row_array['town'] = $row['town'];
+		$row_array['email'] = $row['email'];
+		$row_array['siren'] = $row['siren'];
+		$row_array['siret'] = $row['siret'];
+		$row_array['ape'] = $row['ape'];
+		$row_array['idprof4'] = $row['idprof4'];
+		$row_array['idprof5'] = $row['idprof5'];
+		$row_array['idprof6'] = $row['idprof6'];
+		$row_array['datec'] = $row['datec'];
+		$row_array['logo'] = $row['logo'];
+
+		array_push($return_arr, $row_array);
 	}
+
+	echo json_encode($return_arr);
 } else {
-	echo json_encode(array('nom'=>'ErrorBadParameter', 'label'=>'ErrorBadParameter', 'key'=>'ErrorBadParameter', 'value'=>'ErrorBadParameter'));
+	echo json_encode(array('nom'=>'Error', 'label'=>'Error', 'key'=>'Error', 'value'=>'Error'));
 }

programming_language: PHP
filename: company.php
change_type: ModificationType.MODIFY
diff: @@ -19,7 +19,8 @@
 
 /**
  *       \file       htdocs/societe/ajax/company.php
- *       \brief      File to return Ajax response on thirdparty list request
+ *       \brief      File to return Ajax response on thirdparty list request. Used by the combo list of thirdparties.
+ *       			 Search done on name, name_alias, barcode, tva_intra, ...
  */
 
 if (!defined('NOTOKENRENEWAL')) {
@@ -48,8 +49,8 @@ $outjson = (GETPOST('outjson', 'int') ? GETPOST('outjson', 'int') : 0);
 $action = GETPOST('action', 'aZ09');
 $id = GETPOST('id', 'int');
 $excludeids = GETPOST('excludeids', 'intcomma');
-$showtype = GETPOSTINT('showtype');
-$showcode = GETPOSTINT('showcode');
+$showtype = GETPOSTINT('showtype', 'alpha');
+$showcode = GETPOSTINT('showcode', 'alpha');
 
 $object = new Societe($db);
 if ($id > 0) {
@@ -69,6 +70,8 @@ restrictedArea($user, 'societe', $object->id, '&societe');
  * View
  */
 
+top_httphead('application/json');
+
 //print '<!-- Ajax page called with url '.dol_escape_htmltag($_SERVER["PHP_SELF"]).'?'.dol_escape_htmltag($_SERVER["QUERY_STRING"]).' -->'."\n";
 //print_r($_GET);
 
@@ -90,10 +93,6 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) {
 } else {
 	require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
 
-	$langs->load("companies");
-
-	top_httphead();
-
 	if (empty($htmlname)) {
 		return;
 	}
@@ -124,9 +123,9 @@ if (!empty($action) && $action == 'fetch' && !empty($id)) {
 
 	$arrayresult = $form->select_thirdparty_list(0, $htmlname, $filter, 1, $showtype, 0, null, $searchkey, $outjson, 0, 'minwidth100', '', false, $excludeids, $showcode);
 
-	$db->close();
-
 	if ($outjson) {
 		print json_encode($arrayresult);
 	}
 }
+
+$db->close();

programming_language: PHP
filename: card.php
change_type: ModificationType.MODIFY
diff: @@ -1368,10 +1368,9 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
 		print '</td><td'.(empty($conf->global->SOCIETE_USEPREFIX) ? ' colspan="3"' : '').'>';
 
 		print '<input type="text" class="minwidth300" maxlength="128" name="name" id="name" value="'.dol_escape_htmltag($object->name).'" autofocus="autofocus">';
-		print $form->widgetForTranslation("name", $object, $permissiontoadd, 'string', 'alpahnohtml', 'minwidth300');
-		/* Disabled. Must be implenteted by keeping the input text but calling ajax on a keydown of the input and output
-		   data of duplicate into a div under the input. We need to keep the widgetForTranslation also for some countries.
-		 */
+		print $form->widgetForTranslation("name", $object, $permissiontoadd, 'string', 'alpahnohtml', 'minwidth300');	// For some countries that need the company name in 2 languages
+		// This implementation of the feature to search already existing company has been disabled. It must be implemented by keeping the "input text" and we must call the search ajax societe/ajax/ajaxcompanies.php
+		// on a keydown of the input. We should show data about a duplicate found if we found less than 5 answers into a div under the input.
 		/*
 		print '<select class="name" name="name" id="name" style="min-width:500px"></select>';
 		print "\n".'<script type="text/javascript">';

programming_language: PHP
filename: card.php
change_type: ModificationType.MODIFY
diff: @@ -1273,7 +1273,8 @@ if ($action == 'create') {
 		print '</td>';
 	} else {
 		print '<td colspan="2">';
-		print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', 's.fournisseur=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300');
+		$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)) {
 			print '<script>
@@ -1525,6 +1526,7 @@ if ($action == 'create') {
 
 	// Clone confirmation
 	if ($action == 'clone') {
+		$filter = 's.fournisseur=1';
 		// Create an array for form
 		$formquestion = array(
 			// 'text' => $langs->trans("ConfirmClone"),
@@ -1535,7 +1537,7 @@ if ($action == 'create') {
 				'type' => 'other',
 				'name' => 'socid',
 				'label' => $langs->trans("SelectThirdParty"),
-				'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', 's.fournisseur=1'))
+				'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter))
 			);
 		// Paiement incomplet. On demande si motif = escompte ou autre
 		$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);

programming_language: PHP
filename: terminal.php
change_type: ModificationType.MODIFY
diff: @@ -159,7 +159,8 @@ print '</td></tr>';
 
 print '<tr class="oddeven"><td class="fieldrequired">'.$langs->trans("CashDeskThirdPartyForSell").'</td>';
 print '<td>';
-print $form->select_company(getDolGlobalInt('CASHDESK_ID_THIRDPARTY'.$terminaltouse), 'socid', '(s.client IN (1, 3) AND s.status = 1)', 1, 0, 0, array(), 0);
+$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 '</td></tr>';
 
 $atleastonefound = 0;

programming_language: PHP