CVE-2023-4198 (PHP, published 2023-11-01T09:15Z)
Description: value: Improper Access Control in Dolibarr ERP CRM <= v17.0.3 allows an unauthorized authenticated user to read a database table containing customer data
Severity: nan (CVSS v3 base score: 6.5)
Weakness: CWE-862 \u2014 Missing Authorization
The product does not perform an authorization check when an actor attempts to access a resource or perform an action.
Repository: https://github.com/Dolibarr/dolibarr
Files changed:
htdocs/categories/viewcat.php
htdocs/comm/propal/card.php
htdocs/comm/propal/stats/index.php
htdocs/commande/card.php
htdocs/commande/stats/index.php
htdocs/compta/deplacement/stats/index.php
htdocs/compta/facture/card.php
htdocs/compta/facture/stats/index.php
htdocs/compta/stats/cabyprodserv.php
htdocs/compta/stats/supplier_turnover_by_prodserv.php
htdocs/contact/card.php
htdocs/contrat/card.php
htdocs/core/class/html.form.class.php
htdocs/core/lib/functions.lib.php
htdocs/don/card.php
htdocs/fourn/commande/card.php
htdocs/fourn/facture/card.php
htdocs/margin/customerMargins.php
htdocs/product/fournisseurs.php
htdocs/product/price.php
htdocs/product/stock/replenish.php
htdocs/projet/card.php
htdocs/societe/ajax/ajaxcompanies.php
htdocs/societe/ajax/company.php
htdocs/societe/card.php
htdocs/supplier_proposal/card.php
htdocs/takepos/admin/terminal.php
Commit message: Clean code

Vulnerable code:
				print $form->select_company('', 'elemid', 's.client IN (1,3)');
				print $form->select_company('', 'elemid', 's.fournisseur = 1');
		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');
			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')),
$filter = 's.client IN (1,2,3)';
		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');
				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'))
$filter = '';
print $form->select_company($socid, 'socid', $filter, 1, 1, 0, array(), 0, 'widthcentpercentminusx maxwidth300', '');
		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');
			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)),
// 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';
}

	$parameters = array();
	$reshook = $hookmanager->executeHooks('printFieldListeTitle', $parameters);
	print $hookmanager->resPrint;

	print '</td></tr>';
	print "<tr class=\"liste_titre\">";
				print img_picto('', 'company').$form->select_company(GETPOST('socid', 'int') ?GETPOST('socid', 'int') : ($object->socid ? $object->socid : -1), 'socid', '', $langs->trans("SelectThirdParty"));
			$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)')));
<?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'));
}
	 * @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 (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
		dol_syslog(get_class($this) . "::select_thirdparty_list", LOG_DEBUG);
	 * @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 $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		$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'.
			print $form->select_company($soc->id, 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300');
		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');
			array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', '(s.fournisseur=1)'))
		$morehtmlref .= $form->select_company($object->thirdparty->id, 'new_socid', 's.fournisseur=1', '', 0, 0, array(), 0, 'minwidth300');
		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');
		print img_picto('', 'company').$form->select_company($socid, 'socid', '(client=1 OR client=3)', 1, 0, 0);
					print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(GETPOST("id_fourn", 'alpha'), 'id_fourn', 'fournisseur=1', 'SelectThirdParty', 0, 0, $events);
		print img_picto('', 'company').$form->select_company('', 'socid', 's.client IN (1,2,3)', 'SelectThirdParty', 0, 0, array(), 0, 'minwidth300');
print $langs->trans('Supplier').' '.$form->select_company($fk_supplier, 'fk_supplier', 'fournisseur=1', 1);
		$filteronlist = '';
			$filteronlist = $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');
			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')),
			$filteronlist = '';
				$filteronlist = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
			$text .= $form->select_company($object->thirdparty->id, 'socid', $filteronlist, 'None', 1, 0, array(), 0, 'minwidth300');
 *       \brief      File to return Ajax response on third parties request
	$object->id = $socid;
restrictedArea($user, 'societe', $object->id, '&societe');
// Ajout directives pour resoudre bug IE
//header('Cache-Control: Public, must-revalidate');
//header('Pragma: public');

top_httphead();
// Generate list of companies
if (GETPOST('newcompany') || GETPOST('socid', 'int') || GETPOST('id_fourn', 'int')) {
	$return_arr = array();
	// 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";
	$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 (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'].' - ';
				}
			$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 ($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'));
	echo json_encode(array('nom'=>'ErrorBadParameter', 'label'=>'ErrorBadParameter', 'key'=>'ErrorBadParameter', 'value'=>'ErrorBadParameter'));
 *       \brief      File to return Ajax response on thirdparty list request
$showtype = GETPOSTINT('showtype');
$showcode = GETPOSTINT('showcode');
	$langs->load("companies");

	top_httphead();

	$db->close();

		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 img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', 's.fournisseur=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300');
				'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', 's.fournisseur=1'))
print $form->select_company(getDolGlobalInt('CASHDESK_ID_THIRDPARTY'.$terminaltouse), 'socid', '(s.client IN (1, 3) AND s.status = 1)', 1, 0, 0, array(), 0);

Fixed code:
				$filter = 's.client IN (1,3)';
				print $form->select_company('', 'elemid', $filter);
				$filter ='s.fournisseur = 1';
				print $form->select_company('', 'elemid', $filter);
		$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');
		$filter = '(s.client=1 OR s.client=2 OR s.client=3)';
			array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter, '', 0, 0, null, 0, 'maxwidth300')),
$filter = 's.client IN (1,2,3)';
		$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');
			$filter = '(s.client=1 OR s.client = 2 OR s.client=3)';
				array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter, '', 0, 0, null, 0, 'maxwidth300'))
$filter = '';
print $form->select_company($socid, 'socid', '', 1, 1, 0, array(), 0, 'widthcentpercentminusx maxwidth300', '');
		$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');
		$filter = '(s.client=1 OR s.client=2 OR s.client=3)';
			array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company($object->socid, 'socid', $filter, 1)),
$filter = '';
if ($mode == 'customer') {
	$filter = 's.client in (1,2,3)';
}
if ($mode == 'supplier') {
	$filter = 's.fournisseur = 1';
}
	print '</td>';
	print '</tr>';
	print '<tr class="liste_titre">';
				print img_picto('', 'company').$form->select_company(GETPOST('socid', 'int') ? GETPOST('socid', 'int') : ($object->socid ? $object->socid : -1), 'socid', '', $langs->trans("SelectThirdParty"));
			$filter = '(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)));
	 * @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.
	 * @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
				return 'SQLInjectionTryDetected';
		//$errormsg = '';
		//$filter = forgeSQLFromUniversalSearchCriteria($filter, $errormsg);

		dol_syslog(get_class($this)."::select_thirdparty_list", LOG_DEBUG);
	 * @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 ''
	 * @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		$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'.
			$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');
		$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');
		$filter = '(s.fournisseur=1)';
			array('type' => 'other', 'name' => 'socid', 'label' => $langs->trans("SelectThirdParty"), 'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter))
		$filter = 's.fournisseur=1';
		$morehtmlref .= $form->select_company($object->thirdparty->id, 'new_socid', $filter, '', 0, 0, array(), 0, 'minwidth300');
		$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');
		$filter = '(client=1 OR client=3)';
		print img_picto('', 'company').$form->select_company($socid, 'socid', $filter, 1, 0, 0);
					$filter = 'fournisseur=1';
					print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(GETPOST("id_fourn", 'alpha'), 'id_fourn', $filter, 'SelectThirdParty', 0, 0, $events);
		$filter = 's.client IN (1,2,3)';
		print img_picto('', 'company').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 0, 0, array(), 0, 'minwidth300');
$filter = 'fournisseur=1';
print $langs->trans('Supplier').' '.$form->select_company($fk_supplier, 'fk_supplier', $filter, 1);
		$filter = '';
			$filter = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
		$text = img_picto('', 'company').$form->select_company(GETPOST('socid', 'int'), 'socid', $filter, 'SelectThirdParty', 1, 0, array(), 0, 'minwidth300 widthcentpercentminusxx maxwidth500');
			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')),
			$filter = '';
				$filter = $conf->global->PROJECT_FILTER_FOR_THIRDPARTY_LIST;
			$text .= $form->select_company($object->thirdparty->id, 'socid', $filter, 'None', 1, 0, array(), 0, 'minwidth300');
 *       \brief      File to return Ajax response on third parties request. Search is done on name|name_alias|code_client|code_fournisseur
	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, '&societe');
top_httphead('application/json');
$return_arr = array();
// Define filter on text typed
$socid = GETPOST('newcompany');
if (!$socid) {
	$socid = GETPOST('socid', 'int');
}
if (!$socid) {
	$socid = GETPOST('id_fourn', 'int');
}
// 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))."%'";
	if (!empty($conf->global->SOCIETE_ALLOW_SEARCH_ON_ROWID)) {
		$sql .= " OR s.rowid = ".((int) $socid);
	$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'];
		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'];

		$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);
	echo json_encode(array('nom'=>'Error', 'label'=>'Error', 'key'=>'Error', 'value'=>'Error'));
 *       \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, ...
$showtype = GETPOSTINT('showtype', 'alpha');
$showcode = GETPOSTINT('showcode', 'alpha');
top_httphead('application/json');


$db->close();
		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.
		$filter = 's.fournisseur=1';
		print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 0, 0, null, 0, 'minwidth300');
		$filter = 's.fournisseur=1';
				'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', $filter))
$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);