dolibarr 21.0.0-alpha
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:58
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.
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:70
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.
llxFooter()
Footer empty.
Definition document.php:107
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.
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.