dolibarr 24.0.0-beta
security.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2013-2022 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
4 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
25// Load Dolibarr environment
26require '../../main.inc.php';
48require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
49require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
50require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
51require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
52require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
53require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
54require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
55require_once DOL_DOCUMENT_ROOT.'/core/class/events.class.php';
56
57// Load translation files required by the page
58$langs->loadLangs(array("install", "other", "admin", "errors", "website"));
59
60if (!$user->admin) {
62}
63
64if (GETPOST('action', 'aZ09') == 'donothing') {
65 exit;
66}
67
68$execmethod = getDolGlobalInt('MAIN_EXEC_USE_POPEN', 1);
69
70
71/*
72 * View
73 */
74
75$form = new Form($db);
76
77llxHeader('', '', '', '', 0, 0, '', '', '', 'mod-admin page-system_security');
78
79print load_fiche_titre($langs->trans("Security"), '', 'title_setup');
80
81print '<div class="info">';
82print '<span class="">'.$langs->trans("YouMayFindSecurityAdviceHere", 'hhttps://wiki.dolibarr.org/index.php/Security_information').'</span>';
83print ' &nbsp; &nbsp; ';
84print '<a href="'.$_SERVER["PHP_SELF"].'">';
85print img_picto($langs->trans("Reload"), 'refresh').' ';
86print $langs->trans("Reload");
87print '</a>';
88print '</div>';
89
90
91print '<br>';
92
93
94print load_fiche_titre($langs->trans("PHPSetup"), '', 'folder');
95
96
97print '<div class="divsection wordbreak">';
98
99// Get version of PHP
100$phpversion = version_php();
101print "<strong>PHP</strong>: ".$langs->trans("Version").": ".$phpversion;
102if (function_exists('php_ini_loaded_file')) {
103 $inipath = php_ini_loaded_file();
104 print " - <strong>INI</strong>: ".$inipath;
105}
106print "<br>\n";
107
108// Get version of web server
109print "<br><strong>Web server - ".$langs->trans("Version")."</strong>: ".$_SERVER["SERVER_SOFTWARE"]."<br>\n";
110print '<strong>'.$langs->trans("DataRootServer")."</strong>: ".DOL_DATA_ROOT."<br>\n";
111// Web user group by default
112$labeluser = dol_getwebuser('user');
113$labelgroup = dol_getwebuser('group');
114if ($labeluser && $labelgroup) {
115 print '<strong>'.$langs->trans("WebUserGroup")." (env vars)</strong> : ".$labeluser.':'.$labelgroup;
116 if (function_exists('posix_geteuid') && function_exists('posix_getpwuid')) {
117 $arrayofinfoofuser = posix_getpwuid(posix_geteuid());
118 print ' <span class="opacitymedium">(POSIX '.$arrayofinfoofuser['name'].':'.$arrayofinfoofuser['gecos'].':'.$arrayofinfoofuser['dir'].':'.$arrayofinfoofuser['shell'].')</span><br>'."\n";
119 }
120}
121// Web user group real (detected by 'id' external command)
122if (function_exists('exec')) {
123 $arrayout = array();
124 $varout = 0;
125 exec('id', $arrayout, $varout);
126 if (empty($varout)) { // Test command is ok. Work only on Linux OS.
127 print '<strong>'.$langs->trans("WebUserGroup")." (real, 'id' command)</strong> : ".implode(',', $arrayout)."<br>\n";
128 }
129}
130print '<br>';
131
132print (ini_get('session.use_strict_mode') ? img_picto('', 'tick', 'class="pictofixedwidth"') : img_warning('', '', 'pictofixedwidth nopaddingleft'))."<strong>PHP session.use_strict_mode</strong> = ".(ini_get('session.use_strict_mode') ? ini_get('session.use_strict_mode') : yn(0)).' &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", '1').")</span><br>\n";
133print (ini_get('session.use_only_cookies') ? img_picto('', 'tick', 'class="pictofixedwidth"') : img_warning('', '', 'pictofixedwidth nopaddingleft'))."<strong>PHP session.use_only_cookies</strong> = ".(ini_get('session.use_only_cookies') ? ini_get('session.use_only_cookies') : yn(0)).' &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", '1').")</span><br>\n";
134print (ini_get('session.cookie_httponly') ? img_picto('', 'tick', 'class="pictofixedwidth"') : img_warning('', '', 'pictofixedwidth nopaddingleft'))."<strong>PHP session.cookie_httponly</strong> = ".(ini_get('session.cookie_httponly') ? ini_get('session.cookie_httponly') : '').' &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", '1').")</span><br>\n";
135print (ini_get('session.cookie_samesite') ? img_picto('', 'tick', 'class="pictofixedwidth"') : img_warning('', '', 'pictofixedwidth nopaddingleft'))."<strong>PHP session.cookie_samesite</strong> = ".(ini_get('session.cookie_samesite') ? ini_get('session.cookie_samesite') : 'None');
136if (!ini_get('session.cookie_samesite') || ini_get('session.cookie_samesite') == 'Lax') {
137 print ' &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", 'Lax').")</span>";
138} elseif (ini_get('session.cookie_samesite') == 'Strict') {
139 print ' &nbsp; '.img_warning().' <span class="opacitymedium">'.$langs->trans("WarningPaypalPaymentNotCompatibleWithStrict")."</span>";
140}
141print "<br>\n";
142
143print (ini_get('open_basedir') ? img_picto('', 'tick', 'class="pictofixedwidth"') : img_warning('', '', 'pictofixedwidth nopaddingleft'))."<strong>PHP open_basedir</strong> = ".(ini_get('open_basedir') ? ini_get('open_basedir') : yn(0).' &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("ARestrictedPath").', '.$langs->transnoentitiesnoconv("Example").': '.$_SERVER["DOCUMENT_ROOT"].','.DOL_DATA_ROOT).')</span>')."<br>\n";
144
145print ((empty(ini_get('short_open_tag')) || ini_get('short_open_tag') == 'Off') ? img_picto('', 'tick', 'class="pictofixedwidth"') : img_warning('', '', 'pictofixedwidth nopaddingleft'))."<strong>PHP short_open_tag</strong> = ".((empty(ini_get('short_open_tag')) || ini_get('short_open_tag') == 'Off') ? yn(0) : yn(1)).' &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("No")).')</span>'."<br>\n";
146
147print (ini_get('allow_url_fopen') ? img_picto($langs->trans("YouShouldSetThisToOff"), 'warning', 'class="pictofixedwidth nopaddingleft"') : img_picto('', 'tick', 'class="pictofixedwidth"'))."<strong>PHP allow_url_fopen</strong> = ".(ini_get('allow_url_fopen') ? ini_get('allow_url_fopen') : yn(0)).' &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("No")).", except if Yes is required by some external modules)</span><br>\n";
148
149print (ini_get('allow_url_include') ? img_picto($langs->trans("YouShouldSetThisToOff"), 'warning', 'class="pictofixedwidth nopaddingleft"') : img_picto('', 'tick', 'class="pictofixedwidth"')). "<strong>PHP allow_url_include</strong> = ".(ini_get('allow_url_include') ? ini_get('allow_url_include') : yn(0)).' &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("No")).")</span><br>\n";
150//print "<strong>PHP safe_mode</strong> = ".(ini_get('safe_mode') ? ini_get('safe_mode') : yn(0)).' &nbsp; <span class="opacitymedium">'.$langs->trans("Deprecated")." (removed in PHP 5.4)</span><br>\n";
151
152if (getDolGlobalString('MAIN_SECURITY_SHOW_MORE_INFO')) {
153 print "<strong>PHP auto_prepend_file</strong> = ".(ini_get('auto_prepend_file') ? ini_get('auto_prepend_file') : '')."</span><br>\n";
154
155 print "<strong>PHP sendmail_path</strong> = ".(ini_get('sendmail_path') ? ini_get('sendmail_path') : '')."</span><br>\n";
156}
157
158print '<br>';
159print "<strong>PHP disable_functions</strong>: ";
160// The original value is...
161$disablefunctionorign = '';
162$phparray = phpinfo_array();
163foreach ($phparray as $key => $value) {
164 foreach ($value as $keyparam => $keyvalue) {
165 if ($keyparam == 'disable_functions') {
166 if (!empty($keyvalue['master'])) {
167 $disablefunctionorign = $keyvalue['master'];
168 break;
169 }
170 }
171 }
172}
173/*
174if (empty($disablefunctionorign)) {
175 $disablefunctionorign = ini_get('disable_functions'); // Not always the real value
176}
177*/
178$arrayoffunctionsdisabled = explode(',', $disablefunctionorign);
179
180$arrayoffunctionstodisable = explode(',', 'dl,apache_note,apache_setenv,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,show_source,virtual');
181//$arrayoffunctionstodisable[] = 'stream_wrapper_restore';
182//$arrayoffunctionstodisable[] = 'stream_wrapper_register';
183if ($execmethod == 1) {
184 $arrayoffunctionstodisable2 = explode(',', 'passthru,shell_exec,system,proc_open,popen');
185 $functiontokeep = 'exec';
186} else {
187 $arrayoffunctionstodisable2 = explode(',', 'exec,passthru,shell_exec,system,proc_open');
188 $functiontokeep = 'popen';
189}
190$i = 0;
191foreach ($arrayoffunctionsdisabled as $functionkey) {
192 if ($i > 0) {
193 print ', ';
194 }
195 print '<span class="opacitymedium">'.$functionkey.'</span>';
196 $i++;
197}
198print "<br>\n";
199$todisabletext = '';
200$i = 0;
201foreach ($arrayoffunctionstodisable as $functiontodisable) {
202 if (\function_exists($functiontodisable)) {
203 if ($i > 0) {
204 $todisabletext .= ', ';
205 }
206 $todisabletext .= ' <span class="opacitymedium">'.$functiontodisable.'</span>';
207 $i++;
208 }
209}
210if ($todisabletext) {
211 print img_picto('', 'warning', 'class="pictofixedwidth nopaddingleft"').$langs->trans("YouShouldDisablePHPFunctions").': '.$todisabletext;
212 print '<br>';
213}
214$todisabletext = '';
215$i = 0;
216foreach ($arrayoffunctionstodisable2 as $functiontodisable) {
217 if (\function_exists($functiontodisable)) {
218 if ($i > 0) {
219 $todisabletext .= ', ';
220 }
221 $todisabletext .= ' <span class="opacitymedium">'.$functiontodisable.'</span>';
222 $i++;
223 }
224}
225if ($todisabletext) {
226 print img_picto('', 'warning', 'class="pictofixedwidth nopaddingleft"').$langs->trans("IfCLINotRequiredYouShouldDisablePHPFunctions").': '.$todisabletext;
227 print '<br>';
228}
229if (!function_exists($functiontokeep)) {
230 print img_picto($langs->trans("PHPFunctionsRequiredForCLI"), 'warning', 'class="pictofixedwidth"');
231} else {
232 print img_picto('', 'tick', 'class="pictofixedwidth"');
233}
234print $langs->trans("PHPFunctionsRequiredForCLI").': ';
235print '<span class="opacitymedium" title="exec or popen can be used depending on MAIN_EXEC_USE_POPEN option, currently to '.getDolGlobalInt('MAIN_EXEC_USE_POPEN').'">'.$functiontokeep.'</span>';
236print '<br>';
237
238print '<br>';
239
240// JSON
241$loadedExtensions = array_map('strtolower', get_loaded_extensions(false));
242$test = !in_array('json', $loadedExtensions);
243if ($test || function_exists('dol_json_decode')) {
244 print img_picto('', 'error', 'class="pictofixedwidth nopaddingleft"');
245} else {
246 print img_picto('', 'tick', 'class="pictofixedwidth"');
247}
248print '<strong>JSON</strong>: ';
249if ($test || function_exists('dol_json_decode')) {
250 print $langs->trans("NotInstalled").' - '.$langs->trans("VulnerableToRCEAttack");
251} else {
252 print $langs->trans("Available").' <span class="opacitymedium">(PHP native so not emulated, safe)</span>';
253}
254print '<br>';
255
256// XDebug
257$test = !function_exists('xdebug_is_enabled') && !extension_loaded('xdebug');
258if ($test) {
259 print img_picto('', 'tick', 'class="pictofixedwidth"');
260} else {
261 print img_picto('', 'warning', 'class="pictofixedwidth nopaddingleft"');
262}
263print '<strong>XDebug</strong>: ';
264if ($test) {
265 print $langs->trans("NotInstalled").' - '.$langs->trans("NotRiskOfLeakWithThis");
266} else {
267 print $langs->trans("ModuleActivatedMayExposeInformation", $langs->transnoentities("XDebug"));
268 print ' - '.$langs->trans("MoreInformation").' <a href="'.DOL_URL_ROOT.'/admin/system/xdebug.php">XDebug admin page</a>';
269}
270
271print '</div>';
272
273print '<br>';
274
275
276// OS Setup - Permissions on files
277
278print '<br>';
279print load_fiche_titre($langs->trans("OSSetup").' - '.$langs->trans("PermissionsOnFiles"), '', 'folder');
280
281print '<div class="divsection wordbreak">';
282
283print '<strong>'.$langs->trans("PermissionsOnFilesInWebRoot").'</strong>: ';
284$arrayoffilesinroot = dol_dir_list(DOL_DOCUMENT_ROOT, 'all', 1, '', array('\/custom'), 'name', SORT_ASC, 4, 1, '', 1);
285$fileswithwritepermission = array();
286foreach ($arrayoffilesinroot as $fileinroot) {
287 // Test if there is at least one write permission file. If yes, add the entry into array $fileswithwritepermission
288 if (isset($fileinroot['perm']) && ($fileinroot['perm'] & 0222)) {
289 $fileswithwritepermission[] = $fileinroot['relativename'];
290 }
291}
292if (empty($fileswithwritepermission)) {
293 print img_picto('', 'tick').' '.$langs->trans("NoWritableFilesFoundIntoRootDir");
294} else {
295 print img_warning().' '.$langs->trans("SomeFilesOrDirInRootAreWritable");
296 print ' &nbsp; - &nbsp; <span class="classlink cursorpointer" onclick="javascript: console.log(\'Toggle examples\'); jQuery(\'#examplewritablefiles\').toggle();">'.$langs->trans("Examples").'</span>';
297 print '<span id="examplewritablefiles" class="hideobject"><br>'.$langs->trans("Example").': ';
298 $i = 0;
299 foreach ($fileswithwritepermission as $filewithwritepermission) {
300 if ($i > 0) {
301 print ', ';
302 }
303 print '<span class="opacitymedium">'.$filewithwritepermission.'</span>';
304 if ($i > 20) {
305 print ' ...';
306 break;
307 }
308 $i++;
309 }
310 print '</span>';
311}
312print '<br>';
313print '<br>';
314
315print '<strong>'.$langs->trans("PermissionsOnFile", $conffile).'</strong>: '; // $conffile is defined into filefunc.inc.php
316$perms = fileperms($dolibarr_main_document_root.'/'.$conffile);
317if ($perms) {
318 if (($perms & 0x0004) || ($perms & 0x0002)) {
319 print img_warning().' '.$langs->trans("ConfFileIsReadableOrWritableByAnyUsers");
320 // Web user group by default
321 $labeluser = dol_getwebuser('user');
322 $labelgroup = dol_getwebuser('group');
323 print ' '.$langs->trans("User").': '.$labeluser.':'.$labelgroup;
324 if (function_exists('posix_geteuid') && function_exists('posix_getpwuid')) {
325 $arrayofinfoofuser = posix_getpwuid(posix_geteuid());
326 print ' <span class="opacitymedium">(POSIX '.$arrayofinfoofuser['name'].':'.$arrayofinfoofuser['gecos'].':'.$arrayofinfoofuser['dir'].':'.$arrayofinfoofuser['shell'].')</span>';
327 }
328 } else {
329 print img_picto('', 'tick');
330 }
331} else {
332 print img_warning().' '.$langs->trans("FailedToReadFile", $conffile);
333}
334print '<br>';
335print '<br>';
336
337$installlock = DOL_DATA_ROOT.'/install.lock';
338$upgradeunlock = DOL_DATA_ROOT.'/upgrade.unlock';
339$installmoduleslock = DOL_DATA_ROOT.'/installmodules.lock';
340
341// Is install (upgrade) locked
342$test = file_exists($installlock);
343print '<strong>'.$langs->trans("DolibarrSetup").'</strong>: ';
344if ($test) {
345 if (file_exists($upgradeunlock)) {
346 print img_picto('', 'tick').' '.$langs->trans("InstallLockedBy", $installlock);
347 } else {
348 print img_picto('', 'tick').' '.$langs->trans("InstallAndUpgradeLockedBy", $installlock);
349 }
350} else {
351 print img_warning().' '.$langs->trans("WarningLockFileDoesNotExists", DOL_DATA_ROOT);
352}
353
354print '<br>';
355print '<br>';
356
357// Is upgrade unlocked
358if (file_exists($installlock)) { // If install not locked, no need to show this.
359 if (file_exists($upgradeunlock)) {
360 print '<strong>'.$langs->trans("DolibarrUpgrade").'</strong>: ';
361 print img_warning().' '.$langs->trans("WarningUpgradeHasBeenUnlocked", $upgradeunlock);
362 print '<br>';
363 print '<br>';
364 }
365}
366
367// Is addon install locked ?
368$test = file_exists($installmoduleslock);
369print '<strong>'.$langs->trans("DolibarrAddonInstall").'</strong>: ';
370if ($test) {
371 print img_picto('', 'tick').' '.$langs->trans("InstallAndUpgradeLockedBy", $installmoduleslock);
372} else {
373 print $langs->trans("InstallOfAddonIsNotBlocked", DOL_DATA_ROOT);
374}
375
376print '</div>';
377
378
379
380// File conf.php
381
382print '<br>';
383print '<br>';
384print load_fiche_titre($langs->trans("ConfigurationFile").' ('.$conffile.')', '', 'folder');
385
386print '<div class="divsection wordbreak">';
387print '<strong>$dolibarr_main_prod</strong>: '.($dolibarr_main_prod ? $dolibarr_main_prod : '0');
388if (empty($dolibarr_main_prod)) {
389 print ' &nbsp; &nbsp; '.img_picto('', 'warning').' '.$langs->trans("IfYouAreOnAProductionSetThis", 1);
390}
391print '<br>';
392
393if (!empty($dolibarr_nocsrfcheck)) {
394 print '<strong>$dolibarr_nocsrfcheck</strong>: '.(empty($dolibarr_nocsrfcheck) ? '0' : $dolibarr_nocsrfcheck);
395 print ' &nbsp; &nbsp;'.img_picto('', 'error').' '.$langs->trans("IfYouAreOnAProductionSetThis", 0);
396 print '<br>';
397}
398
399print '<strong>$dolibarr_main_restrict_ip</strong>: ';
400if (empty($dolibarr_main_restrict_ip)) {
401 print $langs->trans("None");
402 print ' &nbsp; &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("StaticIPsOfUsers")).')</span>';
403} else {
404 print $dolibarr_main_restrict_ip;
405}
406print '<br>';
407
408
409print '<strong>$dolibarr_main_restrict_os_commands</strong>: ';
410if (empty($dolibarr_main_restrict_os_commands)) {
411 print $langs->trans("None");
412} else {
413 print $dolibarr_main_restrict_os_commands;
414}
415print ' &nbsp; &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", 'mariadb-dump, mariadb, mysqldump, mysql, pg_dump, pg_restore, clamdscan').')</span>';
416print '<br>';
417
418
419print '<strong>$dolibarr_main_restrict_eval_methods</strong>: ';
420if (empty($dolibarr_main_restrict_eval_methods)) {
421 print $langs->trans("None");
422} else {
423 print $dolibarr_main_restrict_eval_methods;
424}
425print ' &nbsp; &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", 'getDolGlobalString, getDolGlobalInt, getDolCurrency, getDolEntity, getDolDBType, fetchNoCompute, hasRight, isAdmin, isExternalUser, isModEnabled, isStringVarMatching, abs, min, max, round, dol_now, dol_concat, preg_match').')</span>';
426print '<br>';
427
428
429print '<strong>$dolibarr_website_allow_custom_php</strong>: ';
430if (!empty($dolibarr_website_allow_custom_php) && $dolibarr_website_allow_custom_php == 2) {
431 print img_picto('', 'warning').' ';
432}
433if (empty($dolibarr_website_allow_custom_php)) {
434 print '0';
435} else {
436 print $dolibarr_website_allow_custom_php;
437}
438print ' &nbsp; &nbsp; <span class="opacitymedium">(';
439if (isModEnabled('website')) {
440 print $langs->trans("RecommendedValueIs", '0 if you don\'t include PHP in your websites, else 1');
441} else {
442 print $langs->trans("RecommendedValueIs", '0');
443}
444print ')</span>';
445print '<br>';
446
447
448if (!getDolGlobalString('SECURITY_DISABLE_TEST_ON_OBFUSCATED_CONF')) {
449 print '<strong>$dolibarr_main_db_pass</strong>: ';
450 if (!empty($dolibarr_main_db_pass) && empty($dolibarr_main_db_encrypted_pass)) {
451 print img_picto('', 'warning').' '.$langs->trans("DatabasePasswordNotObfuscated").' &nbsp; &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': '.$langs->trans("SetOptionTo", $langs->transnoentitiesnoconv("MainDbPasswordFileConfEncrypted"), yn(1)).')</span>';
452 //print ' <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", $langs->transnoentitiesnoconv("IPsOfUsers")).')</span>';
453 } else {
454 print img_picto('', 'tick').' '.$langs->trans("DatabasePasswordObfuscated");
455 }
456
457 print '<br>';
458}
459
460print '<strong>$dolibarr_main_stream_to_disable</strong>: ';
461// $arrayofstreamtodisable is defined into filefunc.inc.php
462'@phan-var-force string[] $arrayofstreamtodisable';
463if (empty($dolibarr_main_stream_to_disable)) {
464 print '<span class="opacitymedium">'.$langs->trans("Undefined").' = '.implode(', ', $arrayofstreamtodisable).'</span>';
465} else {
466 print implode(', ', $dolibarr_main_stream_to_disable);
467}
468print '<span class="bold"> &nbsp; -> Current PHP streams allowed = </span>';
469$arrayofstreams = stream_get_wrappers();
470if (!empty($arrayofstreams)) {
471 sort($arrayofstreams);
472 print '<span class="wordbreak">'.implode(',', $arrayofstreams).'</span>';
473 print ' &nbsp; &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': '.$langs->trans("TryToKeepOnly", 'file,http,https,php,zip').')</span>'."\n";
474}
475print '</div>';
476
477
478/*
479if (!empty($dolibarr_main_stream_do_not_disable)) {
480 print '<strong>$dolibarr_main_stream_do_not_disable</strong>: ';
481 if (empty($dolibarr_main_stream_do_not_disable)) {
482 print '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>';
483 } else {
484 print join(', ', $dolibarr_main_stream_do_not_disable);
485 }
486 print ' -> PHP stream allowed = ';
487 $arrayofstreams = stream_get_wrappers();
488 if (!empty($arrayofstreams)) {
489 sort($arrayofstreams);
490 print (join(',', $arrayofstreams)).' &nbsp; &nbsp; <span class="opacitymedium">('.$langs->trans("RecommendedValueIs", 'Undefined').')</span>'."\n";
491 }
492
493 print '<br>';
494}
495*/
496
497
498// Menu Home - Setup - Security
499
500print '<br>';
501print '<br>';
502
503print load_fiche_titre($langs->trans("Menu").' '.$langs->trans("SecuritySetup"), '', 'folder');
504
505print '<div class="divsection wordbreak">';
506
507print '<strong>'.$langs->trans("UseCaptchaCode").' - Login</strong>: ';
508print !getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA') ? '' : img_picto('', 'tick').' ';
509print yn(!getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA') ? 0 : 1);
510print '<br>';
511print '<br>';
512
513print '<strong>'.$langs->trans("UseCaptchaCode").' - Ticket</strong>: ';
514print !getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_TICKET') ? '' : img_picto('', 'tick').' ';
515print yn(!getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_TICKET') ? 0 : 1);
516print '<br>';
517print '<br>';
518
519print '<strong>'.$langs->trans("UseCaptchaCode").' - Thirdparty public contact form</strong>: ';
520print !getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_THIRPARTY') ? '' : img_picto('', 'tick').' ';
521print yn(!getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_THIRPARTY') ? 0 : 1);
522print '<br>';
523print '<br>';
524
525print '<strong>'.$langs->trans("UseCaptchaCode").' - Membership subscription</strong>: ';
526print !getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_MEMBER') ? '' : img_picto('', 'tick').' ';
527print yn(!getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_MEMBER') ? 0 : 1);
528print '<br>';
529print '<br>';
530
531$sessiontimeout = ini_get("session.gc_maxlifetime");
532if (!getDolGlobalString('MAIN_SESSION_TIMEOUT')) {
533 $conf->global->MAIN_SESSION_TIMEOUT = $sessiontimeout;
534}
535print '<strong>'.$langs->trans("SessionTimeOut").'</strong>';
536if (!ini_get("session.gc_probability")) {
537 print $form->textwithpicto('', $langs->trans("SessionsPurgedByExternalSystem", ini_get("session.gc_maxlifetime")));
538} else {
539 print $form->textwithpicto('', $langs->trans("SessionExplanation", ini_get("session.gc_probability"), ini_get("session.gc_divisor"), ini_get("session.gc_maxlifetime")));
540}
541print ': '.getDolGlobalInt('MAIN_SESSION_TIMEOUT').' '.strtolower($langs->trans("Seconds"));
542print '<br><br>';
543
544print '<strong>'.$langs->trans("MaxNumberOfImagesInGetPost").'</strong>: ';
545print(getDolGlobalInt('MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT') ? img_picto('', 'tick').' ' : '').getDolGlobalInt('MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT').' '.strtolower($langs->trans("Images"));
546print '<br><br>';
547
548print '<strong>'.$langs->trans("MaxNumberOfPostOnPublicPagesByIP").'</strong>: ';
549print(getDolGlobalInt('MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS', 200) ? img_picto('', 'tick').' ' : '').getDolGlobalInt('MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS', 200).' '.strtolower($langs->trans("Posts"));
550print '<br><br>';
551
552print '<strong>'.$langs->trans("MaxNumberOfAttachementOnForms").'</strong>: ';
553print(getDolGlobalInt('MAIN_SECURITY_MAX_ATTACHMENT_ON_FORMS', 10) ? img_picto('', 'tick').' ' : '').getDolGlobalInt("MAIN_SECURITY_MAX_ATTACHMENT_ON_FORMS", 10).' '.strtolower($langs->trans("Files"));
554print '<br><br>';
555
556
557// Clear password ?
558
559print '<strong>'.$langs->trans("DoNotStoreClearPassword").'</strong>: ';
560print !getDolGlobalString('DATABASE_PWD_ENCRYPTED') ? '' : img_picto('', 'tick').' ';
561print yn(!getDolGlobalString('DATABASE_PWD_ENCRYPTED') ? 0 : 1);
562if (!getDolGlobalString('DATABASE_PWD_ENCRYPTED')) {
563 print ' <span class="opacitymedium">('.$langs->trans("Recommended").' '.yn(1).')</span>';
564}
565print '<br>';
566print '<br>';
567
568
569// Mask by default in upload
570$umask = getDolGlobalString('MAIN_UMASK');
571
572print '<strong>'.$langs->trans("UMask").'</strong>: ';
573if (! in_array($umask, array('600', '660', '0600', '0660'))) {
574 print img_warning().' ';
575}
576print $umask;
577if (! in_array($umask, array('600', '660', '0600', '0660'))) {
578 print ' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': 0600 | 0660)</span>';
579}
580print '<br>';
581print '<br>';
582
583
584/* Already into section conf file */
585/*
586$usepassinconfencrypted = 0;
587global $dolibarr_main_db_pass, $dolibarr_main_db_encrypted_pass;
588if (preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass) || !empty($dolibarr_main_db_encrypted_pass)) {
589 $usepassinconfencrypted = 1;
590}
591print '<strong>'.$langs->trans("MainDbPasswordFileConfEncrypted").'</strong>: ';
592print $usepassinconfencrypted ? img_picto('', 'tick').' ' : img_warning().' ';
593print yn($usepassinconfencrypted);
594if (empty($usepassinconfencrypted)) {
595 print ' <span class="opacitymedium">('.$langs->trans("Recommended").' '.yn(1).')</span>';
596}
597print '<br>';
598print '<br>';
599*/
600
601/* Password length
602
603// Stored into $tabconf[0] if module generator is "Perso" or specific to the module generator.
604$tabConf = explode(";", getDolGlobalString('USER_PASSWORD_PATTERN'));
605
606print '<strong>'.$langs->trans("PasswordLength").'</strong>: ';
607print empty($conf->global->DATABASE_PWD_ENCRYPTED) ? '' : img_picto('', 'tick').' ';
608print yn(empty($conf->global->DATABASE_PWD_ENCRYPTED) ? 0 : 1);
609if (empty($conf->global->DATABASE_PWD_ENCRYPTED)) {
610 print ' <span class="opacitymedium">('.$langs->trans("Recommended").' '.yn(1).')</span>';
611}
612print '<br>';
613print '<br>';
614*/
615
616print '<strong>'.$langs->trans("AntivirusEnabledOnUpload").'</strong>: ';
617print getDolGlobalString('MAIN_ANTIVIRUS_UPLOAD_ON') ? img_picto('', 'tick').' ' : img_warning().' ';
618print yn(!getDolGlobalString('MAIN_ANTIVIRUS_UPLOAD_ON') ? 0 : 1);
619if (!getDolGlobalString('MAIN_ANTIVIRUS_UPLOAD_ON') || !getDolGlobalString('MAIN_ANTIVIRUS_COMMAND')) {
620 print ' - <span class="opacitymedium">'.$langs->trans("Recommended").': '.$langs->trans("DefinedAPathForAntivirusCommandIntoSetup", $langs->transnoentitiesnoconv("Home")." - ".$langs->transnoentitiesnoconv("Setup")." - ".$langs->transnoentitiesnoconv("Security")).'</span>';
621} else {
622 print ' &nbsp; - ' . getDolGlobalString('MAIN_ANTIVIRUS_COMMAND');
623 if (defined('MAIN_ANTIVIRUS_COMMAND') && !defined('MAIN_ANTIVIRUS_BYPASS_COMMAND_AND_PARAM')) {
624 print ' - <span class="opacitymedium">'.$langs->trans("ValueIsForcedBySystem").'</span>';
625 }
626}
627print '<br>';
628print '<br>';
629
630// File extension locked in upload by default
631
632print '<strong>'.$langs->trans("UploadExtensionRestriction").'</strong>: ';
633print implode(', ', explode(',', getDolGlobalString('MAIN_FILE_EXTENSION_UPLOAD_RESTRICTION', implode(',', getExecutableContent()))));
634print ' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': '.implode(', ', getExecutableContent()).')</span>';
635print '<br>';
636print '<br>';
637
638
639print '<strong>'.$langs->trans("MAIN_SECURITY_MAXFILESIZE_DOWNLOADED").'</strong> = '.getDolGlobalString('MAIN_SECURITY_MAXFILESIZE_DOWNLOADED', '<span class="opacitymedium">'.$langs->trans("Undefined").' &nbsp; ('.$langs->trans("Recommended").': < 100000)</span>')."<br>";
640print '<br>';
641
642
643
644$securityevent = new Events($db);
645$eventstolog = $securityevent->eventstolog;
646
647print '<strong>'.$langs->trans("AuditedSecurityEvents").'</strong>: ';
648$out = '';
649if (!empty($eventstolog) && is_array($eventstolog)) {
650 // Loop on each event type
651 $i = 0;
652 foreach ($eventstolog as $key => $arr) {
653 if ($arr['id']) {
654 $key = 'MAIN_LOGEVENTS_'.$arr['id'];
655 $value = getDolGlobalString($key);
656 if ($value) {
657 if ($i > 0) {
658 $out .= ', ';
659 }
660 $out .= '<span class="opacitymedium">'.$key.'</span>';
661 $i++;
662 }
663 }
664 }
665 print $out;
666}
667
668if (empty($out)) {
669 print img_warning().' '.$langs->trans("NoSecurityEventsAreAduited", $langs->transnoentities("Home").' - '.$langs->transnoentities("Setup").' - '.$langs->transnoentities("Security").' - '.$langs->transnoentities("Audit")).'<br>';
670} else {
671 $s = $langs->trans("SeeSetupPage", ' {s1}'.$langs->transnoentities("Home").' - '.$langs->transnoentities("Setup").' - '.$langs->transnoentities("Security").' - '.$langs->transnoentities("Audit").'{s2}');
672 print ' - '.str_replace('{s2}', '</a>', str_replace('{s1}', '<a href="'.DOL_URL_ROOT.'/admin/events.php" target="_blank">'.img_picto('', 'url', 'class="pictofixedwidth"'), $s));
673}
674
675print '<br>';
676
677print '<br>';
678
679print '<strong>MAIN_SECURITY_FORCERP</strong> = '.getDolGlobalString('MAIN_SECURITY_FORCERP', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or")." \"strict-origin-when-cross-origin\" or \"same-origin\" so browser doesn't send any referrer when going into another web site domain)</span><br>";
680print '<br>';
681
682print '<strong>MAIN_SECURITY_FORCESTS</strong> = '.getDolGlobalString('MAIN_SECURITY_FORCESTS', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").": max-age=31536000; includeSubDomains)</span><br>";
683print '<br>';
684
685print '<strong>MAIN_SECURITY_FORCEPP</strong> = '.getDolGlobalString('MAIN_SECURITY_FORCEPP', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").": camera=*, microphone=(), geolocation=*)</span><br>";
686print '<br>';
687
688if (getDolGlobalString('MAIN_SECURITY_FORCECSPRO')) {
689 $examplecsprule = "frame-ancestors 'self'; img-src * data:; font-src *; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googleapis.com *.google-analytics.com *.googletagmanager.com *.dolistore.com *.githubusercontent.com";
690 print '<strong>MAIN_SECURITY_FORCECSPRO</strong> = '.getDolGlobalString('MAIN_SECURITY_FORCECSPRO', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').' &nbsp; <span class="opacitymedium">('.$langs->trans("Example").': "'.$examplecsprule.'")</span><br>';
691 print '<br>';
692}
693
694$examplecsprule = "frame-ancestors 'self'; img-src * data:; font-src *; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googleapis.com *.google-analytics.com *.googletagmanager.com *.dolistore.com *.githubusercontent.com";
695print '<strong>MAIN_SECURITY_FORCECSP</strong> = '.getDolGlobalString('MAIN_SECURITY_FORCECSP', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').' &nbsp; <span class="opacitymedium">('.$langs->trans("Example").': "'.$examplecsprule.'")</span><br>';
696print '<br>';
697
698$tmpurl = constant('DOL_MAIN_URL_ROOT');
699$tmpurl = preg_replace('/^(https?:\/\/[^\/]+)\/.*$/', '\1', $tmpurl);
700print '<strong>MAIN_SECURITY_FORCE_ACCESS_CONTROL_ALLOW_ORIGIN</strong> = '.getDolGlobalString('MAIN_SECURITY_FORCE_ACCESS_CONTROL_ALLOW_ORIGIN', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").": 1 so browsers will accept answers of a page only if page was requested from the domain ".$tmpurl.". Note: it is not possible to limit to several domains)</span><br>";
701
702print '</div>';
703
704print '<br>';
705
706
707
708// Modules/Applications
709
710print '<br>';
711print '<br>';
712print load_fiche_titre($langs->trans("Modules"), '', 'folder');
713
714print '<div class="divsection wordbreak">';
715
716// Module log
717print '<strong>'.$langs->trans("Syslog").'</strong>: ';
718$test = isModEnabled('syslog');
719if (!$test) {
720 print img_picto('', 'tick').' '.$langs->trans("NotInstalled").' - '.$langs->trans("NotRiskOfLeakWithThis");
721} else {
722 if (getDolGlobalInt('SYSLOG_LEVEL') > LOG_NOTICE) {
723 print img_picto('', 'warning').' '.$langs->trans("ModuleActivatedWithTooHighLogLevel", $langs->transnoentities("Syslog"));
724 } else {
725 print img_picto('', 'tick').' '.$langs->trans("ModuleSyslogActivatedButLevelNotTooVerbose", $langs->transnoentities("Syslog"), getDolGlobalInt('SYSLOG_LEVEL'));
726 }
727 //print ' '.$langs->trans("MoreInformation").' <a href="'.DOL_URL_ROOT.'/admin/system/xdebug.php'.'">XDebug admin page</a>';
728}
729print '<br>';
730
731print '<br>';
732
733// Module debugbar
734print '<strong>'.$langs->trans("DebugBar").'</strong>: ';
735$test = isModEnabled('debugbar');
736if (!$test) {
737 print img_picto('', 'tick').' '.$langs->trans("NotInstalled").' - '.$langs->trans("NotRiskOfLeakWithThis");
738} else {
739 print img_picto('', 'error').' '.$langs->trans("ModuleActivatedDoNotUseInProduction", $langs->transnoentities("DebugBar"));
740 //print ' '.$langs->trans("MoreInformation").' <a href="'.DOL_URL_ROOT.'/admin/system/xdebug.php'.'">XDebug admin page</a>';
741}
742print '<br>';
743
744// Modules for Payments
745/*
746$test = isModEnabled('stripe');
747if ($test) {
748 print '<br>';
749
750 print '<strong>'.$langs->trans("Stripe").'</strong>: ';
751 if (!getDolGlobalString('PAYMENT_SECURITY_TOKEN_UNIQUE')) {
752 print img_picto('', 'error').' '.$langs->trans("OptionXShouldBeEnabledInModuleY", $langs->transnoentities("SecurityTokenIsUnique"), $langs->transnoentities("Stripe"));
753 } else {
754 print img_picto('', 'tick').' '.$langs->trans("OptionXIsCorrectlyEnabledInModuleY", $langs->transnoentities("SecurityTokenIsUnique"), $langs->transnoentities("Stripe"));
755 }
756 print '<br>';
757} else {
758 $test = isModEnabled('paypal');
759 if ($test) {
760 print '<br>';
761
762 print '<strong>'.$langs->trans("Paypal").'</strong>: ';
763 if (!getDolGlobalString('PAYMENT_SECURITY_TOKEN_UNIQUE')) {
764 print img_picto('', 'error').' '.$langs->trans("OptionXShouldBeEnabledInModuleY", $langs->transnoentities("SecurityTokenIsUnique"), $langs->transnoentities("Paypal"));
765 } else {
766 print img_picto('', 'tick').' '.$langs->trans("OptionXIsCorrectlyEnabledInModuleY", $langs->transnoentities("SecurityTokenIsUnique"), $langs->transnoentities("Paypal"));
767 }
768 print '<br>';
769 }
770}
771*/
772
773print '</div>';
774
775
776// APIs
777
778print '<br>';
779print '<br>';
780print load_fiche_titre($langs->trans("API"), '', 'folder');
781
782print '<div class="divsection wordbreak">';
783
784if (!isModEnabled('api') && !isModEnabled('webservices')) {
785 print $langs->trans("APIsAreNotEnabled");
786} else {
787 if (isModEnabled('webservices')) {
788 print img_picto('', 'warning').' '.$langs->trans('YouEnableDeprecatedWSAPIsUseRESTAPIsInstead')."<br>\n";
789 print '<br>';
790 }
791 if (isModEnabled('api')) {
792 print '<strong>API_ENDPOINT_RULES</strong> = '.getDolGlobalString('API_ENDPOINT_RULES', '<span class="opacitymedium">'.$langs->trans("Undefined").' &nbsp; ('.$langs->trans("Example").': login:0,users:0,setup:1,status:1,tickets:1,...)</span>')."<br>\n";
793
794 print '<br>';
795
796 print '<strong>API_ENABLE_LOGIN_API</strong> = '.getDolGlobalString('API_ENABLE_LOGIN_API', '0').' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': 0)</span><br>';
797 }
798}
799
800
801print '</div>';
802
803
804print '<br>';
805print '<br>';
806
807
808// Other setup
809
810print load_fiche_titre($langs->trans("OtherSetup"), '', 'folder');
811
812print '<div class="divsection wordbreak">';
813
814print '<strong>MAIN_ALLOW_SVG_FILES_AS_IMAGES</strong> = '.getDolGlobalString('MAIN_ALLOW_SVG_FILES_AS_IMAGES', '0').' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': 0)</span><br>';
815print '<br>';
816
817print '<strong>MAIN_ALWAYS_CREATE_LOCK_AFTER_LAST_UPGRADE</strong> = '.getDolGlobalString('MAIN_ALWAYS_CREATE_LOCK_AFTER_LAST_UPGRADE', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': 1)</span><br>';
818print '<br>';
819
820print '<strong>MAIN_SECURITY_ANTI_SSRF_SERVER_IP</strong> = '.getDolGlobalString('MAIN_SECURITY_ANTI_SSRF_SERVER_IP', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span> &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': List of static IPs of server separated with coma - '.$langs->trans("Note").': common loopback ip like 127.*.*.*, [::1] are already added)</span>')."<br>";
821print '<br>';
822
823print '<strong>MAIN_SECURITY_CSRF_WITH_TOKEN</strong> = '.getDolGlobalString('MAIN_SECURITY_CSRF_WITH_TOKEN', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 2)</span>'."<br>";
824
825print '</div>';
826
827print '<br>';
828print '<br>';
829
830
831
832// Database encryption
833
834print load_fiche_titre($langs->trans("DatabaseEncryption"), '', 'folder');
835
836print '<div class="divsection wordbreak">';
837
838//print '<strong>'.$langs->trans("PasswordEncryption").'</strong>: ';
839print '<strong>'.$langs->trans("AlgorithmFor", $langs->transnoentitiesnoconv("Passwords"));
840print $form->textwithpicto('', 'non reversible encryption, defined into MAIN_SECURITY_HASH_ALGO');
841print '</strong> = '.getDolGlobalString('MAIN_SECURITY_HASH_ALGO', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>')." &nbsp; ";
842if (!getDolGlobalString('MAIN_SECURITY_HASH_ALGO')) {
843 print '<span class="opacitymedium"> &nbsp; &nbsp; (If unset: \'md5\')</span>';
844}
845if (getDolGlobalString('MAIN_SECURITY_HASH_ALGO') != 'password_hash') {
846 print '<br><strong>MAIN_SECURITY_SALT</strong> = '.getDolGlobalString('MAIN_SECURITY_SALT', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').'<br>';
847} else {
848 print '<span class="opacitymedium">('.$langs->trans("Recommended").': password_hash)</span>';
849 print '<br>';
850}
851if (getDolGlobalString('MAIN_SECURITY_HASH_ALGO') != 'password_hash') {
852 print '<div class="info">The recommended value for MAIN_SECURITY_HASH_ALGO is now \'password_hash\' but setting it now will make ALL existing passwords of all users not valid, so update is not possible.<br>';
853 print 'If you really want to switch, you must:<br>';
854 print '- Go on home - setup - other and add constant MAIN_SECURITY_HASH_ALGO to value \'password_hash\'<br>';
855 print '- In same session, WITHOUT LOGGING OUT, go into your admin user record and set a new password<br>';
856 print '- You can now logout and login with this new password. You must now reset password of all other users.<br>';
857 print '</div>';
858}
859print '<br>';
860
861$action = GETPOST('action');
862$exampletodecrypt = GETPOST('exampletodecrypt', 'password');
863
864print '<strong>'.$langs->trans("AlgorithmFor", $langs->transnoentitiesnoconv("SensitiveData"));
865print $form->textwithpicto('', 'reversible encryption done with dolEncrypt/dolDecrypt');
866print '</strong> = '.constant('MAIN_SECURITY_REVERSIBLE_ALGO').' with a random seed + a crypt key defined into the conf.php file (in $dolibarr_main_instance_unique_id or $dolibarr_main_dolcrypt_key)<br>';
867print '<form method="POST" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'" spellcheck="false">';
868print '<input type="hidden" name="action" value="doldecrypt">';
869print '<input type="hidden" name="token" value="'.newToken().'">';
870print '<input type="hidden" name="page_y" value="">';
871print $langs->trans("ToolToDecryptAString").': ';
872print '<input type="text" class="minwidth500 valignmiddle" name="exampletodecrypt" placeholder="dolcrypt:ALGOXXXX:ABCDFEF1234" value="'.$exampletodecrypt.'" spellcheck="false">';
873print '<input type="submit" class="reposition button small smallpaddingimp valignmiddle" name="submit" value="'.$langs->transnoentitiesnoconv("Decrypt").'">';
874if ($action == 'doldecrypt' && $user->admin && $exampletodecrypt) {
875 usleep(200);
876 $decryptedstring = $exampletodecrypt;
877 if (preg_match('/^dolobfuscationv1/', $exampletodecrypt)) {
878 // Clear cache
879 unset($_SESSION['obfuscationkey_'.((int) $conf->entity)]);
880 unset($conf->cache['obfuscationkey_'.((int) $conf->entity)]);
881 // Reload obfuscationkey
882 require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
883 $b = new BlockedLog($db);
884 $obfuscationkey = $b->getObfuscationKey();
885
886 include_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
887 $registrationnumber = getHashUniqueIdOfRegistration();
888 print '<!-- registrationnumber '.$registrationnumber.' -->'."\n";
889 print '<!-- mysoc->idprof1 = '.$mysoc->idprof1.' -->'."\n";
890 print '<!-- session '.$_SESSION['obfuscationkey_'.((int) $conf->entity)].' -->'."\n";
891 print '<!-- conf->cache = '. (string) $conf->cache['obfuscationkey_'.((int) $conf->entity)].' -->'."\n";
892 print '<!-- obfuscationkey => '.$obfuscationkey.' -->'."\n"; // For debug only
893
894 $decryptedstring = dolDecrypt($exampletodecrypt, $obfuscationkey);
895 } elseif (preg_match('/^dolcrypt/', $exampletodecrypt)) {
896 $decryptedstring = dolDecrypt($exampletodecrypt);
897 }
898 if (ascii_check($decryptedstring)) {
899 print '<br> => <textarea rows="'.ROWS_1.'" class="valignmiddle quatrevingtpercent">'.dolPrintHTMLForTextArea($decryptedstring).'</textarea>';
900 } else {
901 print '<br><span class="error"> => Failed to decrypt. The crypting key saved into the conf.php file seems to not be the one used to encrypt the provided encrypted string</span>';
902 }
903}
904print '</form>';
905
906print '</div>';
907
908
909print '<br>';
910print '<br>';
911
912
913// Websites
914
915if (isModEnabled('website')) {
916 print load_fiche_titre($langs->trans("Website"), '', 'website');
917 print '<div class="divsection wordbreak">';
918
919 $sql = "SELECT w.rowid as id, w.ref";
920 $sql .= " FROM ".MAIN_DB_PREFIX."website as w";
921 $sql .= " WHERE w.entity = ".((int) $conf->entity);
922 $sql .= " AND w.status = 1";
923
924 $resql = $db->query($sql);
925 if ($resql) {
926 $num_rows = $db->num_rows($resql);
927 if ($num_rows > 0) {
928 $i = 0;
929 while ($obj = $db->fetch_object($resql)) {
930 print "<strong>".$langs->trans("WebsiteSecurityOptions").": ".$obj->ref."</strong>";
931 print'<br><br>';
932
933 print '<strong>WEBSITE_'.$obj->id.'_SECURITY_FORCERP</strong> = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCERP', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': '.$langs->trans("Undefined").'="strict-origin-when-cross-origin" '.$langs->trans("or").' "same-origin"=more secured)</span><br>';
934
935 print '<strong>WEBSITE_'.$obj->id.'_SECURITY_FORCESTS</strong> = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCESTS', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').' &nbsp; <span class="opacitymedium">('.$langs->trans("Example").": \"max-age=31536000; includeSubDomains\")</span><br>";
936
937 print '<strong>WEBSITE_'.$obj->id.'_SECURITY_FORCEPP</strong> = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCEPP', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>').' &nbsp; <span class="opacitymedium">('.$langs->trans("Example").": \"camera=(), microphone=(), geolocation=*\")</span><br>";
938
939 if (getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCECSPPRO')) {
940 print '<strong>WEBSITE_'.$obj->id.'_SECURITY_FORCECSPPRO</strong> = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCECSPPRO', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>');
941 print ' &nbsp; <span class="opacitymedium">('.$langs->trans("Example").': "';
942 $examplecsprule = "default-src 'self' 'unsafe-inline' matomo.".getDomainFromURL($_SERVER["SERVER_NAME"], 1)." *.transifex.net *.transifex.com *.cloudflare.com *.cloudflareinsights.com *.google-analytics.com *.googletagmanager.com *.google.com *.gstatic.com *.googleapis.com *.googleadservices.com *.ads-twitter.com *.doubleclick.net; frame-ancestors 'self'; object-src *.youtube.com; frame-src 'self' *.twitter.com *.facebook.com *.youtube.com; img-src * data:;";
943 print $examplecsprule;
944 print '")</span><br>';
945 }
946
947 print '<strong>WEBSITE_'.$obj->id.'_SECURITY_FORCECSP</strong> = '.getDolGlobalString('WEBSITE_'.$obj->id.'_SECURITY_FORCECSP', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>');
948 print ' &nbsp; <span class="opacitymedium">('.$langs->trans("Example").': "';
949 $examplecsprule = "default-src 'self' 'unsafe-inline' matomo.".getDomainFromURL($_SERVER["SERVER_NAME"], 1)." *.transifex.net *.transifex.com *.cloudflare.com *.cloudflareinsights.com *.google-analytics.com *.googletagmanager.com *.google.com *.gstatic.com *.googleapis.com *.googleadservices.com *.ads-twitter.com *.doubleclick.net; frame-ancestors 'self'; object-src *.youtube.com; frame-src 'self' *.twitter.com *.facebook.com *.youtube.com; img-src * data:;";
950 print $examplecsprule;
951 print '")</span><br>';
952
953 $i++;
954 if ($i != $num_rows) {
955 print '<br>';
956 }
957 }
958 } else {
959 print '<span class="opacity">'.$langs->trans("NoWebsite").'</span>';
960 }
961 } else {
963 }
964 print '</div>';
965
966
967 print '<br>';
968}
969
970
971// Other - experimental
972
973print load_fiche_titre($langs->trans("OtherSetup").' ('.$langs->trans("Experimental").')', '', 'folder');
974
975print '<div class="divsection wordbreak">';
976print '<strong>MAIN_EXEC_USE_POPEN</strong> = ';
977if (!getDolGlobalString('MAIN_EXEC_USE_POPEN')) {
978 print '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>';
979} else {
980 print getDolGlobalString('MAIN_EXEC_USE_POPEN');
981}
982if ($execmethod == 1) {
983 print '<span class="opacitymedium"> &nbsp; &nbsp; "exec" PHP method will be used for shell commands';
984 print ' &nbsp; ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 1)';
985 print '</span>';
986}
987if ($execmethod == 2) {
988 print '<span class="opacitymedium"> &nbsp; &nbsp; "popen" PHP method will be used for shell commands';
989 print ' &nbsp; ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 1)';
990 print '</span>';
991}
992print '<br>';
993print '<br>';
994
995print '<strong>MAIN_RESTRICTHTML_ONLY_VALID_HTML</strong> = '.(getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML') ? '1' : '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>');
996print ' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").": 1 - does not work on HTML5 with some old libxml libs)</span>";
997
998// Test compatibility of MAIN_RESTRICTHTML_ONLY_VALID_HTML
999$savMAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = getDolGlobalString('MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES');
1000$savMAIN_RESTRICTHTML_ONLY_VALID_HTML = getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML');
1001$savMAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY');
1002$conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = 0;
1003$conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = 1;
1004$conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = 0;
1005$result = dol_htmlwithnojs('<img onerror<=alert(document.domain)> src=>0xbeefed');
1006$conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = $savMAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES;
1007$conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = $savMAIN_RESTRICTHTML_ONLY_VALID_HTML;
1008$conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = $savMAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY;
1009
1010if ($result == 'InvalidHTMLStringCantBeCleaned') {
1011 print ' &nbsp; - &nbsp; '.img_warning().' Your libxml seems to old to work correctly with this option. Disable it !';
1012} else {
1013 print ' &nbsp; - &nbsp; Test of compatibility with this option seems ok';
1014}
1015print '<br>';
1016
1017print '<br>';
1018
1019print '<strong>MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY</strong> = '.(getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY') ? '1' : '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>');
1020print ' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").': 1)</span> &nbsp; - &nbsp; Module "php-tidy" must be enabled (currently: '.((extension_loaded('tidy') && class_exists("tidy")) ? 'Enabled' : img_picto('', 'warning').' Not available').")";
1021if (extension_loaded('tidy') && class_exists("tidy")) {
1022 // Test compatibility of MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY
1023 $savMAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = getDolGlobalString('MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES');
1024 $savMAIN_RESTRICTHTML_ONLY_VALID_HTML = getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML');
1025 $savMAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = getDolGlobalString('MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY');
1026 $conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = 0;
1027 $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = 0;
1028 $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = 1;
1029 $result = dol_htmlwithnojs('<img onerror<=alert(document.domain)> src=>0xbeefed');
1030 $conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = $savMAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES;
1031 $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = $savMAIN_RESTRICTHTML_ONLY_VALID_HTML;
1032 $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = $savMAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY;
1033
1034 if ($result == 'InvalidHTMLStringCantBeCleaned') {
1035 print ' &nbsp; - &nbsp; '.img_warning().' Your libxml seems to old to work correctly with this option. Disable it !';
1036 } else {
1037 print ' &nbsp; - &nbsp; Test of compatibility with this option seems ok';
1038 }
1039}
1040print '<br>';
1041
1042print '<br>';
1043
1044print '<strong>MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES</strong> = '.(getDolGlobalString('MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES') ? '1' : '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>');
1045print ' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").": 1 - does not work on HTML5 with some old libxml libs)</span><br>";
1046print '<br>';
1047
1048// MAIN_DISALLOW_URL_INTO_DESCRIPTIONS = 1, disallow url links except if on the local wrapper document.php or viewimage.php
1049// MAIN_DISALLOW_URL_INTO_DESCRIPTIONS = 2, disallow all urls link
1050print '<strong>MAIN_DISALLOW_URL_INTO_DESCRIPTIONS</strong> = '.getDolGlobalString('MAIN_DISALLOW_URL_INTO_DESCRIPTIONS', '<span class="opacitymedium">'.$langs->trans("Undefined").' &nbsp; ('.$langs->trans("Recommended").': 1=only local links allowed (to wrapper document.php or image.php) or 2=no links at all)</span>')."<br>";
1051print '<br>';
1052
1053print '<strong>MAIN_ALLOW_SVG_FILES_AS_EXTERNAL_LINKS</strong> = '.getDolGlobalString('MAIN_ALLOW_SVG_FILES_AS_EXTERNAL_LINKS', '<span class="opacitymedium">'.$langs->trans("Undefined").' &nbsp; ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 0)</span>')."<br>";
1054print '<br>';
1055
1056print '<strong>MAIN_ALLOW_LINK_STARTING_WITH_FILE</strong> = '.getDolGlobalString('MAIN_ALLOW_LINK_STARTING_WITH_FILE', '<span class="opacitymedium">'.$langs->trans("Undefined").' &nbsp; ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 0)</span>')."<br>";
1057print '<br>';
1058
1059print '<strong>MAIN_ALLOW_OBFUSCATION_METHODS_IN_DOL_EVAL</strong> = '.getDolGlobalString('MAIN_ALLOW_OBFUSCATION_METHODS_IN_DOL_EVAL', '<span class="opacitymedium">'.$langs->trans("Undefined").'</span>');
1060print ' &nbsp; <span class="opacitymedium">('.$langs->trans("Recommended").": ".$langs->trans("Undefined").' '.$langs->trans("or")." 0 - The value 1 allows the use of concatenation functions like . or dol_concat into extra fields conditions or formula but is not secured)</span><br>";
1061print '<br>';
1062
1063// MAIN_ALLOW_LOCAL_LINKS_AS_EXTERNAL_LINKS
1064
1065print '<strong>MAIN_SECURITY_CSRF_TOKEN_RENEWAL_ON_EACH_CALL</strong> = '.getDolGlobalString('MAIN_SECURITY_CSRF_TOKEN_RENEWAL_ON_EACH_CALL', '<span class="opacitymedium">'.$langs->trans("Undefined").' &nbsp; ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 0)</span>')."<br>";
1066print '<br>';
1067
1068print '<strong>MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED</strong> = '.getDolGlobalString('MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED', '<span class="opacitymedium">'.$langs->trans("Undefined").' &nbsp; ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 0)</span>')."<br>";
1069
1070
1071
1072/*
1073 * If we call URL with param security.php/test/test and security.php/test%2Ftest, we can get information if
1074 * AllowEncodedSlashes is enabled or not.
1075 * Note: When there is a string after the page.php/... and before the ? or #, it is available into the $_SERVER["PATH_INFO"].
1076 * Note about $_SERVER:
1077 * REQUEST_URI: /test/before_rewrite/script.php/path/info?q=helloword
1078 * PHP_SELF: /test/after_rewrite/script.php/path/info
1079 * QUERY_STRING: q=helloword
1080 * SCRIPT_NAME: /test/after_rewrite/script.php
1081 * PATH_INFO: /path/info (usually not defined because there is no text between page.php/... and before the ? or #)
1082 * SCRIPT_FILENAME: /var/www/test/php/script.php
1083 * __FILE__ : /var/www/test/php/script_included.php
1084 */
1085$request = $_SERVER['REQUEST_URI'];
1086if (strpos($request, '%2F') !== false) { // It seems than even when AllowEncodedSlashes=NoDecode, behaviour is forced to On on some servers.
1087 echo '<br><strong>AllowEncodedSlashes probably enabled (NoDecode)</strong>';
1088} elseif (strpos($request, '/test/test') !== false) {
1089 echo '<br><strong>AllowEncodedSlashes enabled with decoding On</strong>';
1090} else {
1091 //echo 'Cannot determine';
1092}
1093
1094
1095
1096print '</div>';
1097
1098
1099print '<br>';
1100print '<br>';
1101
1102
1103print load_fiche_titre($langs->trans("LimitsAndMitigation"), '', 'folder');
1104
1105print '<div class="divsection wordbreak">';
1106
1107print '<span class="opacitymedium">';
1108print $langs->trans("RecommendMitigationOnURL").'<br>';
1109print '</span>';
1110
1111print '<br>';
1112$urlexamplebase = 'https://github.com/Dolibarr/dolibarr/blob/develop/dev/setup/fail2ban/filter.d/';
1113print '<span class="fas fa-shield-alt"></span> Login or API authentication (see <a target="_blank" rel="noopener" href="'.$urlexamplebase.'web-dolibarr-rulesbruteforce.conf">fail2ban example on GitHub</a>)<br>';
1114print '<span class="fas fa-shield-alt"></span> '.DOL_URL_ROOT.'/passwordforgotten.php (see <a target="_blank" rel="noopener" href="'.$urlexamplebase.'web-dolibarr-rulespassforgotten.conf">fail2ban example on GitHub</a>)<br>';
1115print '<span class="fas fa-shield-alt"></span> '.DOL_URL_ROOT.'/public/* (see <a target="_blank" rel="noopener" href="'.$urlexamplebase.'web-dolibarr-limitpublic.conf">fail2ban example on GitHub</a>)<br>';
1116print '<br>';
1117$urlexamplebase = 'https://github.com/Dolibarr/dolibarr/blob/develop/dev/setup/apache/';
1118print '<span class="fas fa-shield-alt"></span> You can also protect the application using a HTTP Basic authentication layer (see <a target="_blank" rel="noopener" href="'.$urlexamplebase.'virtualhost">apache2 virtualhost example on GitHub</a>)<br>';
1119
1120print '</div>';
1121
1122// End of page
1123llxFooter();
1124$db->close();
phpinfo_array()
Return the php_info into an array.
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
getHashUniqueIdOfRegistration($algo='sha256')
Return a hash unique identifier of the registration (used to identify the registration of instance wi...
Class to manage Blocked Log.
Events class.
Class to manage generation of HTML components Only common components must be here.
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.
$conffile
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:64
version_php()
Return PHP version.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
dolPrintHTMLForTextArea($s, $allowiframe=0)
Return a string ready to be output on input textarea.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
yn($yesno, $format=1, $color=0)
Return yes or no in current language.
ascii_check($str)
Check if a string is in ASCII.
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...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox=0, $check='restricthtml')
Sanitize a HTML to remove js, dangerous content and external links.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
dol_getwebuser($mode)
Return user/group account of web server.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
dolDecrypt($chain, $key='', $patterntotest='')
Decode a string with a symmetric encryption.