dolibarr 24.0.0-beta
security.lib.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (C) 2008-2021 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2008-2021 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2020 Ferran Marcet <fmarcet@2byte.es>
6 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
7 * Copyright (C) 2025 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2026 William Mead <william@m34d.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 * or see https://www.gnu.org/
23 */
24
33include_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/securitycore.lib.php';
34
35
44function dol_encode($chain, $key = '1')
45{
46 if (is_numeric($key) && $key == '1') { // rule 1 is offset of 17 for char
47 $output_tab = array();
48 $strlength = dol_strlen($chain);
49 for ($i = 0; $i < $strlength; $i++) {
50 $output_tab[$i] = chr(ord(substr($chain, $i, 1)) + 17);
51 }
52 $chain = implode("", $output_tab);
53 } elseif ($key) {
54 $result = '';
55 $strlength = dol_strlen($chain);
56 for ($i = 0; $i < $strlength; $i++) {
57 $keychar = substr($key, ($i % strlen($key)) - 1, 1);
58 $result .= chr(ord(substr($chain, $i, 1)) + (ord($keychar) - 65));
59 }
60 $chain = $result;
61 }
62
63 return base64_encode($chain);
64}
65
75function dol_decode($chain, $key = '1')
76{
77 $chain = base64_decode($chain);
78
79 if (is_numeric($key) && $key == '1') { // rule 1 is offset of 17 for char
80 $output_tab = array();
81 $strlength = dol_strlen($chain);
82 for ($i = 0; $i < $strlength; $i++) {
83 $output_tab[$i] = chr(ord(substr($chain, $i, 1)) - 17);
84 }
85
86 $chain = implode("", $output_tab);
87 } elseif ($key) {
88 $result = '';
89 $strlength = dol_strlen($chain);
90 for ($i = 0; $i < $strlength; $i++) {
91 $keychar = substr($key, ($i % strlen($key)) - 1, 1);
92 $result .= chr(ord(substr($chain, $i, 1)) - (ord($keychar) - 65));
93 }
94 $chain = $result;
95 }
96
97 return $chain;
98}
99
106function dolGetRandomBytes($length)
107{
108 if (function_exists('random_bytes')) { // Available with PHP 7+ only.
109 return bin2hex(random_bytes((int) floor($length / 2))); // the bin2hex will double the number of bytes so we take length / 2
110 }
111
112 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.
113}
114
122function dolGetLdapPasswordHash($password, $type = 'md5')
123{
124 if (empty($type)) {
125 $type = 'md5';
126 }
127
128 $salt = substr(sha1((string) time()), 0, 8);
129
130 if ($type === 'md5') {
131 return '{MD5}' . base64_encode(hash("md5", $password, true)); //For OpenLdap with md5 (based on an unencrypted password in base)
132 } elseif ($type === 'md5frommd5') {
133 return '{MD5}' . base64_encode(hex2bin($password)); // Create OpenLDAP MD5 password from Dolibarr MD5 password
134 } elseif ($type === 'smd5') {
135 return "{SMD5}" . base64_encode(hash("md5", $password . $salt, true) . $salt);
136 } elseif ($type === 'sha') {
137 return '{SHA}' . base64_encode(hash("sha1", $password, true));
138 } elseif ($type === 'ssha') {
139 return "{SSHA}" . base64_encode(hash("sha1", $password . $salt, true) . $salt);
140 } elseif ($type === 'sha256') {
141 return "{SHA256}" . base64_encode(hash("sha256", $password, true));
142 } elseif ($type === 'ssha256') {
143 return "{SSHA256}" . base64_encode(hash("sha256", $password . $salt, true) . $salt);
144 } elseif ($type === 'sha384') {
145 return "{SHA384}" . base64_encode(hash("sha384", $password, true));
146 } elseif ($type === 'ssha384') {
147 return "{SSHA384}" . base64_encode(hash("sha384", $password . $salt, true) . $salt);
148 } elseif ($type === 'sha512') {
149 return "{SHA512}" . base64_encode(hash("sha512", $password, true));
150 } elseif ($type === 'ssha512') {
151 return "{SSHA512}" . base64_encode(hash("sha512", $password . $salt, true) . $salt);
152 } elseif ($type === 'crypt') {
153 return '{CRYPT}' . crypt($password, $salt);
154 } elseif ($type === 'clear') {
155 return '{CLEAR}' . $password; // Just for test, plain text password is not secured !
156 }
157 return "";
158}
159
180function restrictedArea(User $user, $features, $object = 0, $tableandshare = '', $feature2 = '', $dbt_keyfield = 'fk_soc', $dbt_select = 'rowid', $isdraft = 0, $mode = 0)
181{
182 global $hookmanager;
183
184 // Define $objectid
185 if (is_object($object)) {
186 $objectid = $object->id;
187 } else {
188 $objectid = $object; // $objectid can be X or 'X,Y,Z'
189 }
190 if ($objectid == "-1") {
191 $objectid = 0;
192 }
193 if ($objectid) {
194 $objectid = preg_replace('/[^0-9\.\,]/', '', (string) $objectid); // For the case value is coming from a non sanitized user input
195 }
196
197 //dol_syslog("functions.lib:restrictedArea $feature, $objectid, $dbtablename, $feature2, $dbt_socfield, $dbt_select, $isdraft");
198 /*print "user_id=".$user->id.", features=".$features.", feature2=".$feature2.", objectid=".$objectid;
199 print ", dbtablename=".$tableandshare.", dbt_socfield=".$dbt_keyfield.", dbt_select=".$dbt_select;
200 print ", perm: user->hasRight(".$features.($feature2 ? ",".$feature2 : "").", lire) = ".($feature2 ? $user->hasRight($features, $feature2, 'lire') : $user->hasRight($features, 'lire'))."<br>";
201 */
202
203 $parentfortableentity = '';
204
205 // Fix syntax of $features param to support non standard module names.
206 // @todo : use elseif ?
207 $originalfeatures = $features;
208 if ($features == 'agenda') {
209 $tableandshare = 'actioncomm&societe';
210 $feature2 = 'myactions|allactions';
211 $dbt_select = 'id';
212 }
213 if ($features == 'bank') {
214 $features = 'banque';
215 }
216 if ($features == 'facturerec') {
217 $features = 'facture';
218 }
219 if ($features == 'supplier_invoicerec') {
220 $features = 'fournisseur';
221 $feature2 = 'facture';
222 }
223 if ($features == 'mo') {
224 $features = 'mrp';
225 }
226 if ($features == 'member') {
227 $features = 'adherent';
228 }
229 if ($features == 'subscription') {
230 $features = 'adherent';
231 $feature2 = 'cotisation';
232 }
233 if ($features == 'website' && is_object($object) && $object->element == 'websitepage') {
234 $parentfortableentity = 'fk_website@website';
235 }
236 if ($features == 'project') {
237 $features = 'projet';
238 }
239 if ($features == 'product') {
240 $features = 'produit';
241 }
242 if ($features == 'productbatch') {
243 $features = 'produit';
244 }
245 if ($features == 'tax') {
246 $feature2 = 'charges';
247 }
248 if ($features == 'workstation') {
249 $feature2 = 'workstation';
250 }
251 if ($features == 'fournisseur') { // When vendor invoice and purchase order are into module 'fournisseur'
252 $features = 'fournisseur';
253 if (is_object($object) && $object->element == 'invoice_supplier') {
254 $feature2 = 'facture';
255 } elseif (is_object($object) && $object->element == 'order_supplier') {
256 $feature2 = 'commande';
257 }
258 }
259 if ($features == 'payment_sc') {
260 $tableandshare = 'paiementcharge';
261 $parentfortableentity = 'fk_charge@chargesociales';
262 }
263
264 // if commonObjectLine : Using many2one related commonObject
265 // @see commonObjectLine::parentElement
266 if (in_array($features, ['commandedet', 'propaldet', 'facturedet', 'supplier_proposaldet', 'evaluationdet', 'skilldet', 'deliverydet', 'contratdet'])) {
267 $features = substr($features, 0, -3);
268 } elseif (in_array($features, ['stocktransferline', 'inventoryline', 'bomline', 'expensereport_det', 'facture_fourn_det'])) {
269 $features = substr($features, 0, -4);
270 } elseif ($features == 'commandefournisseurdispatch') {
271 $features = 'commandefournisseur';
272 } elseif ($features == 'invoice_supplier_det_rec') {
273 $features = 'invoice_supplier_rec';
274 }
275 if ($features == 'evaluation') {
276 $features = 'hrm';
277 $feature2 = 'evaluation';
278 }
279
280 // When the object is a task (element='project_task') and $feature2 is empty,
281 // $checkUserAccessToObject() falls into the $checkproject path and uses the task ID
282 // as project ID, which always fails. Setting $feature2='project_task' triggers the
283 // normalization at line 974 that redirects to the $checktask path, which correctly
284 // resolves $task->fk_project before calling getProjectsAuthorizedForUser().
285 if (is_object($object) && in_array($object->element, array('project_task', 'task'))
286 && (empty($features) || in_array($features, array('projet', 'project')))
287 && empty($feature2)) {
288 $features = 'projet';
289 $feature2 = 'project_task';
290 if (empty($tableandshare)) {
291 $tableandshare = 'projet_task';
292 }
293 }
294
295 // print $features.' - '.$tableandshare.' - '.$feature2.' - '.$dbt_select."\n";
296
297 // Get more permissions checks from hooks
298 $parameters = array(
299 'features' => $features,
300 'feature2' => $feature2,
301 'originalfeatures' => $originalfeatures,
302 'tableandshare' => $tableandshare,
303 'object' => $object,
304 'objectid' => $objectid,
305 'dbt_keyfield' => $dbt_keyfield,
306 'dbt_select' => $dbt_select,
307 'idtype' => $dbt_select,
308 'isdraft' => $isdraft,
309 'mode' => $mode,
310 );
311 if (!empty($hookmanager)) {
312 $reshook = $hookmanager->executeHooks('restrictedArea', $parameters);
313
314 if (isset($hookmanager->resArray['result'])) {
315 if ($hookmanager->resArray['result'] == 0) {
316 if ($mode) {
317 return 0;
318 } else {
319 accessforbidden(); // Module returns 0, so access forbidden
320 }
321 }
322 }
323 if ($reshook > 0) { // No other test done.
324 return 1;
325 }
326 }
327
328 // Features/modules to check (to support the & and | operator)
329 $featuresarray = array($features);
330 if (preg_match('/&/', $features)) {
331 $featuresarray = explode("&", $features);
332 } elseif (preg_match('/\|/', $features)) {
333 $featuresarray = explode("|", $features);
334 }
335
336 // More subfeatures to check
337 if (!empty($feature2)) {
338 $feature2 = explode("|", $feature2);
339 }
340
341 $listofmodules = explode(',', getDolGlobalString('MAIN_MODULES_FOR_EXTERNAL'));
342
343 // Check read permission from module
344 $readok = 1;
345 $nbko = 0;
346 foreach ($featuresarray as $feature) { // first we check nb of test ko
347 $featureforlistofmodule = $feature;
348 if ($featureforlistofmodule == 'produit') {
349 $featureforlistofmodule = 'product';
350 }
351 if ($featureforlistofmodule == 'supplier_proposal') {
352 $featureforlistofmodule = 'supplierproposal';
353 }
354 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
355 $readok = 0;
356 $nbko++;
357 continue;
358 }
359
360 if ($feature == 'societe' && (empty($feature2) || !in_array('contact', $feature2))) {
361 if (!$user->hasRight('societe', 'lire') && !$user->hasRight('fournisseur', 'lire')) {
362 $readok = 0;
363 $nbko++;
364 }
365 } elseif (($feature == 'societe' && (!empty($feature2) && in_array('contact', $feature2))) || $feature == 'contact') {
366 if (!$user->hasRight('societe', 'contact', 'lire')) {
367 $readok = 0;
368 $nbko++;
369 }
370 } elseif ($feature == 'produit|service') {
371 if (!$user->hasRight('produit', 'lire') && !$user->hasRight('service', 'lire')) {
372 $readok = 0;
373 $nbko++;
374 }
375 } elseif ($feature == 'prelevement') {
376 if (!$user->hasRight('prelevement', 'bons', 'lire')) {
377 $readok = 0;
378 $nbko++;
379 }
380 } elseif ($feature == 'cheque') {
381 if (!$user->hasRight('banque', 'cheque')) {
382 $readok = 0;
383 $nbko++;
384 }
385 } elseif ($feature == 'projet') {
386 if (!$user->hasRight('projet', 'lire') && !$user->hasRight('projet', 'all', 'lire')) {
387 $readok = 0;
388 $nbko++;
389 }
390 } elseif ($feature == 'payment') {
391 if (!$user->hasRight('facture', 'lire')) {
392 $readok = 0;
393 $nbko++;
394 }
395 } elseif ($feature == 'payment_supplier') {
396 if (!$user->hasRight('fournisseur', 'facture', 'lire')) {
397 $readok = 0;
398 $nbko++;
399 }
400 } elseif ($feature == 'payment_sc') {
401 if (!$user->hasRight('tax', 'charges', 'lire')) {
402 $readok = 0;
403 $nbko++;
404 }
405 } elseif ($feature == 'webhook') {
406 if (empty($user->admin)) {
407 $readok = 0;
408 $nbko++;
409 }
410 } elseif (!empty($feature2)) { // This is for permissions on 2 levels (module->object->read)
411 $tmpreadok = 1;
412 foreach ($feature2 as $subfeature) {
413 if ($subfeature == 'user' && $user->id == $objectid) {
414 continue; // A user can always read its own card
415 }
416 if ($subfeature == 'fiscalyear' && $user->hasRight('accounting', 'fiscalyear', 'write')) {
417 // only one right for fiscalyear
418 $tmpreadok = 1;
419 continue;
420 }
421 if (!empty($subfeature) && !$user->hasRight($feature, $subfeature, 'lire') && !$user->hasRight($feature, $subfeature, 'read')) {
422 $tmpreadok = 0;
423 } elseif (empty($subfeature) && !$user->hasRight($feature, 'lire') && !$user->hasRight($feature, 'read')) {
424 $tmpreadok = 0;
425 } else {
426 $tmpreadok = 1;
427 break;
428 } // Break is to bypass second test if the first is ok
429 }
430 if (!$tmpreadok) { // We found a test on feature that is ko
431 $readok = 0; // All tests are ko (we manage here the and, the or will be managed later using $nbko).
432 $nbko++;
433 }
434 } elseif (!empty($feature) && ($feature != 'user' && $feature != 'usergroup')) { // This is permissions on 1 level (module->read)
435 if (!$user->hasRight($feature, 'lire')
436 && !$user->hasRight($feature, 'read')
437 && !$user->hasRight($feature, 'run')) {
438 $readok = 0;
439 $nbko++;
440 }
441 }
442 }
443
444 // If a or and at least one ok
445 if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) {
446 $readok = 1;
447 }
448
449 if (!$readok) {
450 if ($mode) {
451 return 0;
452 } else {
454 }
455 }
456 //print "Read access is ok";
457
458 // Check write permission from module (we need to know write permission to create but also to delete drafts record or to upload files)
459 $createok = 1;
460 $nbko = 0;
461 $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));
462 $wemustcheckpermissionfordeletedraft = ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete');
463
464 if ($wemustcheckpermissionforcreate || $wemustcheckpermissionfordeletedraft) {
465 foreach ($featuresarray as $feature) {
466 if ($feature == 'contact') {
467 if (!$user->hasRight('societe', 'contact', 'creer')) {
468 $createok = 0;
469 $nbko++;
470 }
471 } elseif ($feature == 'produit|service') {
472 if (!$user->hasRight('produit', 'creer') && !$user->hasRight('service', 'creer')) {
473 $createok = 0;
474 $nbko++;
475 }
476 } elseif ($feature == 'prelevement') {
477 if (!$user->hasRight('prelevement', 'bons', 'creer')) {
478 $createok = 0;
479 $nbko++;
480 }
481 } elseif ($feature == 'commande_fournisseur') {
482 if (!$user->hasRight('fournisseur', 'commande', 'creer') || !$user->hasRight('supplier_order', 'creer')) {
483 $createok = 0;
484 $nbko++;
485 }
486 } elseif ($feature == 'banque') {
487 if (!$user->hasRight('banque', 'modifier')) {
488 $createok = 0;
489 $nbko++;
490 }
491 } elseif ($feature == 'cheque') {
492 if (!$user->hasRight('banque', 'cheque')) {
493 $createok = 0;
494 $nbko++;
495 }
496 } elseif ($feature == 'import') {
497 if (!$user->hasRight('import', 'run')) {
498 $createok = 0;
499 $nbko++;
500 }
501 } elseif ($feature == 'ecm') {
502 if (!$user->hasRight('ecm', 'upload')) {
503 $createok = 0;
504 $nbko++;
505 }
506 } elseif ($feature == 'modulebuilder') {
507 if (!$user->hasRight('modulebuilder', 'run')) {
508 $createok = 0;
509 $nbko++;
510 }
511 } elseif ($feature == 'webhook') {
512 if (empty($user->admin)) {
513 $createok = 0;
514 $nbko++;
515 }
516 } elseif (!empty($feature2)) { // This is for permissions on 2 levels (module->object->write)
517 foreach ($feature2 as $subfeature) {
518 if ($subfeature == 'user' && $user->id == $objectid && $user->hasRight('user', 'self', 'creer')) {
519 continue; // User can edit its own card
520 }
521 if ($subfeature == 'user' && $user->id == $objectid && $user->hasRight('user', 'self', 'password')) {
522 continue; // User can edit its own password
523 }
524 if ($subfeature == 'user' && $user->id != $objectid && $user->hasRight('user', 'user', 'password')) {
525 continue; // User can edit another user's password
526 }
527
528 if (!$user->hasRight($feature, $subfeature, 'creer')
529 && !$user->hasRight($feature, $subfeature, 'write')
530 && !$user->hasRight($feature, $subfeature, 'create')) {
531 $createok = 0;
532 $nbko++;
533 } else {
534 $createok = 1;
535 // Break to bypass second test if the first is ok
536 break;
537 }
538 }
539 } elseif (!empty($feature)) { // This is for permissions on 1 levels (module->write)
540 //print '<br>feature='.$feature.' creer='.$user->rights->$feature->creer.' write='.$user->rights->$feature->write; exit;
541 if (!$user->hasRight($feature, 'creer')
542 && !$user->hasRight($feature, 'write')
543 && !$user->hasRight($feature, 'create')) {
544 $createok = 0;
545 $nbko++;
546 }
547 }
548 }
549
550 // If a or and at least one ok
551 if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) {
552 $createok = 1;
553 }
554
555 if ($wemustcheckpermissionforcreate && !$createok) {
556 if ($mode) {
557 return 0;
558 } else {
560 }
561 }
562 //print "Write access is ok";
563 }
564
565 // Check create user permission
566 $createuserok = 1;
567 if (GETPOST('action', 'aZ09') == 'confirm_create_user' && GETPOST("confirm", 'aZ09') == 'yes') {
568 if (!$user->hasRight('user', 'user', 'creer')) {
569 $createuserok = 0;
570 }
571
572 if (!$createuserok) {
573 if ($mode) {
574 return 0;
575 } else {
577 }
578 }
579 //print "Create user access is ok";
580 }
581
582 // Check delete permission from module
583 $deleteok = 1;
584 $nbko = 0;
585 if ((GETPOST("action", "aZ09") == 'confirm_delete' && GETPOST("confirm", "aZ09") == 'yes') || GETPOST("action", "aZ09") == 'delete') {
586 foreach ($featuresarray as $feature) {
587 if ($feature == 'bookmark') {
588 if (!$user->hasRight('bookmark', 'supprimer')) {
589 if ($user->id != $object->fk_user || !$user->hasRight('bookmark', 'creer')) {
590 $deleteok = 0;
591 }
592 }
593 } elseif ($feature == 'contact') {
594 if (!$user->hasRight('societe', 'contact', 'supprimer')) {
595 $deleteok = 0;
596 }
597 } elseif ($feature == 'produit|service') {
598 if (!$user->hasRight('produit', 'supprimer') && !$user->hasRight('service', 'supprimer')) {
599 $deleteok = 0;
600 }
601 } elseif ($feature == 'commande_fournisseur') {
602 if (!$user->hasRight('fournisseur', 'commande', 'supprimer')) {
603 $deleteok = 0;
604 }
605 } elseif ($feature == 'payment_supplier') { // Permission to delete a payment of an invoice is permission to edit an invoice.
606 if (!$user->hasRight('fournisseur', 'facture', 'creer')) {
607 $deleteok = 0;
608 }
609 } elseif ($feature == 'payment') {
610 if (!$user->hasRight('facture', 'paiement')) {
611 $deleteok = 0;
612 }
613 } elseif ($feature == 'payment_sc') {
614 if (!$user->hasRight('tax', 'charges', 'creer')) {
615 $deleteok = 0;
616 }
617 } elseif ($feature == 'banque') {
618 if (!$user->hasRight('banque', 'modifier')) {
619 $deleteok = 0;
620 }
621 } elseif ($feature == 'cheque') {
622 if (!$user->hasRight('banque', 'cheque')) {
623 $deleteok = 0;
624 }
625 } elseif ($feature == 'ecm') {
626 if (!$user->hasRight('ecm', 'upload')) {
627 $deleteok = 0;
628 }
629 } elseif ($feature == 'ftp') {
630 if (!$user->hasRight('ftp', 'write')) {
631 $deleteok = 0;
632 }
633 } elseif ($feature == 'salaries') {
634 if (!$user->hasRight('salaries', 'delete')) {
635 $deleteok = 0;
636 }
637 } elseif ($feature == 'adherent') {
638 if (!$user->hasRight('adherent', 'supprimer')) {
639 $deleteok = 0;
640 }
641 } elseif ($feature == 'paymentbybanktransfer') {
642 if (!$user->hasRight('paymentbybanktransfer', 'create')) { // There is no delete permission
643 $deleteok = 0;
644 }
645 } elseif ($feature == 'prelevement') {
646 if (!$user->hasRight('prelevement', 'bons', 'creer')) { // There is no delete permission
647 $deleteok = 0;
648 }
649 } elseif (!empty($feature2)) { // This is for permissions on 2 levels
650 foreach ($feature2 as $subfeature) {
651 if (!$user->hasRight($feature, $subfeature, 'supprimer') && !$user->hasRight($feature, $subfeature, 'delete')) {
652 $deleteok = 0;
653 } else {
654 $deleteok = 1;
655 break;
656 } // For bypass the second test if the first is ok
657 }
658 } elseif (!empty($feature)) { // This is used for permissions on 1 level
659 //print '<br>feature='.$feature.' creer='.$user->rights->$feature->supprimer.' write='.$user->rights->$feature->delete;
660 if (!$user->hasRight($feature, 'supprimer')
661 && !$user->hasRight($feature, 'delete')
662 && !$user->hasRight($feature, 'run')) {
663 $deleteok = 0;
664 }
665 }
666 }
667
668 // If a or and at least one ok
669 if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) {
670 $deleteok = 1;
671 }
672
673 if (!$deleteok && !($isdraft && $createok)) {
674 if ($mode) {
675 return 0;
676 } else {
678 }
679 }
680 //print "Delete access is ok";
681 }
682
683 // If we have a particular object to check permissions on, we check if $user has permission
684 // for this given object (link to company, is contact for project, ...)
685 if (!empty($objectid) && $objectid > 0) {
686 $ok = checkUserAccessToObject($user, $featuresarray, $object, $tableandshare, $feature2, $dbt_keyfield, $dbt_select, $parentfortableentity);
687 $params = array('objectid' => $objectid, 'features' => implode(',', $featuresarray), 'features2' => $feature2);
688 //print 'checkUserAccessToObject ok='.$ok;
689 if ($mode) {
690 return $ok ? 1 : 0;
691 } else {
692 if ($ok) {
693 return 1;
694 } else {
695 accessforbidden('', 1, 1, 0, $params);
696 }
697 }
698 }
699
700 return 1;
701}
702
718function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tableandshare = '', $feature2 = '', $dbt_keyfield = '', $dbt_select = 'rowid', $parenttableforentity = '')
719{
720 global $db, $conf;
721
722 if (is_object($object)) {
723 $objectid = $object->id;
724 } else {
725 $objectid = $object; // $objectid can be X or 'X,Y,Z'
726 }
727 $objectid = preg_replace('/[^0-9\.\,]/', '', $objectid); // For the case value is coming from a non sanitized user input
728
729 //dol_syslog("functions.lib:restrictedArea $feature, $objectid, $dbtablename, $feature2, $dbt_socfield, $dbt_select, $isdraft");
730 //print "user_id=".$user->id.", features=".join(',', $featuresarray).", objectid=".$objectid;
731 //print ", tableandshare=".$tableandshare.", dbt_socfield=".$dbt_keyfield.", dbt_select=".$dbt_select."<br>";
732
733 // More parameters
734 $params = explode('&', $tableandshare);
735 $dbtablename = (!empty($params[0]) ? $params[0] : '');
736 $sharedelement = (!empty($params[1]) ? $params[1] : $dbtablename);
737
738 foreach ($featuresarray as $feature) {
739 $sql = '';
740
741 //var_dump($feature);exit;
742
743 // For backward compatibility
744 if ($feature == 'societe' && !empty($feature2) && is_array($feature2) && in_array('contact', $feature2)) {
745 $feature = 'contact';
746 $feature2 = '';
747 }
748 if ($feature == 'member') {
749 $feature = 'adherent';
750 }
751 if ($feature == 'category') {
752 $feature = 'categorie';
753 }
754 if ($feature == 'project') {
755 $feature = 'projet';
756 }
757 if ($feature == 'projet' && !empty($feature2) && is_array($feature2) && !empty(array_intersect(array('project_task', 'projet_task'), $feature2))) {
758 $feature = 'project_task';
759 }
760 if ($feature == 'task' || $feature == 'projet_task') {
761 $feature = 'project_task';
762 $dbtablename = 'projet_task';
763 }
764 if ($feature == 'eventorganization') {
765 $feature = 'agenda';
766 $dbtablename = 'actioncomm';
767 }
768 if ($feature == 'payment_sc' && empty($parenttableforentity)) {
769 // If we check perm on payment page but $parenttableforentity not defined, we force value on parent table
770 $parenttableforentity = '';
771 $dbtablename = "chargesociales";
772 $feature = "chargesociales";
773 $objectid = $object->fk_charge;
774 }
775
776 $checkonentitydone = 0;
777
778 // Array to define rules of checks to do
779 $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', 'stock'); // Test on entity only (Objects with no link to company)
780 $checksoc = array('societe'); // Test for object Societe
781 $checkparentsoc = array('agenda', 'contact', 'contrat'); // Test on entity + link to third party on field $dbt_keyfield. Allowed if link is empty (Ex: contacts...).
782 $checkproject = array('projet', 'project'); // Test for project object
783 $checktask = array('projet_task', 'project_task'); // Test for task object
784 $checkhierarchy = array('expensereport', 'holiday', 'hrm'); // check permission among the hierarchy of user
785 $checkuser = array('bookmark'); // check permission among the fk_user (must be myself or null)
786 $nocheck = array('barcode', 'webhook'); // No test
787
788 //$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...).
789
790 // If dbtablename not defined, we use same name for table than module name
791 if (empty($dbtablename)) {
792 $dbtablename = $feature;
793 $sharedelement = (!empty($params[1]) ? $params[1] : $dbtablename); // We change dbtablename, so we set sharedelement too.
794 }
795
796 // To avoid an access forbidden with a numeric ref
797 if ($dbt_select != 'rowid' && $dbt_select != 'id') {
798 $objectid = "'".$objectid."'"; // Note: $objectid was already cast into int at begin of this method.
799 }
800 // Check permission for objectid on entity only
801 if (in_array($feature, $check) && $objectid > 0) { // For $objectid = 0, no check
802 $sql = "SELECT COUNT(dbt.".$db->sanitize($dbt_select).") as nb";
803 $sql .= " FROM ".MAIN_DB_PREFIX.$db->sanitize($dbtablename)." as dbt";
804 if (($feature == 'user' || $feature == 'usergroup') && isModEnabled('multicompany')) { // Special for multicompany
805 if (getDolGlobalString('MULTICOMPANY_TRANSVERSE_MODE')) {
806 if ($conf->entity == 1 && $user->admin && !$user->entity) {
807 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
808 $sql .= " AND dbt.entity IS NOT NULL";
809 } else {
810 $sql .= ",".MAIN_DB_PREFIX."usergroup_user as ug";
811 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
812 $sql .= " AND ((ug.fk_user = dbt.rowid";
813 $sql .= " AND ug.entity IN (".getEntity('usergroup')."))";
814 $sql .= " OR dbt.entity = 0)"; // Show always superadmin
815 }
816 } else {
817 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
818 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
819 }
820 } else {
821 $reg = array();
822 if ($parenttableforentity && preg_match('/(.*)@(.*)/', $parenttableforentity, $reg)) {
823 $sql .= ", ".MAIN_DB_PREFIX.$db->sanitize($reg[2])." as dbtp";
824 $sql .= " WHERE dbt.".$db->sanitize($reg[1])." = dbtp.rowid AND dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
825 $sql .= " AND dbtp.entity IN (".getEntity($sharedelement, 1).")";
826 } else {
827 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
828 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
829 }
830 }
831 $checkonentitydone = 1;
832 }
833 if (in_array($feature, $checksoc) && $objectid > 0) { // We check feature = checksoc. For $objectid = 0, no check
834 // If external user: Check permission for external users
835 if ($user->socid > 0) {
836 if ($user->socid != $objectid) {
837 return false;
838 }
839 } elseif (isModEnabled('societe') && !$user->hasRight('societe', 'lire') && !$user->hasRight('societe', 'client', 'voir')) {
840 dol_syslog("security.lib.php::checkUserAccessToObject Deny access due: (isModEnabled('societe') && !user->hasRight('societe', 'lire') && !user->hasRight('societe', 'client', 'voir'))", LOG_DEBUG);
841 return false;
842 } elseif (isModEnabled("societe") && ($user->hasRight('societe', 'lire') && !$user->hasRight('societe', 'client', 'voir'))) {
843 // If internal user: Check permission for internal users that are restricted on their objects
844 $sql = "SELECT COUNT(sc.fk_soc) as nb";
845 $sql .= " FROM (".MAIN_DB_PREFIX."societe_commerciaux as sc";
846 $sql .= ", ".MAIN_DB_PREFIX."societe as s)";
847 $sql .= " WHERE sc.fk_soc IN (".$db->sanitize($objectid, 1).")";
848 $sql .= " AND (sc.fk_user = ".((int) $user->id);
849 if (getDolGlobalInt('MAIN_SEE_SUBORDINATES')) {
850 $userschilds = $user->getAllChildIds();
851 if (!empty($userschilds)) $sql .= " OR sc.fk_user IN (".$db->sanitize(implode(',', $userschilds)).")";
852 }
853 $sql .= ")";
854 $sql .= " AND sc.fk_soc = s.rowid";
855 $sql .= " AND s.entity IN (".getEntity($sharedelement, 1).")";
856 } elseif (isModEnabled('multicompany')) {
857 // If multicompany and internal users with all permissions, check user is in correct entity
858 $sql = "SELECT COUNT(s.rowid) as nb";
859 $sql .= " FROM ".MAIN_DB_PREFIX."societe as s";
860 $sql .= " WHERE s.rowid IN (".$db->sanitize($objectid, 1).")";
861 $sql .= " AND s.entity IN (".getEntity($sharedelement, 1).")";
862 }
863
864 $checkonentitydone = 1;
865 }
866 if (in_array($feature, $checkparentsoc) && $objectid > 0) { // Test on entity + link to thirdparty. Allowed if link is empty (Ex: contacts...).
867 // If external user: Check permission for external users
868 if ($user->socid > 0) {
869 $sql = "SELECT COUNT(dbt.".$db->sanitize($dbt_select).") as nb";
870 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
871 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
872 $sql .= " AND dbt.fk_soc = ".((int) $user->socid);
873 } elseif (isModEnabled("societe") && ($user->hasRight('societe', 'lire') && !$user->hasRight('societe', 'client', 'voir'))) {
874 // If internal user: Check permission for internal users that are restricted on their objects
875 $sql = "SELECT COUNT(dbt.".$db->sanitize($dbt_select).") as nb";
876 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
877 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON dbt.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
878 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
879 $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
880 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
881 } elseif (isModEnabled('multicompany')) {
882 // If multicompany and internal users with all permissions, check user is in correct entity
883 $sql = "SELECT COUNT(dbt.".$db->sanitize($dbt_select).") as nb";
884 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
885 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
886 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
887 }
888
889 $checkonentitydone = 1;
890 }
891 if (in_array($feature, $checkproject) && $objectid > 0) {
892 if (isModEnabled('project') && !$user->hasRight('projet', 'all', 'lire')) {
893 $projectid = $objectid;
894
895 include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
896 $projectstatic = new Project($db);
897 $tmps = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, 0);
898
899 $tmparray = explode(',', $tmps);
900 if (!in_array($projectid, $tmparray)) {
901 return false;
902 }
903 } else {
904 $sql = "SELECT COUNT(dbt.".$db->sanitize($dbt_select).") as nb";
905 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
906 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
907 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
908 }
909 $checkonentitydone = 1;
910 }
911 if (in_array($feature, $checktask) && (int) $objectid > 0) {
912 if (isModEnabled('project') && !$user->hasRight('projet', 'all', 'lire')) {
913 $task = new Task($db);
914 $task->fetch((int) $objectid);
915 $projectid = $task->fk_project;
916
917 include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
918 $projectstatic = new Project($db);
919 $tmps = $projectstatic->getProjectsAuthorizedForUser($user, 0, 1, 0);
920
921 $tmparray = explode(',', $tmps);
922 if (!in_array($projectid, $tmparray)) {
923 return false;
924 }
925 } else {
926 $sharedelement = 'project'; // for multicompany compatibility
927 $sql = "SELECT COUNT(dbt.".$db->sanitize($dbt_select).") as nb";
928 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
929 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
930 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
931 }
932
933 $checkonentitydone = 1;
934 }
935 //var_dump($sql);
936
937 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
938 // If external user: Check permission for external users
939 if ($user->socid > 0) {
940 if (empty($dbt_keyfield)) {
941 dol_print_error(null, 'Param dbt_keyfield is required but not defined');
942 }
943 $sql = "SELECT COUNT(dbt.".$db->sanitize($dbt_keyfield).") as nb";
944 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
945 $sql .= " WHERE dbt.rowid IN (".$db->sanitize($objectid, 1).")";
946 $sql .= " AND dbt.".$db->sanitize($dbt_keyfield)." = ".((int) $user->socid);
947 } elseif (isModEnabled("societe") && !$user->hasRight('societe', 'client', 'voir')) {
948 // If internal user without permission to see all thirdparties: Check permission for internal users that are restricted on their objects
949 if (empty($dbt_keyfield)) {
950 dol_print_error(null, 'Param dbt_keyfield is required but not defined');
951 }
952 if ($feature != 'ticket') {
953 $sql = "SELECT COUNT(sc.fk_soc) as nb";
954 $sql .= " FROM ".MAIN_DB_PREFIX.$db->sanitize($dbtablename)." as dbt";
955 $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
956 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
957 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
958 $sql .= " AND sc.fk_soc = dbt.".$db->sanitize($dbt_keyfield);
959 $sql .= " AND (sc.fk_user = ".((int) $user->id);
960 if (getDolGlobalInt('MAIN_SEE_SUBORDINATES')) {
961 $userschilds = $user->getAllChildIds();
962 if (!empty($userschilds)) $sql .= " OR sc.fk_user IN (".$db->sanitize(implode(',', $userschilds)).")";
963 }
964 $sql .= ')';
965 } else {
966 // On ticket, the thirdparty is not mandatory, so we need a special test to accept record with no thirdparties.
967 $sql = "SELECT COUNT(dbt.".$db->sanitize($dbt_select).") as nb";
968 $sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
969 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON sc.fk_soc = dbt.".$db->sanitize($dbt_keyfield)." AND sc.fk_user = ".((int) $user->id);
970 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
971 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
972 $sql .= " AND (sc.fk_user = ".((int) $user->id)." OR dbt.".$dbt_keyfield." IS NULL OR dbt.".$dbt_keyfield." = 0)";
973 }
974 } elseif (isModEnabled('multicompany')) {
975 // If multicompany, and user is an internal user with all permissions, check that object is in correct entity
976 $sql = "SELECT COUNT(dbt.".$db->sanitize($dbt_select).") as nb";
977 $sql .= " FROM ".MAIN_DB_PREFIX.$db->sanitize($dbtablename)." as dbt";
978 $sql .= " WHERE dbt.".$db->sanitize($dbt_select)." IN (".$db->sanitize($objectid, 1).")";
979 $sql .= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
980 }
981 }
982
983 // For events, check on users assigned to event
984 if ($feature === 'agenda' && ((int) $objectid) > 0) {
985 // Also check owner or attendee for users without allactions->read
986 if (/* $objectid > 0 && */ !$user->hasRight('agenda', 'allactions', 'read')) {
987 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
988 $action = new ActionComm($db);
989 $action->fetch((int) $objectid);
990 if ($action->authorid != $user->id && $action->userownerid != $user->id && !(array_key_exists($user->id, $action->userassigned))) {
991 return false;
992 }
993 }
994 }
995
996 // For some object, we also have to check it is in the user hierarchy
997 // Param $object must be the full object and not a simple id to have this test possible.
998 if (in_array($feature, $checkhierarchy) && is_object($object) && $objectid > 0) {
999 $childids = $user->getAllChildIds(1);
1000 $useridtocheck = 0;
1001 if ($feature == 'holiday') {
1002 $useridtocheck = $object->fk_user;
1003 if (!$user->hasRight('holiday', 'readall') && !in_array($useridtocheck, $childids) && !in_array($object->fk_validator, $childids)) {
1004 return false;
1005 }
1006 }
1007 if ($feature == 'expensereport') {
1008 $useridtocheck = $object->fk_user_author;
1009 if (!$user->hasRight('expensereport', 'readall')) {
1010 if (!in_array($useridtocheck, $childids)) {
1011 return false;
1012 }
1013 }
1014 }
1015 if ($feature == 'hrm' && in_array('evaluation', $feature2)) {
1016 $useridtocheck = $object->fk_user;
1017
1018 if ($user->hasRight('hrm', 'evaluation', 'readall')) {
1019 // the user can view evaluations for anyone
1020 return true;
1021 }
1022 if (!$user->hasRight('hrm', 'evaluation', 'read')) {
1023 // the user can't view any evaluations
1024 return false;
1025 }
1026 // the user can only see their own evaluations or their subordinates'
1027 return in_array($useridtocheck, $childids);
1028 }
1029 }
1030
1031 // For some object, we also have to check it is public or owned by user
1032 // Param $object must be the full object and not a simple id to have this test possible.
1033 if (in_array($feature, $checkuser) && is_object($object) && $objectid > 0) {
1034 $useridtocheck = $object->fk_user;
1035 if (!empty($useridtocheck) && $useridtocheck > 0 && $useridtocheck != $user->id && empty($user->admin)) {
1036 return false;
1037 }
1038 }
1039
1040 if ($sql) {
1041 $resql = $db->query($sql);
1042 if ($resql) {
1043 $obj = $db->fetch_object($resql);
1044 if (!$obj || $obj->nb < count(explode(',', $objectid))) { // error if we found 0 or less record than nb of id provided
1045 return false;
1046 }
1047 } else {
1048 dol_syslog("Bad forged sql in security.lib.php::checkUserAccessToObject", LOG_WARNING);
1049 return false;
1050 }
1051 }
1052 }
1053
1054 dol_syslog("security.lib.php::checkUserAccessToObject::return True", LOG_DEBUG);
1055 return true;
1056}
1057
1058
1070function httponly_accessforbidden($message = '1', $http_response_code = 403, $stringalreadysanitized = 0)
1071{
1072 top_httphead();
1073 http_response_code($http_response_code);
1074
1075 if ($stringalreadysanitized) {
1076 print $message;
1077 } else {
1078 print htmlentities($message);
1079 }
1080
1081 exit(1);
1082}
1083
1097function accessforbidden($message = '', $printheader = 1, $printfooter = 1, $showonlymessage = 0, $params = null)
1098{
1099 global $conf, $db, $user, $langs, $hookmanager;
1100 global $action, $object;
1101
1102 if (!is_object($langs)) {
1103 include_once DOL_DOCUMENT_ROOT.'/core/class/translate.class.php';
1104 $langs = new Translate('', $conf);
1105 $langs->setDefaultLang();
1106 }
1107
1108 $langs->loadLangs(array("main", "errors"));
1109
1110 if ($printheader && !defined('NOHEADERNOFOOTER')) {
1111 if (function_exists("llxHeader")) {
1112 llxHeader('');
1113 } elseif (function_exists("llxHeaderVierge")) {
1114 llxHeaderVierge('');
1115 }
1116 print '<div style="padding: 20px">';
1117 }
1118 print '<div class="error">';
1119 if (empty($message)) {
1120 print $langs->trans("ErrorForbidden");
1121 } else {
1122 print $langs->trans($message);
1123 }
1124 print '</div>';
1125 print '<br>';
1126 if (empty($showonlymessage)) {
1127 if (empty($hookmanager)) {
1128 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
1129 $hookmanager = new HookManager($db);
1130 // Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
1131 $hookmanager->initHooks(array('main'));
1132 }
1133
1134 $parameters = array('message' => $message, 'params' => $params);
1135 $reshook = $hookmanager->executeHooks('getAccessForbiddenMessage', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1136 print $hookmanager->resPrint;
1137 if (empty($reshook)) {
1138 $langs->loadLangs(array("errors"));
1139 if ($user->login) {
1140 print $langs->trans("CurrentLogin").': <span class="error">'.$user->login.'</span><br>';
1141 print $langs->trans("ErrorForbidden2", $langs->transnoentitiesnoconv("Home"), $langs->transnoentitiesnoconv("Users"));
1142 print $langs->trans("ErrorForbidden4");
1143 } else {
1144 print $langs->trans("ErrorForbidden3");
1145 }
1146 }
1147 }
1148 if ($printfooter && !defined('NOHEADERNOFOOTER') && function_exists("llxFooter")) {
1149 print '</div>';
1150 llxFooter();
1151 }
1152
1153 // End PHP
1154 exit(0);
1155}
1156
1157
1165{
1166 $max = getDolGlobalString('MAIN_UPLOAD_DOC'); // In Kb
1167
1168 $maxphp = @ini_get('upload_max_filesize'); // In unknown
1169 if (preg_match('/k$/i', $maxphp)) {
1170 $maxphp = preg_replace('/k$/i', '', $maxphp);
1171 $maxphp = (int) ((float) $maxphp * 1);
1172 }
1173 if (preg_match('/m$/i', $maxphp)) {
1174 $maxphp = preg_replace('/m$/i', '', $maxphp);
1175 $maxphp = (int) ((float) $maxphp * 1024);
1176 }
1177 if (preg_match('/g$/i', $maxphp)) {
1178 $maxphp = preg_replace('/g$/i', '', $maxphp);
1179 $maxphp = (int) ((float) $maxphp * 1024 * 1024);
1180 }
1181 if (preg_match('/t$/i', $maxphp)) {
1182 $maxphp = preg_replace('/t$/i', '', $maxphp);
1183 $maxphp = (int) ((float) $maxphp * 1024 * 1024 * 1024);
1184 }
1185 $maxphp2 = @ini_get('post_max_size'); // In unknown
1186 if (preg_match('/k$/i', $maxphp2)) {
1187 $maxphp2 = preg_replace('/k$/i', '', $maxphp2);
1188 $maxphp2 = (int) ((float) $maxphp2) * 1;
1189 }
1190 if (preg_match('/m$/i', $maxphp2)) {
1191 $maxphp2 = preg_replace('/m$/i', '', $maxphp2);
1192 $maxphp2 = (int) ((float) $maxphp2 * 1024);
1193 }
1194 if (preg_match('/g$/i', $maxphp2)) {
1195 $maxphp2 = preg_replace('/g$/i', '', $maxphp2);
1196 $maxphp2 = (int) ((float) $maxphp2 * 1024 * 1024);
1197 }
1198 if (preg_match('/t$/i', $maxphp2)) {
1199 $maxphp2 = preg_replace('/t$/i', '', $maxphp2);
1200 $maxphp2 = (int) ((float) $maxphp2 * 1024 * 1024 * 1024);
1201 }
1202 // Now $max and $maxphp and $maxphp2 are in Kb
1203 $maxmin = $max;
1204 $maxphptoshow = $maxphptoshowparam = '';
1205 if ($maxphp > 0) {
1206 $maxmin = min($maxmin, $maxphp);
1207 $maxphptoshow = $maxphp;
1208 $maxphptoshowparam = 'upload_max_filesize';
1209 }
1210 if ($maxphp2 > 0) {
1211 $maxmin = min($maxmin, $maxphp2);
1212 if ($maxphp2 < $maxphp) {
1213 $maxphptoshow = $maxphp2;
1214 $maxphptoshowparam = 'post_max_size';
1215 }
1216 }
1217 //var_dump($maxphp.'-'.$maxphp2);
1218 //var_dump($maxmin);
1219
1220 return array('max' => $max, 'maxmin' => $maxmin, 'maxphptoshow' => $maxphptoshow, 'maxphptoshowparam' => $maxphptoshowparam);
1221}
1222
1230function checkIPInCidr($ip, $cidr)
1231{
1232 list($network, $prefix) = explode('/', $cidr, 2);
1233
1234 // Convert IPs to binary format
1235 $ip_bin = @inet_pton($ip);
1236 $net_bin = @inet_pton($network);
1237 if ($ip_bin === false || $net_bin === false) {
1238 return -1;
1239 }
1240
1241 // Require same address IPvX family
1242 if (strlen($ip_bin) !== strlen($net_bin)) {
1243 return -1;
1244 }
1245
1246 // Comparison boundaries
1247 $total_bits = strlen($ip_bin) * 8;
1248 $prefix = max(0, min((int) $prefix, $total_bits));
1249 $full_bytes = intdiv($prefix, 8);
1250 $rem_bits = $prefix % 8;
1251
1252 // Compare full bytes and partial bytes
1253 if ($full_bytes > 0) {
1254 if (substr($ip_bin, 0, $full_bytes) !== substr($net_bin, 0, $full_bytes)) {
1255 return 0;
1256 }
1257 }
1258 if ($rem_bits > 0) {
1259 $mask = (0xFF << (8 - $rem_bits)) & 0xFF;
1260 $ip_byte = ord($ip_bin[$full_bytes]);
1261 $net_byte = ord($net_bin[$full_bytes]);
1262 if (($ip_byte & $mask) !== ($net_byte & $mask)) {
1263 return 0;
1264 }
1265 }
1266 return 1;
1267}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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=[], $ws='')
Header function.
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
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:73
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.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
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.
isModEnabled($module)
Is Dolibarr module enabled.
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.
checkIPInCidr($ip, $cidr)
Check if IP address is in CIDR range.
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.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.