From 1351a43a30c2f34ddab06f77b0575be750c997b1 Mon Sep 17 00:00:00 2001
From: Laurent Destailleur <eldy@destailleur.fr>
Date: Mon, 18 Dec 2017 15:39:40 +0100
Subject: [PATCH] FIX Maxi debug of permission for users external or restricted
 to sales representatives

---
 htdocs/adherents/document.php                 |  4 --
 htdocs/comm/action/class/actioncomm.class.php | 11 ++-
 htdocs/comm/propal/class/propal.class.php     | 11 ++-
 htdocs/commande/card.php                      |  1 -
 htdocs/commande/class/commande.class.php      | 11 ++-
 htdocs/compta/facture/class/facture.class.php | 11 ++-
 htdocs/contrat/class/contrat.class.php        | 11 ++-
 htdocs/core/class/commonobject.class.php      | 34 ++++++---
 htdocs/core/class/html.form.class.php         |  6 +-
 htdocs/core/lib/security.lib.php              | 70 +++++++++----------
 htdocs/don/card.php                           |  6 +-
 .../class/fournisseur.commande.class.php      | 11 ++-
 .../fourn/class/fournisseur.facture.class.php | 11 ++-
 htdocs/projet/ganttview.php                   |  4 +-
 htdocs/societe/class/societe.class.php        |  5 ++
 .../class/supplier_proposal.class.php         | 11 ++-
 16 files changed, 156 insertions(+), 62 deletions(-)

diff --git a/htdocs/adherents/document.php b/htdocs/adherents/document.php
index 59328f24fd5..54e975c2f8c 100644
--- a/htdocs/adherents/document.php
+++ b/htdocs/adherents/document.php
@@ -42,10 +42,6 @@ $action=GETPOST('action','alpha');
 $confirm=GETPOST('confirm','alpha');
 
 // Security check
-if ($user->societe_id > 0)
-{
-	$id = $user->societe_id;
-}
 $result=restrictedArea($user,'adherent',$id);
 
 // Get parameters
diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php
index 39e2f0a98f7..985a50df9ec 100644
--- a/htdocs/comm/action/class/actioncomm.class.php
+++ b/htdocs/comm/action/class/actioncomm.class.php
@@ -36,8 +36,17 @@ class ActionComm extends CommonObject
     public $element='action';
     public $table_element = 'actioncomm';
     public $table_rowid = 'id';
-    public $ismultientitymanaged = 1;	// 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
     public $picto='action';
+    /**
+     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
+     * @var int
+     */
+    public $ismultientitymanaged = 1;
+    /**
+     * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user, 2=Same than 1 but accept record if fksoc is empty
+     * @var integer
+     */
+    public $restrictiononfksoc = 2;
 
     /**
      * Id of the event
diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php
index 1b6a98dbdb9..84ad5707fe2 100644
--- a/htdocs/comm/propal/class/propal.class.php
+++ b/htdocs/comm/propal/class/propal.class.php
@@ -48,8 +48,17 @@ class Propal extends CommonObject
 	public $table_element='propal';
 	public $table_element_line='propaldet';
 	public $fk_element='fk_propal';
-	public $ismultientitymanaged = 1;	// 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
 	public $picto='propal';
+	/**
+	 * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
+	 * @var int
+	 */
+	public $ismultientitymanaged = 1;
+	/**
+	 * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
+	 * @var integer
+	 */
+	public $restrictiononfksoc = 1;
 
 	/**
 	 * {@inheritdoc}
diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php
index 9474d54b925..63ca86191d3 100644
--- a/htdocs/commande/card.php
+++ b/htdocs/commande/card.php
@@ -1288,7 +1288,6 @@ if (empty($reshook))
 	include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
 
 
-
 	if (! $error && ! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $user->rights->commande->creer)
 	{
 		if ($action == 'addcontact')
diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php
index 6ebe94c327b..35ead22c32f 100644
--- a/htdocs/commande/class/commande.class.php
+++ b/htdocs/commande/class/commande.class.php
@@ -46,8 +46,17 @@ class Commande extends CommonOrder
     public $table_element_line = 'commandedet';
     public $class_element_line = 'OrderLine';
     public $fk_element = 'fk_commande';
-    public $ismultientitymanaged = 1;	// 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
     public $picto = 'order';
+    /**
+     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
+     * @var int
+     */
+    public $ismultientitymanaged = 1;
+    /**
+     * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
+     * @var integer
+     */
+    public $restrictiononfksoc = 1;
 
     /**
      * {@inheritdoc}
diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php
index ac068fb5f6e..0d96236a6ab 100644
--- a/htdocs/compta/facture/class/facture.class.php
+++ b/htdocs/compta/facture/class/facture.class.php
@@ -52,8 +52,17 @@ class Facture extends CommonInvoice
 	public $table_element='facture';
 	public $table_element_line = 'facturedet';
 	public $fk_element = 'fk_facture';
-	public $ismultientitymanaged = 1;	// 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
 	public $picto='bill';
+	/**
+	 * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
+	 * @var int
+	 */
+	public $ismultientitymanaged = 1;
+	/**
+	 * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
+	 * @var integer
+	 */
+	public $restrictiononfksoc = 1;
 
 	/**
 	 * {@inheritdoc}
diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php
index 48768af5a7a..1b52ac278ec 100644
--- a/htdocs/contrat/class/contrat.class.php
+++ b/htdocs/contrat/class/contrat.class.php
@@ -44,8 +44,17 @@ class Contrat extends CommonObject
 	public $table_element='contrat';
 	public $table_element_line='contratdet';
 	public $fk_element='fk_contrat';
-	public $ismultientitymanaged = 1;	// 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
     public $picto='contract';
+    /**
+     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
+     * @var int
+     */
+    public $ismultientitymanaged = 1;
+    /**
+     * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
+     * @var integer
+     */
+    public $restrictiononfksoc = 1;
 
 	/**
 	 * {@inheritdoc}
diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index 37f87ca1da2..25d9f67a219 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -1414,6 +1414,10 @@ abstract class CommonObject
 		}
 		if ($fieldid == 'none') return 1;
 
+		// Security on socid
+		$socid = 0;
+		if ($user->societe_id > 0) $socid = $user->societe_id;
+
 		// this->ismultientitymanaged contains
 		// 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
 		$alias = 's';
@@ -1422,18 +1426,25 @@ abstract class CommonObject
 		$sql = "SELECT MAX(te.".$fieldid.")";
 		$sql.= " FROM ".(empty($nodbprefix)?MAIN_DB_PREFIX:'').$this->table_element." as te";
 		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2) $sql.= ", ".MAIN_DB_PREFIX."societe as s";	// If we need to link to societe to limit select to entity
-		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2 && !$user->rights->societe->client->voir) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ".$alias.".rowid = sc.fk_soc";
+		else if ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe as s";	// If we need to link to societe to limit select to socid
+		else if ($this->restrictiononfksoc == 2 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON te.fk_soc = s.rowid";	// If we need to link to societe to limit select to socid
+		if ($this->restrictiononfksoc && !$user->rights->societe->client->voir && !$socid)  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ".$alias.".rowid = sc.fk_soc";
 		$sql.= " WHERE te.".$fieldid." < '".$this->db->escape($this->ref)."'";  // ->ref must always be defined (set to id if field does not exists)
-		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2 && !$user->rights->societe->client->voir) $sql.= " AND sc.fk_user = " .$user->id;
+		if ($this->restrictiononfksoc == 1 && !$user->rights->societe->client->voir && !$socid) $sql.= " AND sc.fk_user = " .$user->id;
+		if ($this->restrictiononfksoc == 2 && !$user->rights->societe->client->voir && !$socid) $sql.= " AND (sc.fk_user = " .$user->id.' OR te.fk_soc IS NULL)';
 		if (! empty($filter))
 		{
 			if (! preg_match('/^\s*AND/i', $filter)) $sql.=" AND ";   // For backward compatibility
 			$sql.=$filter;
 		}
 		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2) $sql.= ' AND te.fk_soc = s.rowid';			// If we need to link to societe to limit select to entity
-		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql.= ' AND te.entity IN ('.getEntity($this->element, 1).')';
+		else if ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= ' AND te.fk_soc = s.rowid';			// If we need to link to societe to limit select to socid
+		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql.= ' AND te.entity IN ('.getEntity($this->element).')';
+		if ($this->restrictiononfksoc == 1 && $socid && $this->element != 'societe') $sql.= ' AND te.fk_soc = ' . $socid;
+		if ($this->restrictiononfksoc == 2 && $socid && $this->element != 'societe') $sql.= ' AND (te.fk_soc = ' . $socid.' OR te.fk_soc IS NULL)';
+		if ($this->restrictiononfksoc && $socid && $this->element == 'societe') $sql.= ' AND te.rowid = ' . $socid;
+		//print 'socid='.$socid.' restrictiononfksoc='.$this->restrictiononfksoc.' ismultientitymanaged = '.$this->ismultientitymanaged.' filter = '.$filter.' -> '.$sql."<br>";
 
-		//print 'filter = '.$filter.' -> '.$sql."<br>";
 		$result = $this->db->query($sql);
 		if (! $result)
 		{
@@ -1447,19 +1458,26 @@ abstract class CommonObject
 		$sql = "SELECT MIN(te.".$fieldid.")";
 		$sql.= " FROM ".(empty($nodbprefix)?MAIN_DB_PREFIX:'').$this->table_element." as te";
 		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2) $sql.= ", ".MAIN_DB_PREFIX."societe as s";	// If we need to link to societe to limit select to entity
-		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2 && !$user->rights->societe->client->voir) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ".$alias.".rowid = sc.fk_soc";
+		else if ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe as s";	// If we need to link to societe to limit select to socid
+		else if ($this->restrictiononfksoc == 2 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON te.fk_soc = s.rowid";	// If we need to link to societe to limit select to socid
+		if ($this->restrictiononfksoc && !$user->rights->societe->client->voir && !$socid) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ".$alias.".rowid = sc.fk_soc";
 		$sql.= " WHERE te.".$fieldid." > '".$this->db->escape($this->ref)."'";  // ->ref must always be defined (set to id if field does not exists)
-		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2 && !$user->rights->societe->client->voir) $sql.= " AND sc.fk_user = " .$user->id;
+		if ($this->restrictiononfksoc == 1 && !$user->rights->societe->client->voir && !$socid) $sql.= " AND sc.fk_user = " .$user->id;
+		if ($this->restrictiononfksoc == 2 && !$user->rights->societe->client->voir && !$socid) $sql.= " AND (sc.fk_user = " .$user->id.' OR te.fk_soc IS NULL)';
 		if (! empty($filter))
 		{
 			if (! preg_match('/^\s*AND/i', $filter)) $sql.=" AND ";   // For backward compatibility
 			$sql.=$filter;
 		}
 		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2) $sql.= ' AND te.fk_soc = s.rowid';			// If we need to link to societe to limit select to entity
-		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql.= ' AND te.entity IN ('.getEntity($this->element, 1).')';
+		else if ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= ' AND te.fk_soc = s.rowid';			// If we need to link to societe to limit select to socid
+		if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql.= ' AND te.entity IN ('.getEntity($this->element).')';
+		if ($this->restrictiononfksoc == 1 && $socid && $this->element != 'societe') $sql.= ' AND te.fk_soc = ' . $socid;
+		if ($this->restrictiononfksoc == 2 && $socid && $this->element != 'societe') $sql.= ' AND (te.fk_soc = ' . $socid.' OR te.fk_soc IS NULL)';
+		if ($this->restrictiononfksoc && $socid && $this->element == 'societe') $sql.= ' AND te.rowid = ' . $socid;
+		//print 'socid='.$socid.' restrictiononfksoc='.$this->restrictiononfksoc.' ismultientitymanaged = '.$this->ismultientitymanaged.' filter = '.$filter.' -> '.$sql."<br>";
 		// Rem: Bug in some mysql version: SELECT MIN(rowid) FROM llx_socpeople WHERE rowid > 1 when one row in database with rowid=1, returns 1 instead of null
 
-		//print $sql."<br>";
 		$result = $this->db->query($sql);
 		if (! $result)
 		{
diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index 085b9874aeb..e69aa485736 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -5281,7 +5281,11 @@ class Form
 		if ($objecttmp->ismultientitymanaged == 2)
 			if (!$user->rights->societe->client->voir && !$user->societe_id) $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
 		$sql.= " WHERE t.entity IN (".getEntity($objecttmp->table_element).")";
-		if ($objecttmp->ismultientitymanaged == 1 && ! empty($user->societe_id)) $sql.= " AND t.fk_soc = ".$user->societe_id;
+		if ($objecttmp->ismultientitymanaged == 1 && ! empty($user->societe_id))
+		{
+			if ($objecttmp->element == 'societe') $sql.= " AND t.rowid = ".$user->societe_id;
+				else $sql.= " AND t.fk_soc = ".$user->societe_id;
+		}
 		if ($searchkey != '') $sql.=natural_search(explode(',',$fieldstoshow), $searchkey);
 		if ($objecttmp->ismultientitymanaged == 2)
 			if (!$user->rights->societe->client->voir && !$user->societe_id) $sql.= " AND t.rowid = sc.fk_soc AND sc.fk_user = " .$user->id;
diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php
index cf37b749b5b..fa624a118f8 100644
--- a/htdocs/core/lib/security.lib.php
+++ b/htdocs/core/lib/security.lib.php
@@ -355,14 +355,14 @@ function restrictedArea($user, $features, $objectid=0, $tableandshare='', $featu
  * Check access by user to object.
  * This function is also called by restrictedArea
  *
- * @param User		$user			User to check
- * @param array		$featuresarray	Features/modules to check. Example: ('user','service','member','project','task',...)
- * @param int		$objectid		Object ID if we want to check a particular record (optional) is linked to a owned thirdparty (optional).
- * @param string	$tableandshare	'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity for multicompany modume. Param not used if objectid is null (optional).
- * @param string	$feature2		Feature to check, second level of permission (optional). Can be or check with 'level1|level2'.
- * @param string	$dbt_keyfield	Field name for socid foreign key if not fk_soc. Not used if objectid is null (optional)
- * @param string	$dbt_select		Field name for select if not rowid. Not used if objectid is null (optional)
- * @return	bool		True if user has access, False otherwise
+ * @param User			$user			User to check
+ * @param array			$featuresarray	Features/modules to check. Example: ('user','service','member','project','task',...)
+ * @param int|string	$objectid		Object ID if we want to check a particular record (optional) is linked to a owned thirdparty (optional).
+ * @param string		$tableandshare	'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity for multicompany modume. Param not used if objectid is null (optional).
+ * @param string		$feature2		Feature to check, second level of permission (optional). Can be or check with 'level1|level2'.
+ * @param string		$dbt_keyfield	Field name for socid foreign key if not fk_soc. Not used if objectid is null (optional)
+ * @param string		$dbt_select		Field name for select if not rowid. Not used if objectid is null (optional)
+ * @return	bool						True if user has access, False otherwise
  * @see restrictedArea
  */
 function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandshare='', $feature2='', $dbt_keyfield='', $dbt_select='rowid')
@@ -379,16 +379,16 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh
 		$sql='';
 
 		// For backward compatibility
-		if ($feature == 'member') $feature='adherent';
+		if ($feature == 'member')  $feature='adherent';
 		if ($feature == 'project') $feature='projet';
-		if ($feature == 'task') $feature='projet_task';
+		if ($feature == 'task')    $feature='projet_task';
 
 		$check = array('adherent','banque','user','usergroup','produit','service','produit|service','categorie'); // Test on entity only (Objects with no link to company)
 		$checksoc = array('societe');	 // Test for societe object
 		$checkother = array('contact','agenda');	 // Test on entity and link to third party. Allowed if link is empty (Ex: contacts...).
 		$checkproject = array('projet','project'); // Test for project object
 		$checktask = array('projet_task');
-		$nocheck = array('barcode','stock','fournisseur');	// No test
+		$nocheck = array('barcode','stock','fournisseur','don');	// No test
 		$checkdefault = 'all other not already defined'; // Test on entity and link to third party. Not allowed if link is empty (Ex: invoice, orders...).
 
 		// If dbtablename not defined, we use same name for table than module name
@@ -401,9 +401,9 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh
 		// Check permission for object with entity
 		if (in_array($feature,$check))
 		{
-			$sql = "SELECT dbt.".$dbt_select;
+			$sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
 			$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
-			$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
+			$sql.= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
 			if (($feature == 'user' || $feature == 'usergroup') && ! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
 			{
 				$sql.= " AND dbt.entity IS NOT NULL";
@@ -423,10 +423,10 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh
 			// If internal user: Check permission for internal users that are restricted on their objects
 			else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir))
 			{
-				$sql = "SELECT sc.fk_soc";
+				$sql = "SELECT COUNT(sc.fk_soc) as nb";
 				$sql.= " FROM (".MAIN_DB_PREFIX."societe_commerciaux as sc";
 				$sql.= ", ".MAIN_DB_PREFIX."societe as s)";
-				$sql.= " WHERE sc.fk_soc = ".$objectid;
+				$sql.= " WHERE sc.fk_soc IN (".$objectid.")";
 				$sql.= " AND sc.fk_user = ".$user->id;
 				$sql.= " AND sc.fk_soc = s.rowid";
 				$sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
@@ -434,9 +434,9 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh
 			// If multicompany and internal users with all permissions, check user is in correct entity
 			else if (! empty($conf->multicompany->enabled))
 			{
-				$sql = "SELECT s.rowid";
+				$sql = "SELECT COUNT(s.rowid) as nb";
 				$sql.= " FROM ".MAIN_DB_PREFIX."societe as s";
-				$sql.= " WHERE s.rowid = ".$objectid;
+				$sql.= " WHERE s.rowid IN (".$objectid.")";
 				$sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
 			}
 		}
@@ -445,27 +445,27 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh
 			// If external user: Check permission for external users
 			if ($user->societe_id > 0)
 			{
-				$sql = "SELECT dbt.".$dbt_select;
+				$sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
 				$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
-				$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
+				$sql.= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
 				$sql.= " AND dbt.fk_soc = ".$user->societe_id;
 			}
 			// If internal user: Check permission for internal users that are restricted on their objects
 			else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir))
 			{
-				$sql = "SELECT dbt.".$dbt_select;
+				$sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
 				$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
 				$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON dbt.fk_soc = sc.fk_soc AND sc.fk_user = '".$user->id."'";
-				$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
+				$sql.= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
 				$sql.= " AND (dbt.fk_soc IS NULL OR sc.fk_soc IS NOT NULL)";	// Contact not linked to a company or to a company of user
 				$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
 			}
 			// If multicompany and internal users with all permissions, check user is in correct entity
 			else if (! empty($conf->multicompany->enabled))
 			{
-				$sql = "SELECT dbt.".$dbt_select;
+				$sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
 				$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
-				$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
+				$sql.= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
 				$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
 			}
 		}
@@ -481,9 +481,9 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh
 			}
 			else
 			{
-				$sql = "SELECT dbt.".$dbt_select;
+				$sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
 				$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
-				$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
+				$sql.= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
 				$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
 			}
 		}
@@ -502,9 +502,9 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh
 			}
 			else
 			{
-				$sql = "SELECT dbt.".$dbt_select;
+				$sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
 				$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
-				$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
+				$sql.= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
 				$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
 			}
 		}
@@ -514,20 +514,20 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh
 			if ($user->societe_id > 0)
 			{
 				if (empty($dbt_keyfield)) dol_print_error('','Param dbt_keyfield is required but not defined');
-				$sql = "SELECT dbt.".$dbt_keyfield;
+				$sql = "SELECT COUNT(dbt.".$dbt_keyfield.") as nb";
 				$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
-				$sql.= " WHERE dbt.rowid = ".$objectid;
+				$sql.= " WHERE dbt.rowid IN (".$objectid.")";
 				$sql.= " AND dbt.".$dbt_keyfield." = ".$user->societe_id;
 			}
 			// If internal user: Check permission for internal users that are restricted on their objects
 			else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir))
 			{
 				if (empty($dbt_keyfield)) dol_print_error('','Param dbt_keyfield is required but not defined');
-				$sql = "SELECT sc.fk_soc";
+				$sql = "SELECT COUNT(sc.fk_soc) as nb";
 				$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
 				$sql.= ", ".MAIN_DB_PREFIX."societe as s";
 				$sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
-				$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
+				$sql.= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
 				$sql.= " AND sc.fk_soc = dbt.".$dbt_keyfield;
 				$sql.= " AND dbt.".$dbt_keyfield." = s.rowid";
 				$sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
@@ -536,20 +536,20 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh
 			// If multicompany and internal users with all permissions, check user is in correct entity
 			else if (! empty($conf->multicompany->enabled))
 			{
-				$sql = "SELECT dbt.".$dbt_select;
+				$sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
 				$sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
-				$sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
+				$sql.= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
 				$sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
 			}
 		}
 
-		//print "sql=".$sql."<br>";
 		if ($sql)
 		{
 			$resql=$db->query($sql);
 			if ($resql)
 			{
-				if ($db->num_rows($resql) == 0)	return false;
+				$obj = $db->fetch_object($resql);
+				if (! $obj || $obj->nb < count(explode(',', $objectid))) return false;
 			}
 			else
 			{
diff --git a/htdocs/don/card.php b/htdocs/don/card.php
index 539bae26e48..5081e32dd0e 100644
--- a/htdocs/don/card.php
+++ b/htdocs/don/card.php
@@ -1,6 +1,6 @@
 <?php
 /* Copyright (C) 2001-2002	Rodolphe Quiedeville	<rodolphe@quiedeville.org>
- * Copyright (C) 2004-2015	Laurent Destailleur		<eldy@users.sourceforge.net>
+ * Copyright (C) 2004-2017	Laurent Destailleur		<eldy@users.sourceforge.net>
  * Copyright (C) 2005-2012	Regis Houssin			<regis.houssin@capnetworks.com>
  * Copyright (C) 2013       Florian Henry		  	<florian.henry@open-concept.pro>
  * Copyright (C) 2015-2016  Alexandre Spangaro	  	<aspangaro.dolibarr@gmail.com>
@@ -630,8 +630,8 @@ if (! empty($id) && $action != 'edit')
 	 * Payments
 	 */
 	$sql = "SELECT p.rowid, p.num_payment, p.datep as dp, p.amount,";
-	$sql.= "c.code as type_code,c.libelle as paiement_type";
-	$sql.= " FROM ".MAIN_DB_PREFIX."payment_donation as p LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as c AND c.entity IN (".getEntity('c_paiement').")";
+	$sql.= " c.code as type_code,c.libelle as paiement_type";
+	$sql.= " FROM ".MAIN_DB_PREFIX."payment_donation as p LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as c ON c.entity IN (".getEntity('c_paiement').")";
 	$sql.= ", ".MAIN_DB_PREFIX."don as d";
 	$sql.= " WHERE d.rowid = '".$id."'";
 	$sql.= " AND p.fk_donation = d.rowid";
diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php
index 868014ea618..e6e309c2239 100644
--- a/htdocs/fourn/class/fournisseur.commande.class.php
+++ b/htdocs/fourn/class/fournisseur.commande.class.php
@@ -43,8 +43,17 @@ class CommandeFournisseur extends CommonOrder
     public $table_element='commande_fournisseur';
     public $table_element_line = 'commande_fournisseurdet';
     public $fk_element = 'fk_commande';
-    public $ismultientitymanaged = 1;	// 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
     public $picto='order';
+    /**
+     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
+     * @var int
+     */
+    public $ismultientitymanaged = 1;
+    /**
+     * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
+     * @var integer
+     */
+    public $restrictiononfksoc = 1;
 
     /**
      * {@inheritdoc}
diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php
index 2be366cfc46..995745b4faa 100644
--- a/htdocs/fourn/class/fournisseur.facture.class.php
+++ b/htdocs/fourn/class/fournisseur.facture.class.php
@@ -44,8 +44,17 @@ class FactureFournisseur extends CommonInvoice
     public $table_element='facture_fourn';
     public $table_element_line='facture_fourn_det';
     public $fk_element='fk_facture_fourn';
-    public $ismultientitymanaged = 1;	// 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
     public $picto='bill';
+    /**
+     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
+     * @var int
+     */
+    public $ismultientitymanaged = 1;
+    /**
+     * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
+     * @var integer
+     */
+    public $restrictiononfksoc = 1;
 
     /**
      * {@inheritdoc}
diff --git a/htdocs/projet/ganttview.php b/htdocs/projet/ganttview.php
index d63f2d2bb62..77e4709f4b9 100644
--- a/htdocs/projet/ganttview.php
+++ b/htdocs/projet/ganttview.php
@@ -32,7 +32,7 @@ require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
 require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
 
-$id=GETPOST('id','int');
+$id=GETPOST('id','intcomma');
 $ref=GETPOST('ref','alpha');
 
 $mode = GETPOST('mode', 'alpha');
@@ -46,7 +46,7 @@ include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php';  // Must be inclu
 // Security check
 $socid=0;
 //if ($user->societe_id > 0) $socid = $user->societe_id;    // For external user, no check is done on company because readability is managed by public status of project and assignement.
-$result = restrictedArea($user, 'projet', $id,'projet&project');
+$result = restrictedArea($user, 'projet', $id, 'projet&project');
 
 $langs->load("users");
 $langs->load("projects");
diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php
index f8fe4a80123..4a37699e6c6 100644
--- a/htdocs/societe/class/societe.class.php
+++ b/htdocs/societe/class/societe.class.php
@@ -53,6 +53,11 @@ class Societe extends CommonObject
 	 * @var int
 	 */
 	public $ismultientitymanaged = 1;
+	/**
+	 * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
+	 * @var integer
+	 */
+	public $restrictiononfksoc = 1;
 
 
 	// BEGIN MODULEBUILDER PROPERTIES
diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php
index 5b830f6e37c..4fa0c8fad6e 100644
--- a/htdocs/supplier_proposal/class/supplier_proposal.class.php
+++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php
@@ -48,8 +48,17 @@ class SupplierProposal extends CommonObject
     public $table_element='supplier_proposal';
     public $table_element_line='supplier_proposaldet';
     public $fk_element='fk_supplier_proposal';
-    public $ismultientitymanaged = 1;	// 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
     public $picto='propal';
+    /**
+     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
+     * @var int
+     */
+    public $ismultientitymanaged = 1;
+    /**
+     * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
+     * @var integer
+     */
+    public $restrictiononfksoc = 1;
 
     /**
      * {@inheritdoc}
-- 
GitLab