dolibarr 21.0.0-beta
security.lib.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2008-2021 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2008-2021 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2020 Ferran Marcet <fmarcet@2byte.es>
5 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * or see https://www.gnu.org/
20 */
21
39function dol_encode($chain, $key = '1')
40{
41 if (is_numeric($key) && $key == '1') { // rule 1 is offset of 17 for char
42 $output_tab = array();
43 $strlength = dol_strlen($chain);
44 for ($i = 0; $i < $strlength; $i++) {
45 $output_tab[$i] = chr(ord(substr($chain, $i, 1)) + 17);
46 }
47 $chain = implode("", $output_tab);
48 } elseif ($key) {
49 $result = '';
50 $strlength = dol_strlen($chain);
51 for ($i = 0; $i < $strlength; $i++) {
52 $keychar = substr($key, ($i % strlen($key)) - 1, 1);
53 $result .= chr(ord(substr($chain, $i, 1)) + (ord($keychar) - 65));
54 }
55 $chain = $result;
56 }
57
58 return base64_encode($chain);
59}
60
70function dol_decode($chain, $key = '1')
71{
72 $chain = base64_decode($chain);
73
74 if (is_numeric($key) && $key == '1') { // rule 1 is offset of 17 for char
75 $output_tab = array();
76 $strlength = dol_strlen($chain);
77 for ($i = 0; $i < $strlength; $i++) {
78 $output_tab[$i] = chr(ord(substr($chain, $i, 1)) - 17);
79 }
80
81 $chain = implode("", $output_tab);
82 } elseif ($key) {
83 $result = '';
84 $strlength = dol_strlen($chain);
85 for ($i = 0; $i < $strlength; $i++) {
86 $keychar = substr($key, ($i % strlen($key)) - 1, 1);
87 $result .= chr(ord(substr($chain, $i, 1)) - (ord($keychar) - 65));
88 }
89 $chain = $result;
90 }
91
92 return $chain;
93}
94
101function dolGetRandomBytes($length)
102{
103 if (function_exists('random_bytes')) { // Available with PHP 7 only.
104 return bin2hex(random_bytes((int) floor($length / 2))); // the bin2hex will double the number of bytes so we take length / 2
105 }
106
107 return bin2hex(openssl_random_pseudo_bytes((int) floor($length / 2))); // the bin2hex will double the number of bytes so we take length / 2. May be very slow on Windows.
108}
109
110
111define('MAIN_SECURITY_REVERSIBLE_ALGO', 'AES-256-CTR');
112
126function dolEncrypt($chain, $key = '', $ciphering = '', $forceseed = '')
127{
128 global $conf;
129 global $dolibarr_disable_dolcrypt_for_debug;
130
131 if ($chain === '' || is_null($chain)) {
132 return '';
133 }
134
135 $reg = array();
136 if (preg_match('/^dolcrypt:([^:]+):(.+)$/', $chain, $reg)) {
137 // The $chain is already a encrypted string
138 return $chain;
139 }
140
141 if (empty($key)) {
142 $key = $conf->file->instance_unique_id;
143 }
144 if (empty($ciphering)) {
145 $ciphering = constant('MAIN_SECURITY_REVERSIBLE_ALGO');
146 }
147
148 $newchain = $chain;
149
150 if (function_exists('openssl_encrypt') && empty($dolibarr_disable_dolcrypt_for_debug)) {
151 if (empty($key)) {
152 return $chain;
153 }
154
155 $ivlen = 16;
156 if (function_exists('openssl_cipher_iv_length')) {
157 $ivlen = openssl_cipher_iv_length($ciphering);
158 }
159 if ($ivlen === false || $ivlen < 1 || $ivlen > 32) {
160 $ivlen = 16;
161 }
162 if (empty($forceseed)) {
163 $ivseed = dolGetRandomBytes($ivlen);
164 } else {
165 $ivseed = dol_substr(md5($forceseed), 0, $ivlen, 'ascii', 1);
166 }
167
168 $newchain = openssl_encrypt($chain, $ciphering, $key, 0, $ivseed);
169 return 'dolcrypt:'.$ciphering.':'.$ivseed.':'.$newchain;
170 } else {
171 return $chain;
172 }
173}
174
185function dolDecrypt($chain, $key = '')
186{
187 global $conf;
188
189 if ($chain === '' || is_null($chain)) {
190 return '';
191 }
192
193 if (empty($key)) {
194 if (!empty($conf->file->dolcrypt_key)) {
195 // If dolcrypt_key is defined, we used it in priority
196 $key = $conf->file->dolcrypt_key;
197 } else {
198 // We fall back on the instance_unique_id
199 $key = !empty($conf->file->instance_unique_id) ? $conf->file->instance_unique_id : "";
200 }
201 }
202
203 //var_dump('key='.$key);
204 $reg = array();
205 if (preg_match('/^dolcrypt:([^:]+):(.+)$/', $chain, $reg)) {
206 // Do not enable this log, except during debug
207 //dol_syslog("We try to decrypt the chain: ".$chain, LOG_DEBUG);
208
209 $ciphering = $reg[1];
210 if (function_exists('openssl_decrypt')) {
211 if (empty($key)) {
212 dol_syslog("Error dolDecrypt decrypt key is empty", LOG_WARNING);
213 return $chain;
214 }
215 $tmpexplode = explode(':', $reg[2]);
216 if (!empty($tmpexplode[1]) && is_string($tmpexplode[0])) {
217 $newchain = openssl_decrypt($tmpexplode[1], $ciphering, $key, 0, $tmpexplode[0]);
218 } else {
219 $newchain = openssl_decrypt((string) $tmpexplode[0], $ciphering, $key, 0, '');
220 }
221 } else {
222 dol_syslog("Error dolDecrypt openssl_decrypt is not available", LOG_ERR);
223 return $chain;
224 }
225 return $newchain;
226 } else {
227 return $chain;
228 }
229}
230
243function dol_hash($chain, $type = '0', $nosalt = 0)
244{
245 // No need to add salt for password_hash
246 if (($type == '0' || $type == 'auto') && getDolGlobalString('MAIN_SECURITY_HASH_ALGO') && getDolGlobalString('MAIN_SECURITY_HASH_ALGO') == 'password_hash' && function_exists('password_hash')) {
247 if (strpos($chain, "\0") !== false) {
248 // String contains a null character that can't be encoded. Return an error instead of fatal error.
249 return 'Invalid string to encrypt. Contains a null character.';
250 }
251 return password_hash($chain, PASSWORD_DEFAULT);
252 }
253
254 // Salt value
255 if (getDolGlobalString('MAIN_SECURITY_SALT') && $type != '4' && $type !== 'openldap' && empty($nosalt)) {
256 $chain = getDolGlobalString('MAIN_SECURITY_SALT') . $chain;
257 }
258
259 if ($type == '1' || $type == 'sha1') {
260 return sha1($chain);
261 } elseif ($type == '2' || $type == 'sha1md5') {
262 return sha1(md5($chain));
263 } elseif ($type == '3' || $type == 'md5') { // For hashing with no need of security
264 return md5($chain);
265 } elseif ($type == '4' || $type == 'openldap') {
266 return dolGetLdapPasswordHash($chain, getDolGlobalString('LDAP_PASSWORD_HASH_TYPE', 'md5'));
267 } elseif ($type == '5' || $type == 'sha256') {
268 return hash('sha256', $chain);
269 } elseif ($type == '6' || $type == 'password_hash') {
270 return password_hash($chain, PASSWORD_DEFAULT);
271 } elseif (getDolGlobalString('MAIN_SECURITY_HASH_ALGO') == 'sha1') {
272 return sha1($chain);
273 } elseif (getDolGlobalString('MAIN_SECURITY_HASH_ALGO') == 'sha1md5') {
274 return sha1(md5($chain));
275 }
276
277 // No particular encoding defined, use default
278 return md5($chain);
279}
280
293function dol_verifyHash($chain, $hash, $type = '0')
294{
295 if ($type == '0' && getDolGlobalString('MAIN_SECURITY_HASH_ALGO') && getDolGlobalString('MAIN_SECURITY_HASH_ALGO') == 'password_hash' && function_exists('password_verify')) {
296 if (! empty($hash[0]) && $hash[0] == '$') {
297 return password_verify($chain, $hash);
298 } elseif (dol_strlen($hash) == 32) {
299 return dol_verifyHash($chain, $hash, '3'); // md5
300 } elseif (dol_strlen($hash) == 40) {
301 return dol_verifyHash($chain, $hash, '2'); // sha1md5
302 }
303
304 return false;
305 }
306
307 return dol_hash($chain, $type) == $hash;
308}
309
317function dolGetLdapPasswordHash($password, $type = 'md5')
318{
319 if (empty($type)) {
320 $type = 'md5';
321 }
322
323 $salt = substr(sha1((string) time()), 0, 8);
324
325 if ($type === 'md5') {
326 return '{MD5}' . base64_encode(hash("md5", $password, true)); //For OpenLdap with md5 (based on an unencrypted password in base)
327 } elseif ($type === 'md5frommd5') {
328 return '{MD5}' . base64_encode(hex2bin($password)); // Create OpenLDAP MD5 password from Dolibarr MD5 password
329 } elseif ($type === 'smd5') {
330 return "{SMD5}" . base64_encode(hash("md5", $password . $salt, true) . $salt);
331 } elseif ($type === 'sha') {
332 return '{SHA}' . base64_encode(hash("sha1", $password, true));
333 } elseif ($type === 'ssha') {
334 return "{SSHA}" . base64_encode(hash("sha1", $password . $salt, true) . $salt);
335 } elseif ($type === 'sha256') {
336 return "{SHA256}" . base64_encode(hash("sha256", $password, true));
337 } elseif ($type === 'ssha256') {
338 return "{SSHA256}" . base64_encode(hash("sha256", $password . $salt, true) . $salt);
339 } elseif ($type === 'sha384') {
340 return "{SHA384}" . base64_encode(hash("sha384", $password, true));
341 } elseif ($type === 'ssha384') {
342 return "{SSHA384}" . base64_encode(hash("sha384", $password . $salt, true) . $salt);
343 } elseif ($type === 'sha512') {
344 return "{SHA512}" . base64_encode(hash("sha512", $password, true));
345 } elseif ($type === 'ssha512') {
346 return "{SSHA512}" . base64_encode(hash("sha512", $password . $salt, true) . $salt);
347 } elseif ($type === 'crypt') {
348 return '{CRYPT}' . crypt($password, $salt);
349 } elseif ($type === 'clear') {
350 return '{CLEAR}' . $password; // Just for test, plain text password is not secured !
351 }
352 return "";
353}
354
375function restrictedArea(User $user, $features, $object = 0, $tableandshare = '', $feature2 = '', $dbt_keyfield = 'fk_soc', $dbt_select = 'rowid', $isdraft = 0, $mode = 0)
376{
377 global $hookmanager;
378
379 // Define $objectid
380 if (is_object($object)) {
381 $objectid = $object->id;
382 } else {
383 $objectid = $object; // $objectid can be X or 'X,Y,Z'
384 }
385 if ($objectid == "-1") {
386 $objectid = 0;
387 }
388 if ($objectid) {
389 $objectid = preg_replace('/[^0-9\.\,]/', '', (string) $objectid); // For the case value is coming from a non sanitized user input
390 }
391
392 //dol_syslog("functions.lib:restrictedArea $feature, $objectid, $dbtablename, $feature2, $dbt_socfield, $dbt_select, $isdraft");
393 /*print "user_id=".$user->id.", features=".$features.", feature2=".$feature2.", objectid=".$objectid;
394 print ", dbtablename=".$tableandshare.", dbt_socfield=".$dbt_keyfield.", dbt_select=".$dbt_select;
395 print ", perm: user->hasRight(".$features.($feature2 ? ",".$feature2 : "").", lire) = ".($feature2 ? $user->hasRight($features, $feature2, 'lire') : $user->hasRight($features, 'lire'))."<br>";
396 */
397
398 $parentfortableentity = '';
399
400 // Fix syntax of $features param to support non standard module names.
401 // @todo : use elseif ?
402 $originalfeatures = $features;
403 if ($features == 'agenda') {
404 $tableandshare = 'actioncomm&societe';
405 $feature2 = 'myactions|allactions';
406 $dbt_select = 'id';
407 }
408 if ($features == 'bank') {
409 $features = 'banque';
410 }
411 if ($features == 'facturerec') {
412 $features = 'facture';
413 }
414 if ($features == 'supplier_invoicerec') {
415 $features = 'fournisseur';
416 $feature2 = 'facture';
417 }
418 if ($features == 'mo') {
419 $features = 'mrp';
420 }
421 if ($features == 'member') {
422 $features = 'adherent';
423 }
424 if ($features == 'subscription') {
425 $features = 'adherent';
426 $feature2 = 'cotisation';
427 }
428 if ($features == 'website' && is_object($object) && $object->element == 'websitepage') {
429 $parentfortableentity = 'fk_website@website';
430 }
431 if ($features == 'project') {
432 $features = 'projet';
433 }
434 if ($features == 'product') {
435 $features = 'produit';
436 }
437 if ($features == 'productbatch') {
438 $features = 'produit';
439 }
440 if ($features == 'tax') {
441 $feature2 = 'charges';
442 }
443 if ($features == 'workstation') {
444 $feature2 = 'workstation';
445 }
446 if ($features == 'fournisseur') { // When vendor invoice and purchase order are into module 'fournisseur'
447 $features = 'fournisseur';
448 if (is_object($object) && $object->element == 'invoice_supplier') {
449 $feature2 = 'facture';
450 } elseif (is_object($object) && $object->element == 'order_supplier') {
451 $feature2 = 'commande';
452 }
453 }
454 if ($features == 'payment_sc') {
455 $tableandshare = 'paiementcharge';
456 $parentfortableentity = 'fk_charge@chargesociales';
457 }
458 // if commonObjectLine : Using many2one related commonObject
459 // @see commonObjectLine::parentElement
460 if (in_array($features, ['commandedet', 'propaldet', 'facturedet', 'supplier_proposaldet', 'evaluationdet', 'skilldet', 'deliverydet', 'contratdet'])) {
461 $features = substr($features, 0, -3);
462 } elseif (in_array($features, ['stocktransferline', 'inventoryline', 'bomline', 'expensereport_det', 'facture_fourn_det'])) {
463 $features = substr($features, 0, -4);
464 } elseif ($features == 'commandefournisseurdispatch') {
465 $features = 'commandefournisseur';
466 } elseif ($features == 'invoice_supplier_det_rec') {
467 $features = 'invoice_supplier_rec';
468 }
469 // @todo check : project_task
470 // @todo possible ?
471 // elseif (substr($features, -3, 3) == 'det') {
472 // $features = substr($features, 0, -3);
473 // } elseif (substr($features, -4, 4) == '_det' || substr($features, -4, 4) == 'line') {
474 // $features = substr($features, 0, -4);
475 // }
476
477 //print $features.' - '.$tableandshare.' - '.$feature2.' - '.$dbt_select."\n";
478
479 // Get more permissions checks from hooks
480 $parameters = array('features' => $features, 'originalfeatures' => $originalfeatures, 'objectid' => $objectid, 'dbt_select' => $dbt_select, 'idtype' => $dbt_select, 'isdraft' => $isdraft);
481 if (!empty($hookmanager)) {
482 $reshook = $hookmanager->executeHooks('restrictedArea', $parameters);
483
484 if (isset($hookmanager->resArray['result'])) {
485 if ($hookmanager->resArray['result'] == 0) {
486 if ($mode) {
487 return 0;
488 } else {
489 accessforbidden(); // Module returns 0, so access forbidden
490 }
491 }
492 }
493 if ($reshook > 0) { // No other test done.
494 return 1;
495 }
496 }
497
498 // Features/modules to check (to support the & and | operator)
499 $featuresarray = array($features);
500 if (preg_match('/&/', $features)) {
501 $featuresarray = explode("&", $features);
502 } elseif (preg_match('/\|/', $features)) {
503 $featuresarray = explode("|", $features);
504 }
505
506 // More subfeatures to check
507 if (!empty($feature2)) {
508 $feature2 = explode("|", $feature2);
509 }
510
511 $listofmodules = explode(',', getDolGlobalString('MAIN_MODULES_FOR_EXTERNAL'));
512
513 // Check read permission from module
514 $readok = 1;
515 $nbko = 0;
516 foreach ($featuresarray as $feature) { // first we check nb of test ko
517 $featureforlistofmodule = $feature;
518 if ($featureforlistofmodule == 'produit') {
519 $featureforlistofmodule = 'product';
520 }
521 if ($featureforlistofmodule == 'supplier_proposal') {
522 $featureforlistofmodule = 'supplierproposal';
523 }
524 if (!empty($user->socid) && getDolGlobalString('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
525 $readok = 0;
526 $nbko++;
527 continue;
528 }
529
530 if ($feature == 'societe' && (empty($feature2) || !in_array('contact', $feature2))) {
531 if (!$user->hasRight('societe', 'lire') && !$user->hasRight('fournisseur', 'lire')) {
532 $readok = 0;
533 $nbko++;
534 }
535 } elseif (($feature == 'societe' && (!empty($feature2) && in_array('contact', $feature2))) || $feature == 'contact') {
536 if (!$user->hasRight('societe', 'contact', 'lire')) {
537 $readok = 0;
538 $nbko++;
539 }
540 } elseif ($feature == 'produit|service') {
541 if (!$user->hasRight('produit', 'lire') && !$user->hasRight('service', 'lire')) {
542 $readok = 0;
543 $nbko++;
544 }
545 } elseif ($feature == 'prelevement') {
546 if (!$user->hasRight('prelevement', 'bons', 'lire')) {
547 $readok = 0;
548 $nbko++;
549 }
550 } elseif ($feature == 'cheque') {
551 if (!$user->hasRight('banque', 'cheque')) {
552 $readok = 0;
553 $nbko++;
554 }
555 } elseif ($feature == 'projet') {
556 if (!$user->hasRight('projet', 'lire') && !$user->hasRight('projet', 'all', 'lire')) {
557 $readok = 0;
558 $nbko++;
559 }
560 } elseif ($feature == 'payment') {
561 if (!$user->hasRight('facture', 'lire')) {
562 $readok = 0;
563 $nbko++;
564 }
565 } elseif ($feature == 'payment_supplier') {
566 if (!$user->hasRight('fournisseur', 'facture', 'lire')) {
567 $readok = 0;
568 $nbko++;
569 }
570 } elseif ($feature == 'payment_sc') {
571 if (!$user->hasRight('tax', 'charges', 'lire')) {
572 $readok = 0;
573 $nbko++;
574 }
575 } elseif (!empty($feature2)) { // This is for permissions on 2 levels (module->object->read)
576 $tmpreadok = 1;
577 foreach ($feature2 as $subfeature) {
578 if ($subfeature == 'user' && $user->id == $objectid) {
579 continue; // A user can always read its own card
580 }
581 if ($subfeature == 'fiscalyear' && $user->hasRight('accounting', 'fiscalyear', 'write')) {
582 // only one right for fiscalyear
583 $tmpreadok = 1;
584 continue;
585 }
586 if (!empty($subfeature) && !$user->hasRight($feature, $subfeature, 'lire') && !$user->hasRight($feature, $subfeature, 'read')) {
587 $tmpreadok = 0;
588 } elseif (empty($subfeature) && !$user->hasRight($feature, 'lire') && !$user->hasRight($feature, 'read')) {
589 $tmpreadok = 0;
590 } else {
591 $tmpreadok = 1;
592 break;
593 } // Break is to bypass second test if the first is ok
594 }
595 if (!$tmpreadok) { // We found a test on feature that is ko
596 $readok = 0; // All tests are ko (we manage here the and, the or will be managed later using $nbko).
597 $nbko++;
598 }
599 } elseif (!empty($feature) && ($feature != 'user' && $feature != 'usergroup')) { // This is permissions on 1 level (module->read)
600 if (!$user->hasRight($feature, 'lire')
601 && !$user->hasRight($feature, 'read')
602 && !$user->hasRight($feature, 'run')) {
603 $readok = 0;
604 $nbko++;
605 }
606 }
607 }
608
609 // If a or and at least one ok
610 if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) {
611 $readok = 1;
612 }
613
614 if (!$readok) {
615 if ($mode) {
616 return 0;
617 } else {
619 }
620 }
621 //print "Read access is ok";
622
623 // Check write permission from module (we need to know write permission to create but also to delete drafts record or to upload files)
624 $createok = 1;
625 $nbko = 0;
626 $wemustcheckpermissionforcreate = (GETPOST('sendit', 'alpha') || GETPOST('linkit', 'alpha') || in_array(GETPOST('action', 'aZ09'), array('create', 'update', 'set', 'upload', 'add_element_resource', 'confirm_deletebank', 'confirm_delete_linked_resource')) || GETPOST('roworder', 'alpha', 2));
627 $wemustcheckpermissionfordeletedraft = ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete');
628
629 if ($wemustcheckpermissionforcreate || $wemustcheckpermissionfordeletedraft) {
630 foreach ($featuresarray as $feature) {
631 if ($feature == 'contact') {
632 if (!$user->hasRight('societe', 'contact', 'creer')) {
633 $createok = 0;
634 $nbko++;
635 }
636 } elseif ($feature == 'produit|service') {
637 if (!$user->hasRight('produit', 'creer') && !$user->hasRight('service', 'creer')) {
638 $createok = 0;
639 $nbko++;
640 }
641 } elseif ($feature == 'prelevement') {
642 if (!$user->hasRight('prelevement', 'bons', 'creer')) {
643 $createok = 0;
644 $nbko++;
645 }
646 } elseif ($feature == 'commande_fournisseur') {
647 if (!$user->hasRight('fournisseur', 'commande', 'creer') || !$user->hasRight('supplier_order', 'creer')) {
648 $createok = 0;
649 $nbko++;
650 }
651 } elseif ($feature == 'banque') {
652 if (!$user->hasRight('banque', 'modifier')) {
653 $createok = 0;
654 $nbko++;
655 }
656 } elseif ($feature == 'cheque') {
657 if (!$user->hasRight('banque', 'cheque')) {
658 $createok = 0;
659 $nbko++;
660 }
661 } elseif ($feature == 'import') {
662 if (!$user->hasRight('import', 'run')) {
663 $createok = 0;
664 $nbko++;
665 }
666 } elseif ($feature == 'ecm') {
667 if (!$user->hasRight('ecm', 'upload')) {
668 $createok = 0;
669 $nbko++;
670 }
671 } elseif ($feature == 'modulebuilder') {
672 if (!$user->hasRight('modulebuilder', 'run')) {
673 $createok = 0;
674 $nbko++;
675 }
676 } elseif (!empty($feature2)) { // This is for permissions on 2 levels (module->object->write)
677 foreach ($feature2 as $subfeature) {
678 if ($subfeature == 'user' && $user->id == $objectid && $user->hasRight('user', 'self', 'creer')) {
679 continue; // User can edit its own card
680 }
681 if ($subfeature == 'user' && $user->id == $objectid && $user->hasRight('user', 'self', 'password')) {
682 continue; // User can edit its own password
683 }
684 if ($subfeature == 'user' && $user->id != $objectid && $user->hasRight('user', 'user', 'password')) {
685 continue; // User can edit another user's password
686 }
687
688 if (!$user->hasRight($feature, $subfeature, 'creer')
689 && !$user->hasRight($feature, $subfeature, 'write')
690 && !$user->hasRight($feature, $subfeature, 'create')) {
691 $createok = 0;
692 $nbko++;
693 } else {
694 $createok = 1;
695 // Break to bypass second test if the first is ok
696 break;
697 }
698 }
699 } elseif (!empty($feature)) { // This is for permissions on 1 levels (module->write)
700 //print '<br>feature='.$feature.' creer='.$user->rights->$feature->creer.' write='.$user->rights->$feature->write; exit;
701 if (!$user->hasRight($feature, 'creer')
702 && !$user->hasRight($feature, 'write')
703 && !$user->hasRight($feature, 'create')) {
704 $createok = 0;
705 $nbko++;
706 }
707 }
708 }
709
710 // If a or and at least one ok
711 if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) {
712 $createok = 1;
713 }
714
715 if ($wemustcheckpermissionforcreate && !$createok) {
716 if ($mode) {
717 return 0;
718 } else {
720 }
721 }
722 //print "Write access is ok";
723 }
724
725 // Check create user permission
726 $createuserok = 1;
727 if (GETPOST('action', 'aZ09') == 'confirm_create_user' && GETPOST("confirm", 'aZ09') == 'yes') {
728 if (!$user->hasRight('user', 'user', 'creer')) {
729 $createuserok = 0;
730 }
731
732 if (!$createuserok) {
733 if ($mode) {
734 return 0;
735 } else {
737 }
738 }
739 //print "Create user access is ok";
740 }
741
742 // Check delete permission from module
743 $deleteok = 1;
744 $nbko = 0;
745 if ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete') {
746 foreach ($featuresarray as $feature) {
747 if ($feature == 'bookmark') {
748 if (!$user->hasRight('bookmark', 'supprimer')) {
749 if ($user->id != $object->fk_user || !$user->hasRight('bookmark', 'creer')) {
750 $deleteok = 0;
751 }
752 }
753 } elseif ($feature == 'contact') {
754 if (!$user->hasRight('societe', 'contact', 'supprimer')) {
755 $deleteok = 0;
756 }
757 } elseif ($feature == 'produit|service') {
758 if (!$user->hasRight('produit', 'supprimer') && !$user->hasRight('service', 'supprimer')) {
759 $deleteok = 0;
760 }
761 } elseif ($feature == 'commande_fournisseur') {
762 if (!$user->hasRight('fournisseur', 'commande', 'supprimer')) {
763 $deleteok = 0;
764 }
765 } elseif ($feature == 'payment_supplier') { // Permission to delete a payment of an invoice is permission to edit an invoice.
766 if (!$user->hasRight('fournisseur', 'facture', 'creer')) {
767 $deleteok = 0;
768 }
769 } elseif ($feature == 'payment') {
770 if (!$user->hasRight('facture', 'paiement')) {
771 $deleteok = 0;
772 }
773 } elseif ($feature == 'payment_sc') {
774 if (!$user->hasRight('tax', 'charges', 'creer')) {
775 $deleteok = 0;
776 }
777 } elseif ($feature == 'banque') {
778 if (!$user->hasRight('banque', 'modifier')) {
779 $deleteok = 0;
780 }
781 } elseif ($feature == 'cheque') {
782 if (!$user->hasRight('banque', 'cheque')) {
783 $deleteok = 0;
784 }
785 } elseif ($feature == 'ecm') {
786 if (!$user->hasRight('ecm', 'upload')) {
787 $deleteok = 0;
788 }
789 } elseif ($feature == 'ftp') {
790 if (!$user->hasRight('ftp', 'write')) {
791 $deleteok = 0;
792 }
793 } elseif ($feature == 'salaries') {
794 if (!$user->hasRight('salaries', 'delete')) {
795 $deleteok = 0;
796 }
797 } elseif ($feature == 'adherent') {
798 if (!$user->hasRight('adherent', 'supprimer')) {
799 $deleteok = 0;
800 }
801 } elseif ($feature == 'paymentbybanktransfer') {
802 if (!$user->hasRight('paymentbybanktransfer', 'create')) { // There is no delete permission
803 $deleteok = 0;
804 }
805 } elseif ($feature == 'prelevement') {
806 if (!$user->hasRight('prelevement', 'bons', 'creer')) { // There is no delete permission
807 $deleteok = 0;
808 }
809 } elseif (!empty($feature2)) { // This is for permissions on 2 levels
810 foreach ($feature2 as $subfeature) {
811 if (!$user->hasRight($feature, $subfeature, 'supprimer') && !$user->hasRight($feature, $subfeature, 'delete')) {
812 $deleteok = 0;
813 } else {
814 $deleteok = 1;
815 break;
816 } // For bypass the second test if the first is ok
817 }
818 } elseif (!empty($feature)) { // This is used for permissions on 1 level
819 //print '<br>feature='.$feature.' creer='.$user->rights->$feature->supprimer.' write='.$user->rights->$feature->delete;
820 if (!$user->hasRight($feature, 'supprimer')
821 && !$user->hasRight($feature, 'delete')
822 && !$user->hasRight($feature, 'run')) {
823 $deleteok = 0;
824 }
825 }
826 }
827
828 // If a or and at least one ok
829 if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) {
830 $deleteok = 1;
831 }
832
833 if (!$deleteok && !($isdraft && $createok)) {
834 if ($mode) {
835 return 0;
836 } else {
838 }
839 }
840 //print "Delete access is ok";
841 }
842
843 // If we have a particular object to check permissions on, we check if $user has permission
844 // for this given object (link to company, is contact for project, ...)
845 if (!empty($objectid) && $objectid > 0) {
846 $ok = checkUserAccessToObject($user, $featuresarray, $object, $tableandshare, $feature2, $dbt_keyfield, $dbt_select, $parentfortableentity);
847 $params = array('objectid' => $objectid, 'features' => implode(',', $featuresarray), 'features2' => $feature2);
848 //print 'checkUserAccessToObject ok='.$ok;
849 if ($mode) {
850 return $ok ? 1 : 0;
851 } else {
852 if ($ok) {
853 return 1;
854 } else {
855 accessforbidden('', 1, 1, 0, $params);
856 }
857 }
858 }
859
860 return 1;
861}
862
878function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tableandshare = '', $feature2 = '', $dbt_keyfield = '', $dbt_select = 'rowid', $parenttableforentity = '')
879{
880 global $db, $conf;
881
882 if (is_object($object)) {
883 $objectid = $object->id;
884 } else {
885 $objectid = $object; // $objectid can be X or 'X,Y,Z'
886 }
887 $objectid = preg_replace('/[^0-9\.\,]/', '', $objectid); // For the case value is coming from a non sanitized user input
888
889 //dol_syslog("functions.lib:restrictedArea $feature, $objectid, $dbtablename, $feature2, $dbt_socfield, $dbt_select, $isdraft");
890 //print "user_id=".$user->id.", features=".join(',', $featuresarray).", objectid=".$objectid;
891 //print ", tableandshare=".$tableandshare.", dbt_socfield=".$dbt_keyfield.", dbt_select=".$dbt_select."<br>";
892
893 // More parameters
894 $params = explode('&', $tableandshare);
895 $dbtablename = (!empty($params[0]) ? $params[0] : '');
896 $sharedelement = (!empty($params[1]) ? $params[1] : $dbtablename);
897
898 foreach ($featuresarray as $feature) {
899 $sql = '';
900
901 //var_dump($feature);exit;
902
903 // For backward compatibility
904 if ($feature == 'societe' && !empty($feature2) && is_array($feature2) && in_array('contact', $feature2)) {
905 $feature = 'contact';
906 $feature2 = '';
907 }
908 if ($feature == 'member') {
909 $feature = 'adherent';
910 }
911 if ($feature == 'project') {
912 $feature = 'projet';
913 }
914 if ($feature == 'task') {
915 $feature = 'projet_task';
916 }
917 if ($feature == 'eventorganization') {
918 $feature = 'agenda';
919 $dbtablename = 'actioncomm';
920 }
921 if ($feature == 'payment_sc' && empty($parenttableforentity)) {
922 // If we check perm on payment page but $parenttableforentity not defined, we force value on parent table
923 $parenttableforentity = '';
924 $dbtablename = "chargesociales";
925 $feature = "chargesociales";
926 $objectid = $object->fk_charge;
927 }
928
929 $checkonentitydone = 0;
930
931 // Array to define rules of checks to do
932 $check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'payment_sc', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website', 'recruitment', 'chargesociales', 'knowledgemanagement'); // Test on entity only (Objects with no link to company)
933 $checksoc = array('societe'); // Test for object Societe
934 $checkparentsoc = array('agenda', 'contact', 'contrat'); // Test on entity + link to third party on field $dbt_keyfield. Allowed if link is empty (Ex: contacts...).
935 $checkproject = array('projet', 'project'); // Test for project object
936 $checktask = array('projet_task'); // Test for task object
937 $checkhierarchy = array('expensereport', 'holiday'); // check permission among the hierarchy of user
938 $checkuser = array('bookmark'); // check permission among the fk_user (must be myself or null)
939 $nocheck = array('barcode', 'stock'); // No test
940
941 //$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...).
942
943 // If dbtablename not defined, we use same name for table than module name
944 if (empty($dbtablename)) {
945 $dbtablename = $feature;
946 $sharedelement = (!empty($params[1]) ? $params[1] : $dbtablename); // We change dbtablename, so we set sharedelement too.
947 }
948
949 // To avoid an access forbidden with a numeric ref
950 if ($dbt_select != 'rowid' && $dbt_select != 'id') {
951 $objectid = "'".$objectid."'"; // Note: $objectid was already cast into int at begin of this method.
952 }
953 // Check permission for objectid on entity only
954 if (in_array($feature, $check) && $objectid > 0) { // For $objectid = 0, no check
955 $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
956 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
957 if (($feature == 'user' || $feature == 'usergroup') && isModEnabled('multicompany')) { // Special for multicompany
958 if (getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
959 if ($conf->entity == 1 && $user->admin && !$user->entity) {
960 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
961 $sql .= " AND dbt.entity IS NOT NULL";
962 } else {
963 $sql .= ",".MAIN_DB_PREFIX."usergroup_user as ug";
964 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
965 $sql .= " AND ((ug.fk_user = dbt.rowid";
966 $sql .= " AND ug.entity IN (".getEntity('usergroup')."))";
967 $sql .= " OR dbt.entity = 0)"; // Show always superadmin
968 }
969 } else {
970 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
971 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
972 }
973 } else {
974 $reg = array();
975 if ($parenttableforentity && preg_match('/(.*)@(.*)/', $parenttableforentity, $reg)) {
976 $sql .= ", ".MAIN_DB_PREFIX.$reg[2]." as dbtp";
977 $sql .= " WHERE dbt.".$reg[1]." = dbtp.rowid AND dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
978 $sql .= " AND dbtp.entity IN (".getEntity($sharedelement, 1).")";
979 } else {
980 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
981 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
982 }
983 }
984 $checkonentitydone = 1;
985 }
986 if (in_array($feature, $checksoc) && $objectid > 0) { // We check feature = checksoc. For $objectid = 0, no check
987 // If external user: Check permission for external users
988 if ($user->socid > 0) {
989 if ($user->socid != $objectid) {
990 return false;
991 }
992 } elseif (isModEnabled("societe") && ($user->hasRight('societe', 'lire') && !$user->hasRight('societe', 'client', 'voir'))) {
993 // If internal user: Check permission for internal users that are restricted on their objects
994 $sql = "SELECT COUNT(sc.fk_soc) as nb";
995 $sql .= " FROM (".MAIN_DB_PREFIX."societe_commerciaux as sc";
996 $sql .= ", ".MAIN_DB_PREFIX."societe as s)";
997 $sql .= " WHERE sc.fk_soc IN (".$db->sanitize($objectid, 1).")";
998 $sql .= " AND (sc.fk_user = ".((int) $user->id);
999 if (getDolGlobalInt('MAIN_SEE_SUBORDINATES')) {
1000 $userschilds = $user->getAllChildIds();
1001 $sql .= " OR sc.fk_user IN (".$db->sanitize(implode(',', $userschilds)).")";
1002 }
1003 $sql .= ")";
1004 $sql .= " AND sc.fk_soc = s.rowid";
1005 $sql .= " AND s.entity IN (".getEntity($sharedelement, 1).")";
1006 } elseif (isModEnabled('multicompany')) {
1007 // If multicompany and internal users with all permissions, check user is in correct entity
1008 $sql = "SELECT COUNT(s.rowid) as nb";
1009 $sql .= " FROM ".MAIN_DB_PREFIX."societe as s";
1010 $sql .= " WHERE s.rowid IN (".$db->sanitize($objectid, 1).")";
1011 $sql .= " AND s.entity IN (".getEntity($sharedelement, 1).")";
1012 }
1013
1014 $checkonentitydone = 1;
1015 }
1016 if (in_array($feature, $checkparentsoc) && $objectid > 0) { // Test on entity + link to thirdparty. Allowed if link is empty (Ex: contacts...).
1017 // If external user: Check permission for external users
1018 if ($user->socid > 0) {
1019 $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
1020 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
1021 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
1022 $sql .= " AND dbt.fk_soc = ".((int) $user->socid);
1023 } elseif (isModEnabled("societe") && ($user->hasRight('societe', 'lire') && !$user->hasRight('societe', 'client', 'voir'))) {
1024 // If internal user: Check permission for internal users that are restricted on their objects
1025 $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
1026 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
1027 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON dbt.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
1028 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
1029 $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
1030 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
1031 } elseif (isModEnabled('multicompany')) {
1032 // If multicompany and internal users with all permissions, check user is in correct entity
1033 $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
1034 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
1035 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
1036 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
1037 }
1038
1039 $checkonentitydone = 1;
1040 }
1041 if (in_array($feature, $checkproject) && $objectid > 0) {
1042 if (isModEnabled('project') && !$user->hasRight('projet', 'all', 'lire')) {
1043 $projectid = $objectid;
1044
1045 include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
1046 $projectstatic = new Project($db);
1047 $tmps = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, 0);
1048
1049 $tmparray = explode(',', $tmps);
1050 if (!in_array($projectid, $tmparray)) {
1051 return false;
1052 }
1053 } else {
1054 $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
1055 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
1056 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
1057 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
1058 }
1059 $checkonentitydone = 1;
1060 }
1061 if (in_array($feature, $checktask) && $objectid > 0) {
1062 if (isModEnabled('project') && !$user->hasRight('projet', 'all', 'lire')) {
1063 $task = new Task($db);
1064 $task->fetch($objectid);
1065 $projectid = $task->fk_project;
1066
1067 include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
1068 $projectstatic = new Project($db);
1069 $tmps = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, 0);
1070
1071 $tmparray = explode(',', $tmps);
1072 if (!in_array($projectid, $tmparray)) {
1073 return false;
1074 }
1075 } else {
1076 $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
1077 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
1078 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
1079 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
1080 }
1081
1082 $checkonentitydone = 1;
1083 }
1084 //var_dump($sql);
1085
1086 if (!$checkonentitydone && !in_array($feature, $nocheck) && $objectid > 0) { // By default (case of $checkdefault), we check on object entity + link to third party on field $dbt_keyfield
1087 // If external user: Check permission for external users
1088 if ($user->socid > 0) {
1089 if (empty($dbt_keyfield)) {
1090 dol_print_error(null, 'Param dbt_keyfield is required but not defined');
1091 }
1092 $sql = "SELECT COUNT(dbt.".$dbt_keyfield.") as nb";
1093 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
1094 $sql .= " WHERE dbt.rowid IN (".$db->sanitize($objectid, 1).")";
1095 $sql .= " AND dbt.".$dbt_keyfield." = ".((int) $user->socid);
1096 } elseif (isModEnabled("societe") && !$user->hasRight('societe', 'client', 'voir')) {
1097 // If internal user without permission to see all thirdparties: Check permission for internal users that are restricted on their objects
1098 if ($feature != 'ticket') {
1099 if (empty($dbt_keyfield)) {
1100 dol_print_error(null, 'Param dbt_keyfield is required but not defined');
1101 }
1102 $sql = "SELECT COUNT(sc.fk_soc) as nb";
1103 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
1104 $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
1105 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
1106 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
1107 $sql .= " AND sc.fk_soc = dbt.".$dbt_keyfield;
1108 $sql .= " AND (sc.fk_user = ".((int) $user->id);
1109 if (getDolGlobalInt('MAIN_SEE_SUBORDINATES')) {
1110 $userschilds = $user->getAllChildIds();
1111 foreach ($userschilds as $key => $value) {
1112 $sql .= ' OR sc.fk_user = '.((int) $value);
1113 }
1114 }
1115 $sql .= ')';
1116 } else {
1117 // On ticket, the thirdparty is not mandatory, so we need a special test to accept record with no thirdparties.
1118 $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
1119 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
1120 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON sc.fk_soc = dbt.".$dbt_keyfield." AND sc.fk_user = ".((int) $user->id);
1121 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
1122 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
1123 $sql .= " AND (sc.fk_user = ".((int) $user->id)." OR sc.fk_user IS NULL)";
1124 }
1125 } elseif (isModEnabled('multicompany')) {
1126 // If multicompany, and user is an internal user with all permissions, check that object is in correct entity
1127 $sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
1128 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
1129 $sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
1130 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
1131 }
1132 }
1133
1134 // For events, check on users assigned to event
1135 if ($feature === 'agenda' && $objectid > 0) {
1136 // Also check owner or attendee for users without allactions->read
1137 if ($objectid > 0 && !$user->hasRight('agenda', 'allactions', 'read')) {
1138 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
1139 $action = new ActionComm($db);
1140 $action->fetch($objectid);
1141 if ($action->authorid != $user->id && $action->userownerid != $user->id && !(array_key_exists($user->id, $action->userassigned))) {
1142 return false;
1143 }
1144 }
1145 }
1146
1147 // For some object, we also have to check it is in the user hierarchy
1148 // Param $object must be the full object and not a simple id to have this test possible.
1149 if (in_array($feature, $checkhierarchy) && is_object($object) && $objectid > 0) {
1150 $childids = $user->getAllChildIds(1);
1151 $useridtocheck = 0;
1152 if ($feature == 'holiday') {
1153 $useridtocheck = $object->fk_user;
1154 if (!$user->hasRight('holiday', 'readall') && !in_array($useridtocheck, $childids) && !in_array($object->fk_validator, $childids)) {
1155 return false;
1156 }
1157 }
1158 if ($feature == 'expensereport') {
1159 $useridtocheck = $object->fk_user_author;
1160 if (!$user->hasRight('expensereport', 'readall')) {
1161 if (!in_array($useridtocheck, $childids)) {
1162 return false;
1163 }
1164 }
1165 }
1166 }
1167
1168 // For some object, we also have to check it is public or owned by user
1169 // Param $object must be the full object and not a simple id to have this test possible.
1170 if (in_array($feature, $checkuser) && is_object($object) && $objectid > 0) {
1171 $useridtocheck = $object->fk_user;
1172 if (!empty($useridtocheck) && $useridtocheck > 0 && $useridtocheck != $user->id && empty($user->admin)) {
1173 return false;
1174 }
1175 }
1176
1177 if ($sql) {
1178 $resql = $db->query($sql);
1179 if ($resql) {
1180 $obj = $db->fetch_object($resql);
1181 if (!$obj || $obj->nb < count(explode(',', $objectid))) { // error if we found 0 or less record than nb of id provided
1182 return false;
1183 }
1184 } else {
1185 dol_syslog("Bad forged sql in checkUserAccessToObject", LOG_WARNING);
1186 return false;
1187 }
1188 }
1189 }
1190
1191 return true;
1192}
1193
1194
1206function httponly_accessforbidden($message = '1', $http_response_code = 403, $stringalreadysanitized = 0)
1207{
1208 top_httphead();
1209 http_response_code($http_response_code);
1210
1211 if ($stringalreadysanitized) {
1212 print $message;
1213 } else {
1214 print htmlentities($message);
1215 }
1216
1217 exit(1);
1218}
1219
1233function accessforbidden($message = '', $printheader = 1, $printfooter = 1, $showonlymessage = 0, $params = null)
1234{
1235 global $conf, $db, $user, $langs, $hookmanager;
1236 global $action, $object;
1237
1238 if (!is_object($langs)) {
1239 include_once DOL_DOCUMENT_ROOT.'/core/class/translate.class.php';
1240 $langs = new Translate('', $conf);
1241 $langs->setDefaultLang();
1242 }
1243
1244 $langs->loadLangs(array("main", "errors"));
1245
1246 if ($printheader && !defined('NOHEADERNOFOOTER')) {
1247 if (function_exists("llxHeader")) {
1248 llxHeader('');
1249 } elseif (function_exists("llxHeaderVierge")) {
1250 llxHeaderVierge('');
1251 }
1252 print '<div style="padding: 20px">';
1253 }
1254 print '<div class="error">';
1255 if (empty($message)) {
1256 print $langs->trans("ErrorForbidden");
1257 } else {
1258 print $langs->trans($message);
1259 }
1260 print '</div>';
1261 print '<br>';
1262 if (empty($showonlymessage)) {
1263 if (empty($hookmanager)) {
1264 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
1265 $hookmanager = new HookManager($db);
1266 // Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
1267 $hookmanager->initHooks(array('main'));
1268 }
1269
1270 $parameters = array('message' => $message, 'params' => $params);
1271 $reshook = $hookmanager->executeHooks('getAccessForbiddenMessage', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1272 print $hookmanager->resPrint;
1273 if (empty($reshook)) {
1274 $langs->loadLangs(array("errors"));
1275 if ($user->login) {
1276 print $langs->trans("CurrentLogin").': <span class="error">'.$user->login.'</span><br>';
1277 print $langs->trans("ErrorForbidden2", $langs->transnoentitiesnoconv("Home"), $langs->transnoentitiesnoconv("Users"));
1278 print $langs->trans("ErrorForbidden4");
1279 } else {
1280 print $langs->trans("ErrorForbidden3");
1281 }
1282 }
1283 }
1284 if ($printfooter && !defined('NOHEADERNOFOOTER') && function_exists("llxFooter")) {
1285 print '</div>';
1286 llxFooter();
1287 }
1288
1289 exit(0);
1290}
1291
1292
1300{
1301 $max = getDolGlobalString('MAIN_UPLOAD_DOC'); // In Kb
1302
1303 $maxphp = @ini_get('upload_max_filesize'); // In unknown
1304 if (preg_match('/k$/i', $maxphp)) {
1305 $maxphp = preg_replace('/k$/i', '', $maxphp);
1306 $maxphp = (int) ((float) $maxphp * 1);
1307 }
1308 if (preg_match('/m$/i', $maxphp)) {
1309 $maxphp = preg_replace('/m$/i', '', $maxphp);
1310 $maxphp = (int) ((float) $maxphp * 1024);
1311 }
1312 if (preg_match('/g$/i', $maxphp)) {
1313 $maxphp = preg_replace('/g$/i', '', $maxphp);
1314 $maxphp = (int) ((float) $maxphp * 1024 * 1024);
1315 }
1316 if (preg_match('/t$/i', $maxphp)) {
1317 $maxphp = preg_replace('/t$/i', '', $maxphp);
1318 $maxphp = (int) ((float) $maxphp * 1024 * 1024 * 1024);
1319 }
1320 $maxphp2 = @ini_get('post_max_size'); // In unknown
1321 if (preg_match('/k$/i', $maxphp2)) {
1322 $maxphp2 = preg_replace('/k$/i', '', $maxphp2);
1323 $maxphp2 = (int) ((float) $maxphp2) * 1;
1324 }
1325 if (preg_match('/m$/i', $maxphp2)) {
1326 $maxphp2 = preg_replace('/m$/i', '', $maxphp2);
1327 $maxphp2 = (int) ((float) $maxphp2 * 1024);
1328 }
1329 if (preg_match('/g$/i', $maxphp2)) {
1330 $maxphp2 = preg_replace('/g$/i', '', $maxphp2);
1331 $maxphp2 = (int) ((float) $maxphp2 * 1024 * 1024);
1332 }
1333 if (preg_match('/t$/i', $maxphp2)) {
1334 $maxphp2 = preg_replace('/t$/i', '', $maxphp2);
1335 $maxphp2 = (int) ((float) $maxphp2 * 1024 * 1024 * 1024);
1336 }
1337 // Now $max and $maxphp and $maxphp2 are in Kb
1338 $maxmin = $max;
1339 $maxphptoshow = $maxphptoshowparam = '';
1340 if ($maxphp > 0) {
1341 $maxmin = min($maxmin, $maxphp);
1342 $maxphptoshow = $maxphp;
1343 $maxphptoshowparam = 'upload_max_filesize';
1344 }
1345 if ($maxphp2 > 0) {
1346 $maxmin = min($maxmin, $maxphp2);
1347 if ($maxphp2 < $maxphp) {
1348 $maxphptoshow = $maxphp2;
1349 $maxphptoshowparam = 'post_max_size';
1350 }
1351 }
1352 //var_dump($maxphp.'-'.$maxphp2);
1353 //var_dump($maxmin);
1354
1355 return array('max' => $max, 'maxmin' => $maxmin, 'maxphptoshow' => $maxphptoshow, 'maxphptoshowparam' => $maxphptoshowparam);
1356}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
if(!defined( 'NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined( 'NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) if(!defined( 'NOLOGIN')) if(!defined('NOCSRFCHECK')) if(!defined( 'NOIPCHECK')) llxHeaderVierge($title, $head="", $disablejs=0, $disablehead=0, $arrayofjs=[], $arrayofcss=[])
Header function.
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:87
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:71
Class to manage agenda events (actions)
Class to manage hooks.
Class to manage projects.
Class to manage tasks.
Class to manage translations.
Class to manage Dolibarr users.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_substr($string, $start, $length=null, $stringencoding='', $trunconbytes=0)
Make a substring.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
if(!defined( 'NOREQUIREMENU')) if(!empty(GETPOST('seteventmessages', 'alpha'))) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
dolGetRandomBytes($length)
Return a string of random bytes (hexa string) with length = $length for cryptographic purposes.
httponly_accessforbidden($message='1', $http_response_code=403, $stringalreadysanitized=0)
Show a message to say access is forbidden and stop program.
dol_encode($chain, $key='1')
Encode a string with base 64 algorithm + specific delta change.
checkUserAccessToObject($user, array $featuresarray, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='', $dbt_select='rowid', $parenttableforentity='')
Check that access by a given user to an object is ok.
dol_verifyHash($chain, $hash, $type='0')
Compute a hash and compare it to the given one For backward compatibility reasons,...
dolEncrypt($chain, $key='', $ciphering='', $forceseed='')
Encode a string with a symmetric encryption.
getMaxFileSizeArray()
Return the max allowed for file upload.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
dol_decode($chain, $key='1')
Decode a base 64 encoded + specific delta change.
dolGetLdapPasswordHash($password, $type='md5')
Returns a specific ldap hash of a password.
dolDecrypt($chain, $key='')
Decode a string with a symmetric encryption.
dol_hash($chain, $type='0', $nosalt=0)
Returns a hash (non reversible encryption) of a string.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.