dolibarr  13.0.2
security.lib.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2008-2017 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2020 Ferran Marcet <fmarcet@2byte.es>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  * or see https://www.gnu.org/
19  */
20 
38 function dol_encode($chain, $key = '1')
39 {
40  if (is_numeric($key) && $key == '1') // rule 1 is offset of 17 for char
41  {
42  $output_tab = array();
43  $strlength = dol_strlen($chain);
44  for ($i = 0; $i < $strlength; $i++)
45  {
46  $output_tab[$i] = chr(ord(substr($chain, $i, 1)) + 17);
47  }
48  $chain = implode("", $output_tab);
49  } elseif ($key)
50  {
51  $result = '';
52  $strlength = dol_strlen($chain);
53  for ($i = 0; $i < $strlength; $i++)
54  {
55  $keychar = substr($key, ($i % strlen($key)) - 1, 1);
56  $result .= chr(ord(substr($chain, $i, 1)) + (ord($keychar) - 65));
57  }
58  $chain = $result;
59  }
60 
61  return base64_encode($chain);
62 }
63 
73 function dol_decode($chain, $key = '1')
74 {
75  $chain = base64_decode($chain);
76 
77  if (is_numeric($key) && $key == '1') // rule 1 is offset of 17 for char
78  {
79  $output_tab = array();
80  $strlength = dol_strlen($chain);
81  for ($i = 0; $i < $strlength; $i++)
82  {
83  $output_tab[$i] = chr(ord(substr($chain, $i, 1)) - 17);
84  }
85 
86  $chain = implode("", $output_tab);
87  } elseif ($key)
88  {
89  $result = '';
90  $strlength = dol_strlen($chain);
91  for ($i = 0; $i < $strlength; $i++)
92  {
93  $keychar = substr($key, ($i % strlen($key)) - 1, 1);
94  $result .= chr(ord(substr($chain, $i, 1)) - (ord($keychar) - 65));
95  }
96  $chain = $result;
97  }
98 
99  return $chain;
100 }
101 
102 
113 function dol_hash($chain, $type = '0')
114 {
115  global $conf;
116 
117  // No need to add salt for password_hash
118  if (($type == '0' || $type == 'auto') && !empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'password_hash' && function_exists('password_hash'))
119  {
120  return password_hash($chain, PASSWORD_DEFAULT);
121  }
122 
123  // Salt value
124  if (!empty($conf->global->MAIN_SECURITY_SALT) && $type != '4' && $type !== 'md5openldap') $chain = $conf->global->MAIN_SECURITY_SALT.$chain;
125 
126  if ($type == '1' || $type == 'sha1') return sha1($chain);
127  elseif ($type == '2' || $type == 'sha1md5') return sha1(md5($chain));
128  elseif ($type == '3' || $type == 'md5') return md5($chain);
129  elseif ($type == '4' || $type == 'md5openldap') return '{md5}'.base64_encode(mhash(MHASH_MD5, $chain)); // For OpenLdap with md5 (based on an unencrypted password in base)
130  elseif ($type == '5') return hash('sha256', $chain);
131  elseif (!empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'sha1') return sha1($chain);
132  elseif (!empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'sha1md5') return sha1(md5($chain));
133 
134  // No particular encoding defined, use default
135  return md5($chain);
136 }
137 
149 function dol_verifyHash($chain, $hash, $type = '0')
150 {
151  global $conf;
152 
153  if ($type == '0' && !empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'password_hash' && function_exists('password_verify')) {
154  if ($hash[0] == '$') return password_verify($chain, $hash);
155  elseif (strlen($hash) == 32) return dol_verifyHash($chain, $hash, '3'); // md5
156  elseif (strlen($hash) == 40) return dol_verifyHash($chain, $hash, '2'); // sha1md5
157 
158  return false;
159  }
160 
161  return dol_hash($chain, $type) == $hash;
162 }
163 
164 
181 function restrictedArea($user, $features, $objectid = 0, $tableandshare = '', $feature2 = '', $dbt_keyfield = 'fk_soc', $dbt_select = 'rowid', $isdraft = 0)
182 {
183  global $db, $conf;
184  global $hookmanager;
185 
186  //dol_syslog("functions.lib:restrictedArea $feature, $objectid, $dbtablename, $feature2, $dbt_socfield, $dbt_select, $isdraft");
187  //print "user_id=".$user->id.", features=".$features.", feature2=".$feature2.", objectid=".$objectid;
188  //print ", dbtablename=".$dbtablename.", dbt_socfield=".$dbt_keyfield.", dbt_select=".$dbt_select;
189  //print ", perm: ".$features."->".$feature2."=".($user->rights->$features->$feature2->lire)."<br>";
190 
191  $parentfortableentity = '';
192 
193  // Fix syntax of $features param
194  $originalfeatures = $features;
195  if ($features == 'facturerec') $features = 'facture';
196  if ($features == 'mo') $features = 'mrp';
197  if ($features == 'member') $features = 'adherent';
198  if ($features == 'subscription') { $features = 'adherent'; $feature2 = 'cotisation'; };
199  if ($features == 'websitepage') { $features = 'website'; $tableandshare = 'website_page'; $parentfortableentity = 'fk_website@website'; }
200  if ($features == 'project') $features = 'projet';
201  if ($features == 'product') $features = 'produit';
202 
203  // Get more permissions checks from hooks
204  $parameters = array('features'=>$features, 'originalfeatures'=>$originalfeatures, 'objectid'=>$objectid, 'dbt_select'=>$dbt_select, 'idtype'=>$dbt_select, 'isdraft'=>$isdraft);
205  $reshook = $hookmanager->executeHooks('restrictedArea', $parameters);
206 
207  if (isset($hookmanager->resArray['result'])) {
208  if ($hookmanager->resArray['result'] == 0) accessforbidden(); // Module returns 0, so access forbidden
209  }
210  if ($reshook > 0) { // No other test done.
211  return 1;
212  }
213 
214  if ($dbt_select != 'rowid' && $dbt_select != 'id') $objectid = "'".$objectid."'";
215 
216  // Features/modules to check
217  $featuresarray = array($features);
218  if (preg_match('/&/', $features)) $featuresarray = explode("&", $features);
219  elseif (preg_match('/\|/', $features)) $featuresarray = explode("|", $features);
220 
221  // More subfeatures to check
222  if (!empty($feature2)) $feature2 = explode("|", $feature2);
223 
224  $listofmodules = explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL);
225 
226  // Check read permission from module
227  $readok = 1; $nbko = 0;
228  foreach ($featuresarray as $feature) { // first we check nb of test ko
229  $featureforlistofmodule = $feature;
230  if ($featureforlistofmodule == 'produit') $featureforlistofmodule = 'product';
231  if (!empty($user->socid) && !empty($conf->global->MAIN_MODULES_FOR_EXTERNAL) && !in_array($featureforlistofmodule, $listofmodules)) { // If limits on modules for external users, module must be into list of modules for external users
232  $readok = 0; $nbko++;
233  continue;
234  }
235 
236  if ($feature == 'societe') {
237  if (!$user->rights->societe->lire && !$user->rights->fournisseur->lire) { $readok = 0; $nbko++; }
238  } elseif ($feature == 'contact') {
239  if (!$user->rights->societe->contact->lire) { $readok = 0; $nbko++; }
240  } elseif ($feature == 'produit|service') {
241  if (!$user->rights->produit->lire && !$user->rights->service->lire) { $readok = 0; $nbko++; }
242  } elseif ($feature == 'prelevement') {
243  if (!$user->rights->prelevement->bons->lire) { $readok = 0; $nbko++; }
244  } elseif ($feature == 'cheque') {
245  if (!$user->rights->banque->cheque) { $readok = 0; $nbko++; }
246  } elseif ($feature == 'projet') {
247  if (!$user->rights->projet->lire && !$user->rights->projet->all->lire) { $readok = 0; $nbko++; }
248  } elseif ($feature == 'payment') {
249  if (!$user->rights->facture->lire) { $readok = 0; $nbko++; }
250  } elseif ($feature == 'payment_supplier') {
251  if (!$user->rights->fournisseur->facture->lire) { $readok = 0; $nbko++; }
252  } elseif (!empty($feature2)) { // This is for permissions on 2 levels
253  $tmpreadok = 1;
254  foreach ($feature2 as $subfeature) {
255  if ($subfeature == 'user' && $user->id == $objectid) continue; // A user can always read its own card
256  if (!empty($subfeature) && empty($user->rights->$feature->$subfeature->lire) && empty($user->rights->$feature->$subfeature->read)) { $tmpreadok = 0; } elseif (empty($subfeature) && empty($user->rights->$feature->lire) && empty($user->rights->$feature->read)) { $tmpreadok = 0; } else { $tmpreadok = 1; break; } // Break is to bypass second test if the first is ok
257  }
258  if (!$tmpreadok) { // We found a test on feature that is ko
259  $readok = 0; // All tests are ko (we manage here the and, the or will be managed later using $nbko).
260  $nbko++;
261  }
262  } elseif (!empty($feature) && ($feature != 'user' && $feature != 'usergroup')) { // This is permissions on 1 level
263  if (empty($user->rights->$feature->lire)
264  && empty($user->rights->$feature->read)
265  && empty($user->rights->$feature->run)) { $readok = 0; $nbko++; }
266  }
267  }
268 
269  // If a or and at least one ok
270  if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $readok = 1;
271 
272  if (!$readok) accessforbidden();
273  //print "Read access is ok";
274 
275  // Check write permission from module (we need to know write permission to create but also to delete drafts record or to upload files)
276  $createok = 1; $nbko = 0;
277  $wemustcheckpermissionforcreate = (GETPOST('sendit', 'alpha') || GETPOST('linkit', 'alpha') || GETPOST('action', 'aZ09') == 'create' || GETPOST('action', 'aZ09') == 'update');
278  $wemustcheckpermissionfordeletedraft = ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete');
279 
280  if ($wemustcheckpermissionforcreate || $wemustcheckpermissionfordeletedraft)
281  {
282  foreach ($featuresarray as $feature)
283  {
284  if ($feature == 'contact') {
285  if (!$user->rights->societe->contact->creer) { $createok = 0; $nbko++; }
286  } elseif ($feature == 'produit|service') {
287  if (!$user->rights->produit->creer && !$user->rights->service->creer) { $createok = 0; $nbko++; }
288  } elseif ($feature == 'prelevement') {
289  if (!$user->rights->prelevement->bons->creer) { $createok = 0; $nbko++; }
290  } elseif ($feature == 'commande_fournisseur') {
291  if (!$user->rights->fournisseur->commande->creer) { $createok = 0; $nbko++; }
292  } elseif ($feature == 'banque') {
293  if (!$user->rights->banque->modifier) { $createok = 0; $nbko++; }
294  } elseif ($feature == 'cheque') {
295  if (!$user->rights->banque->cheque) { $createok = 0; $nbko++; }
296  } elseif ($feature == 'import') {
297  if (!$user->rights->import->run) { $createok = 0; $nbko++; }
298  } elseif ($feature == 'ecm') {
299  if (!$user->rights->ecm->upload) { $createok = 0; $nbko++; }
300  } elseif (!empty($feature2)) { // This is for permissions on one level
301  foreach ($feature2 as $subfeature) {
302  if ($subfeature == 'user' && $user->id == $objectid && $user->rights->user->self->creer) continue; // User can edit its own card
303  if ($subfeature == 'user' && $user->id == $objectid && $user->rights->user->self->password) continue; // User can edit its own password
304 
305  if (empty($user->rights->$feature->$subfeature->creer)
306  && empty($user->rights->$feature->$subfeature->write)
307  && empty($user->rights->$feature->$subfeature->create)) {
308  $createok = 0;
309  $nbko++;
310  } else {
311  $createok = 1;
312  // Break to bypass second test if the first is ok
313  break;
314  }
315  }
316  } elseif (!empty($feature)) { // This is for permissions on 2 levels ('creer' or 'write')
317  //print '<br>feature='.$feature.' creer='.$user->rights->$feature->creer.' write='.$user->rights->$feature->write; exit;
318  if (empty($user->rights->$feature->creer)
319  && empty($user->rights->$feature->write)
320  && empty($user->rights->$feature->create)) {
321  $createok = 0;
322  $nbko++;
323  }
324  }
325  }
326 
327  // If a or and at least one ok
328  if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $createok = 1;
329 
330  if ($wemustcheckpermissionforcreate && !$createok) accessforbidden();
331  //print "Write access is ok";
332  }
333 
334  // Check create user permission
335  $createuserok = 1;
336  if (GETPOST('action', 'aZ09') == 'confirm_create_user' && GETPOST("confirm", 'aZ09') == 'yes')
337  {
338  if (!$user->rights->user->user->creer) $createuserok = 0;
339 
340  if (!$createuserok) accessforbidden();
341  //print "Create user access is ok";
342  }
343 
344  // Check delete permission from module
345  $deleteok = 1; $nbko = 0;
346  if ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete')
347  {
348  foreach ($featuresarray as $feature)
349  {
350  if ($feature == 'contact')
351  {
352  if (!$user->rights->societe->contact->supprimer) $deleteok = 0;
353  } elseif ($feature == 'produit|service')
354  {
355  if (!$user->rights->produit->supprimer && !$user->rights->service->supprimer) $deleteok = 0;
356  } elseif ($feature == 'commande_fournisseur')
357  {
358  if (!$user->rights->fournisseur->commande->supprimer) $deleteok = 0;
359  } elseif ($feature == 'banque')
360  {
361  if (!$user->rights->banque->modifier) $deleteok = 0;
362  } elseif ($feature == 'cheque')
363  {
364  if (!$user->rights->banque->cheque) $deleteok = 0;
365  } elseif ($feature == 'ecm')
366  {
367  if (!$user->rights->ecm->upload) $deleteok = 0;
368  } elseif ($feature == 'ftp')
369  {
370  if (!$user->rights->ftp->write) $deleteok = 0;
371  } elseif ($feature == 'salaries')
372  {
373  if (!$user->rights->salaries->delete) $deleteok = 0;
374  } elseif ($feature == 'salaries')
375  {
376  if (!$user->rights->salaries->delete) $deleteok = 0;
377  } elseif (!empty($feature2)) // This is for permissions on 2 levels
378  {
379  foreach ($feature2 as $subfeature)
380  {
381  if (empty($user->rights->$feature->$subfeature->supprimer) && empty($user->rights->$feature->$subfeature->delete)) $deleteok = 0;
382  else { $deleteok = 1; break; } // For bypass the second test if the first is ok
383  }
384  } elseif (!empty($feature)) // This is used for permissions on 1 level
385  {
386  //print '<br>feature='.$feature.' creer='.$user->rights->$feature->supprimer.' write='.$user->rights->$feature->delete;
387  if (empty($user->rights->$feature->supprimer)
388  && empty($user->rights->$feature->delete)
389  && empty($user->rights->$feature->run)) $deleteok = 0;
390  }
391  }
392 
393  // If a or and at least one ok
394  if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $deleteok = 1;
395 
396  if (!$deleteok && !($isdraft && $createok)) accessforbidden();
397  //print "Delete access is ok";
398  }
399 
400  // If we have a particular object to check permissions on, we check this object
401  // is linked to a company allowed to $user.
402  if (!empty($objectid) && $objectid > 0)
403  {
404  $ok = checkUserAccessToObject($user, $featuresarray, $objectid, $tableandshare, $feature2, $dbt_keyfield, $dbt_select, $parentfortableentity);
405  $params = array('objectid' => $objectid, 'features' => join(',', $featuresarray), 'features2' => $feature2);
406  return $ok ? 1 : accessforbidden('', 1, 1, 0, $params);
407  }
408 
409  return 1;
410 }
411 
427 function checkUserAccessToObject($user, $featuresarray, $objectid = 0, $tableandshare = '', $feature2 = '', $dbt_keyfield = '', $dbt_select = 'rowid', $parenttableforentity = '')
428 {
429  global $db, $conf;
430 
431  //dol_syslog("functions.lib:restrictedArea $feature, $objectid, $dbtablename, $feature2, $dbt_socfield, $dbt_select, $isdraft");
432  //print "user_id=".$user->id.", features=".join(',', $featuresarray).", feature2=".$feature2.", objectid=".$objectid;
433  //print ", tableandshare=".$tableandshare.", dbt_socfield=".$dbt_keyfield.", dbt_select=".$dbt_select."<br>";
434 
435  // More parameters
436  $params = explode('&', $tableandshare);
437  $dbtablename = (!empty($params[0]) ? $params[0] : '');
438  $sharedelement = (!empty($params[1]) ? $params[1] : $dbtablename);
439 
440  foreach ($featuresarray as $feature)
441  {
442  $sql = '';
443 
444  // For backward compatibility
445  if ($feature == 'member') $feature = 'adherent';
446  if ($feature == 'project') $feature = 'projet';
447  if ($feature == 'task') $feature = 'projet_task';
448 
449  $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'website'); // Test on entity only (Objects with no link to company)
450  $checksoc = array('societe'); // Test for societe object
451  $checkother = array('contact', 'agenda'); // Test on entity + link to third party on field $dbt_keyfield. Allowed if link is empty (Ex: contacts...).
452  $checkproject = array('projet', 'project'); // Test for project object
453  $checktask = array('projet_task'); // Test for task object
454  $nocheck = array('barcode', 'stock'); // No test
455  //$checkdefault = 'all other not already defined'; // Test on entity + link to third party on field $dbt_keyfield. Not allowed if link is empty (Ex: invoice, orders...).
456 
457  // If dbtablename not defined, we use same name for table than module name
458  if (empty($dbtablename))
459  {
460  $dbtablename = $feature;
461  $sharedelement = (!empty($params[1]) ? $params[1] : $dbtablename); // We change dbtablename, so we set sharedelement too.
462  }
463 
464  // Check permission for object on entity only
465  if (in_array($feature, $check))
466  {
467  $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
468  $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
469  if (($feature == 'user' || $feature == 'usergroup') && !empty($conf->multicompany->enabled)) { // Special for multicompany
470  if (!empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
471  if ($conf->entity == 1 && $user->admin && !$user->entity) {
472  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
473  $sql .= " AND dbt.entity IS NOT NULL";
474  } else {
475  $sql .= ",".MAIN_DB_PREFIX."usergroup_user as ug";
476  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
477  $sql .= " AND ((ug.fk_user = dbt.rowid";
478  $sql .= " AND ug.entity IN (".getEntity('usergroup')."))";
479  $sql .= " OR dbt.entity = 0)"; // Show always superadmin
480  }
481  } else {
482  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
483  $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
484  }
485  } else {
486  $reg = array();
487  if ($parenttableforentity && preg_match('/(.*)@(.*)/', $parenttableforentity, $reg)) {
488  $sql .= ", ".MAIN_DB_PREFIX.$reg[2]." as dbtp";
489  $sql .= " WHERE dbt.".$reg[1]." = dbtp.rowid AND dbt.".$dbt_select." IN (".$objectid.")";
490  $sql .= " AND dbtp.entity IN (".getEntity($sharedelement, 1).")";
491  } else {
492  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
493  $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
494  }
495  }
496  } elseif (in_array($feature, $checksoc)) { // We check feature = checksoc
497  if ($user->socid > 0) {
498  // If external user: Check permission for external users
499  if ($user->socid <> $objectid) return false;
500  } elseif (!empty($conf->societe->enabled) && ($user->rights->societe->lire && !$user->rights->societe->client->voir)) {
501  // If internal user: Check permission for internal users that are restricted on their objects
502  $sql = "SELECT COUNT(sc.fk_soc) as nb";
503  $sql .= " FROM (".MAIN_DB_PREFIX."societe_commerciaux as sc";
504  $sql .= ", ".MAIN_DB_PREFIX."societe as s)";
505  $sql .= " WHERE sc.fk_soc IN (".$objectid.")";
506  $sql .= " AND sc.fk_user = ".$user->id;
507  $sql .= " AND sc.fk_soc = s.rowid";
508  $sql .= " AND s.entity IN (".getEntity($sharedelement, 1).")";
509  } elseif (!empty($conf->multicompany->enabled)) {
510  // If multicompany and internal users with all permissions, check user is in correct entity
511  $sql = "SELECT COUNT(s.rowid) as nb";
512  $sql .= " FROM ".MAIN_DB_PREFIX."societe as s";
513  $sql .= " WHERE s.rowid IN (".$objectid.")";
514  $sql .= " AND s.entity IN (".getEntity($sharedelement, 1).")";
515  }
516  } elseif (in_array($feature, $checkother)) // Test on entity + link to thirdparty. Allowed if link is empty (Ex: contacts...).
517  {
518  // If external user: Check permission for external users
519  if ($user->socid > 0)
520  {
521  $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
522  $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
523  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
524  $sql .= " AND dbt.fk_soc = ".$user->socid;
525  } // If internal user: Check permission for internal users that are restricted on their objects
526  elseif (!empty($conf->societe->enabled) && ($user->rights->societe->lire && !$user->rights->societe->client->voir))
527  {
528  $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
529  $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
530  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON dbt.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
531  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
532  $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
533  $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
534  } // If multicompany and internal users with all permissions, check user is in correct entity
535  elseif (!empty($conf->multicompany->enabled))
536  {
537  $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
538  $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
539  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
540  $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
541  }
542  if ($feature == 'agenda')// Also check owner or attendee for users without allactions->read
543  {
544  if ($objectid > 0 && empty($user->rights->agenda->allactions->read)) {
545  require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
546  $action = new ActionComm($db);
547  $action->fetch($objectid);
548  if ($action->authorid != $user->id && $action->userownerid != $user->id && !(array_key_exists($user->id, $action->userassigned))) {
549  return false;
550  }
551  }
552  }
553  } elseif (in_array($feature, $checkproject)) {
554  if (!empty($conf->projet->enabled) && empty($user->rights->projet->all->lire))
555  {
556  include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
557  $projectstatic = new Project($db);
558  $tmps = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, 0);
559  $tmparray = explode(',', $tmps);
560  if (!in_array($objectid, $tmparray)) return false;
561  } else {
562  $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
563  $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
564  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
565  $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
566  }
567  } elseif (in_array($feature, $checktask)) {
568  if (!empty($conf->projet->enabled) && empty($user->rights->projet->all->lire))
569  {
570  $task = new Task($db);
571  $task->fetch($objectid);
572 
573  include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
574  $projectstatic = new Project($db);
575  $tmps = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, 0);
576  $tmparray = explode(',', $tmps);
577  if (!in_array($task->fk_project, $tmparray)) return false;
578  } else {
579  $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
580  $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
581  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
582  $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
583  }
584  } elseif (!in_array($feature, $nocheck)) { // By default (case of $checkdefault), we check on object entity + link to third party on field $dbt_keyfield
585  // If external user: Check permission for external users
586  if ($user->socid > 0) {
587  if (empty($dbt_keyfield)) dol_print_error('', 'Param dbt_keyfield is required but not defined');
588  $sql = "SELECT COUNT(dbt.".$dbt_keyfield.") as nb";
589  $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
590  $sql .= " WHERE dbt.rowid IN (".$objectid.")";
591  $sql .= " AND dbt.".$dbt_keyfield." = ".$user->socid;
592  } elseif (!empty($conf->societe->enabled) && !$user->rights->societe->client->voir) {
593  // If internal user: Check permission for internal users that are restricted on their objects
594  if ($feature != 'ticket') {
595  if (empty($dbt_keyfield)) dol_print_error('', 'Param dbt_keyfield is required but not defined');
596  $sql = "SELECT COUNT(sc.fk_soc) as nb";
597  $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
598  $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
599  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
600  $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
601  $sql .= " AND sc.fk_soc = dbt.".$dbt_keyfield;
602  $sql .= " AND sc.fk_user = ".$user->id;
603  } else {
604  // On ticket, the thirdparty is not mandatory, so we need a special test to accept record with no thirdparties.
605  $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
606  $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
607  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON sc.fk_soc = dbt.".$dbt_keyfield." AND sc.fk_user = ".$user->id;
608  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
609  $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
610  $sql .= " AND (sc.fk_user = ".$user->id." OR sc.fk_user IS NULL)";
611  }
612  } // If multicompany and internal users with all permissions, check user is in correct entity
613  elseif (!empty($conf->multicompany->enabled))
614  {
615  $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
616  $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
617  $sql .= " WHERE dbt.".$dbt_select." IN (".$objectid.")";
618  $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
619  }
620  }
621 
622  if ($sql)
623  {
624  $resql = $db->query($sql);
625  if ($resql)
626  {
627  $obj = $db->fetch_object($resql);
628  if (!$obj || $obj->nb < count(explode(',', $objectid))) return false;
629  } else {
630  return false;
631  }
632  }
633  }
634 
635  return true;
636 }
637 
649 function accessforbidden($message = '', $printheader = 1, $printfooter = 1, $showonlymessage = 0, $params = null)
650 {
651  global $conf, $db, $user, $langs, $hookmanager;
652  if (!is_object($langs))
653  {
654  include_once DOL_DOCUMENT_ROOT.'/core/class/translate.class.php';
655  $langs = new Translate('', $conf);
656  $langs->setDefaultLang();
657  }
658 
659  $langs->load("errors");
660 
661  if ($printheader)
662  {
663  if (function_exists("llxHeader")) llxHeader('');
664  elseif (function_exists("llxHeaderVierge")) llxHeaderVierge('');
665  }
666  print '<div class="error">';
667  if (!$message) print $langs->trans("ErrorForbidden");
668  else print $message;
669  print '</div>';
670  print '<br>';
671  if (empty($showonlymessage))
672  {
673  global $action, $object;
674  if (empty($hookmanager))
675  {
676  $hookmanager = new HookManager($db);
677  // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
678  $hookmanager->initHooks(array('main'));
679  }
680  $parameters = array('message'=>$message, 'params'=>$params);
681  $reshook = $hookmanager->executeHooks('getAccessForbiddenMessage', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
682  print $hookmanager->resPrint;
683  if (empty($reshook))
684  {
685  if ($user->login)
686  {
687  print $langs->trans("CurrentLogin").': <font class="error">'.$user->login.'</font><br>';
688  print $langs->trans("ErrorForbidden2", $langs->transnoentitiesnoconv("Home"), $langs->transnoentitiesnoconv("Users"));
689  } else {
690  print $langs->trans("ErrorForbidden3");
691  }
692  }
693  }
694  if ($printfooter && function_exists("llxFooter")) llxFooter();
695  exit(0);
696 }
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_hash($chain, $type= '0')
Returns a hash of a string.
dol_decode($chain, $key= '1')
Decode a base 64 encoded + specific delta change.
checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandshare= '', $feature2= '', $dbt_keyfield= '', $dbt_select= 'rowid', $parenttableforentity= '')
Check access by user to object.
Class to manage agenda events (actions)
dol_verifyHash($chain, $hash, $type= '0')
Compute a hash and compare it to the given one For backward compatibility reasons, if the hash is not in the password_hash format, we will try to match against md5 and sha1md5 If constant MAIN_SECURITY_HASH_ALGO is defined, we use this function as hashing function.
llxHeader()
Empty header.
Definition: wrapper.php:45
Class to manage hooks.
Class to manage projects.
dol_strlen($string, $stringencoding= 'UTF-8')
Make a strlen call.
dol_encode($chain, $key= '1')
Encode a string with base 64 algorithm + specific delta change.
restrictedArea($user, $features, $objectid=0, $tableandshare= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid', $isdraft=0)
Check permissions of a user to show a page and an object.
accessforbidden($message= '', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program Calling this function terminate execution ...
Class to manage translations.
llxHeaderVierge()
Header function.
print
Draft customers invoices.
Definition: index.php:89
Class to manage tasks.
Definition: task.class.php:35
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
llxFooter()
Empty footer.
Definition: wrapper.php:59