Issues (2811)

public/htdocs/main.inc.php (1 issue)

Labels
Severity
1
<?php
2
3
/* Copyright (C) 2002-2007  Rodolphe Quiedeville        <[email protected]>
4
 * Copyright (C) 2003       Xavier Dutoit               <[email protected]>
5
 * Copyright (C) 2004-2021  Laurent Destailleur         <[email protected]>
6
 * Copyright (C) 2004       Sebastien Di Cintio         <[email protected]>
7
 * Copyright (C) 2004       Benoit Mortier              <[email protected]>
8
 * Copyright (C) 2005-2021  Regis Houssin               <[email protected]>
9
 * Copyright (C) 2011-2014  Philippe Grand              <[email protected]>
10
 * Copyright (C) 2008       Matteli
11
 * Copyright (C) 2011-2016  Juanjo Menent               <[email protected]>
12
 * Copyright (C) 2012       Christophe Battarel         <[email protected]>
13
 * Copyright (C) 2014-2015  Marcos García               <[email protected]>
14
 * Copyright (C) 2015       Raphaël Doursenaud          <[email protected]>
15
 * Copyright (C) 2020       Demarest Maxime             <[email protected]>
16
 * Copyright (C) 2020       Charlene Benke              <[email protected]>
17
 * Copyright (C) 2021-2024  Frédéric France             <[email protected]>
18
 * Copyright (C) 2021       Alexandre Spangaro          <[email protected]>
19
 * Copyright (C) 2023       Joachim Küter      		    <[email protected]>
20
 * Copyright (C) 2023       Eric Seigne      		    <[email protected]>
21
 * Copyright (C) 2024		MDW							<[email protected]>
22
 * Copyright (C) 2024       Rafael San José             <[email protected]>
23
 *
24
 * This program is free software; you can redistribute it and/or modify
25
 * it under the terms of the GNU General Public License as published by
26
 * the Free Software Foundation; either version 3 of the License, or
27
 * (at your option) any later version.
28
 *
29
 * This program is distributed in the hope that it will be useful,
30
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32
 * GNU General Public License for more details.
33
 *
34
 * You should have received a copy of the GNU General Public License
35
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
36
 */
37
38
use Dolibarr\Code\Core\Classes\Translate;
39
use Dolibarr\Lib\Filters;
40
use Dolibarr\Tools\Debug;
41
use Dolibarr\Lib\Version;
42
use Dolibarr\Lib\ViewMain;
43
44
/**
45
 *  \file       htdocs/main.inc.php
46
 *  \ingroup    core
47
 *  \brief      File that defines environment for Dolibarr GUI pages only (file not required by scripts)
48
 */
49
50
//@ini_set('memory_limit', '128M'); // This may be useless if memory is hard limited by your PHP
51
52
// For optional tuning. Enabled if environment variable MAIN_SHOW_TUNING_INFO is defined.
53
54
$micro_start_time = 0;
55
if (!empty($_SERVER['MAIN_SHOW_TUNING_INFO'])) {
56
    list($usec, $sec) = explode(" ", microtime());
57
    $micro_start_time = ((float)$usec + (float)$sec);
58
    // Add Xdebug code coverage
59
    //define('XDEBUGCOVERAGE',1);
60
    if (defined('XDEBUGCOVERAGE')) {
61
        xdebug_start_code_coverage();
62
    }
63
}
64
65
// To disable the WAF for GET and POST and PHP_SELF, uncomment this
66
//define('NOSCANPHPSELFFORINJECTION', 1);
67
//define('NOSCANGETFORINJECTION', 1);
68
//define('NOSCANPOSTFORINJECTION', 1 or 2);
69
70
// Check consistency of NOREQUIREXXX DEFINES
71
if ((defined('NOREQUIREDB') || defined('NOREQUIRETRAN')) && !defined('NOREQUIREMENU')) {
72
    print 'If define NOREQUIREDB or NOREQUIRETRAN are set, you must also set NOREQUIREMENU or not set them.';
73
    exit;
74
}
75
if (defined('NOREQUIREUSER') && !defined('NOREQUIREMENU')) {
76
    print 'If define NOREQUIREUSER is set, you must also set NOREQUIREMENU or not set it.';
77
    exit;
78
}
79
80
// Sanity check on URL
81
/*
82
if (!defined('NOSCANPHPSELFFORINJECTION') && !empty($_SERVER["PHP_SELF"])) {
83
    $morevaltochecklikepost = array($_SERVER["PHP_SELF"]);
84
    analyseVarsForSqlAndScriptsInjection($morevaltochecklikepost, 2);
85
}
86
*/
87
88
// Sanity check on GET parameters
89
if (!defined('NOSCANGETFORINJECTION') && !empty($_SERVER["QUERY_STRING"])) {
90
    // Note: QUERY_STRING is url encoded, but $_GET and $_POST are already decoded
91
    // Because the analyseVarsForSqlAndScriptsInjection is designed for already url decoded value, we must decode QUERY_STRING
92
    // Another solution is to provide $_GET as parameter with analyseVarsForSqlAndScriptsInjection($_GET, 1);
93
    $morevaltochecklikeget = array(urldecode($_SERVER["QUERY_STRING"]));
94
    Filters::analyseVarsForSqlAndScriptsInjection($morevaltochecklikeget, 1);
95
}
96
97
// Sanity check on POST
98
if (!defined('NOSCANPOSTFORINJECTION') || is_array(constant('NOSCANPOSTFORINJECTION'))) {
99
    Filters::analyseVarsForSqlAndScriptsInjection($_POST, 0);
100
}
101
102
// This is to make Dolibarr working with Plesk
103
if (!empty($_SERVER['DOCUMENT_ROOT']) && substr($_SERVER['DOCUMENT_ROOT'], -6) !== 'htdocs') {
104
    set_include_path($_SERVER['DOCUMENT_ROOT'] . '/htdocs');
105
}
106
107
// Include the conf.php and functions.lib.php and security.lib.php. This defined the constants like DOL_DOCUMENT_ROOT, DOL_DATA_ROOT, DOL_URL_ROOT...
108
require_once 'filefunc.inc.php';
109
110
// If there is a POST parameter to tell to save automatically some POST parameters into cookies, we do it.
111
// This is used for example by form of boxes to save personalization of some options.
112
// DOL_AUTOSET_COOKIE=cookiename:val1,val2 and  cookiename_val1=aaa cookiename_val2=bbb will set cookie_name with value json_encode(array('val1'=> , ))
113
if (GETPOST("DOL_AUTOSET_COOKIE")) {
114
    $tmpautoset = explode(':', GETPOST("DOL_AUTOSET_COOKIE"), 2);
115
    $tmplist = explode(',', $tmpautoset[1]);
116
    $cookiearrayvalue = array();
117
    foreach ($tmplist as $tmpkey) {
118
        $postkey = $tmpautoset[0] . '_' . $tmpkey;
119
        //var_dump('tmpkey='.$tmpkey.' postkey='.$postkey.' value='.GETPOST($postkey);
120
        if (GETPOST($postkey)) {
121
            $cookiearrayvalue[$tmpkey] = GETPOST($postkey);
122
        }
123
    }
124
    $cookiename = $tmpautoset[0];
125
    $cookievalue = json_encode($cookiearrayvalue);
126
    //var_dump('setcookie cookiename='.$cookiename.' cookievalue='.$cookievalue);
127
    if (PHP_VERSION_ID < 70300) {
128
        setcookie($cookiename, empty($cookievalue) ? '' : $cookievalue, empty($cookievalue) ? 0 : (time() + (86400 * 354)), '/', '', ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? false : true), true); // keep cookie 1 year and add tag httponly
129
    } else {
130
        // Only available for php >= 7.3
131
        $cookieparams = array(
132
            'expires' => empty($cookievalue) ? 0 : (time() + (86400 * 354)),
133
            'path' => '/',
134
            //'domain' => '.mywebsite.com', // the dot at the beginning allows compatibility with subdomains
135
            'secure' => ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? false : true),
136
            'httponly' => true,
137
            'samesite' => 'Lax' // None || Lax  || Strict
138
        );
139
        setcookie($cookiename, empty($cookievalue) ? '' : $cookievalue, $cookieparams);
140
    }
141
    if (empty($cookievalue)) {
142
        unset($_COOKIE[$cookiename]);
143
    }
144
}
145
146
// Set the handler of session
147
// if (ini_get('session.save_handler') == 'user')
148
if (!empty($php_session_save_handler) && $php_session_save_handler == 'db') {
149
    require_once 'core/lib/phpsessionin' . $php_session_save_handler . '.lib.php';
150
}
151
152
// Init session. Name of session is specific to Dolibarr instance.
153
// Must be done after the include of filefunc.inc.php so global variables of conf file are defined (like $dolibarr_main_instance_unique_id or $dolibarr_main_force_https).
154
// Note: the function dol_getprefix() is defined into functions.lib.php but may have been defined to return a different key to manage another area to protect.
155
$prefix = dol_getprefix('');
156
$sessionname = 'DOLSESSID_' . $prefix;
157
$sessiontimeout = 'DOLSESSTIMEOUT_' . $prefix;
158
if (!empty($_COOKIE[$sessiontimeout])) {
159
    ini_set('session.gc_maxlifetime', $_COOKIE[$sessiontimeout]);
160
}
161
162
// This create lock, released by session_write_close() or end of page.
163
// We need this lock as long as we read/write $_SESSION ['vars']. We can remove lock when finished.
164
if (!defined('NOSESSION')) {
165
    if (PHP_VERSION_ID < 70300) {
166
        session_set_cookie_params(0, '/', null, ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? false : true), true); // Add tag secure and httponly on session cookie (same as setting session.cookie_httponly into php.ini). Must be called before the session_start.
167
    } else {
168
        // Only available for php >= 7.3
169
        $sessioncookieparams = array(
170
            'lifetime' => 0,
171
            'path' => '/',
172
            //'domain' => '.mywebsite.com', // the dot at the beginning allows compatibility with subdomains
173
            'secure' => ((empty($dolibarr_main_force_https) && isHTTPS() === false) ? false : true),
174
            'httponly' => true,
175
            'samesite' => 'Lax' // None || Lax  || Strict
176
        );
177
        session_set_cookie_params($sessioncookieparams);
178
    }
179
    session_name($sessionname);
180
    dol_session_start();    // This call the open and read of session handler
181
    //exit; // this exist generates a call to write and close
182
}
183
184
185
// Init the 6 global objects, this include will make the 'new Xxx()' and set properties for: $conf, $db, $langs, $user, $mysoc, $hookmanager
186
require_once 'master.inc.php';
187
188
// Uncomment this and set session.save_handler = user to use local session storing
189
// include DOL_DOCUMENT_ROOT.'/core/lib/phpsessionindb.inc.php
190
191
// If software has been locked. Only login $conf->global->MAIN_ONLY_LOGIN_ALLOWED is allowed.
192
if (getDolGlobalString('MAIN_ONLY_LOGIN_ALLOWED')) {
193
    $ok = 0;
194
    if ((!session_id() || !isset($_SESSION["dol_login"])) && !isset($_POST["username"]) && !empty($_SERVER["GATEWAY_INTERFACE"])) {
195
        $ok = 1; // We let working pages if not logged and inside a web browser (login form, to allow login by admin)
196
    } elseif (isset($_POST["username"]) && $_POST["username"] == $conf->global->MAIN_ONLY_LOGIN_ALLOWED) {
197
        $ok = 1; // We let working pages that is a login submission (login submit, to allow login by admin)
198
    } elseif (defined('NOREQUIREDB')) {
199
        $ok = 1; // We let working pages that don't need database access (xxx.css.php)
200
    } elseif (defined('EVEN_IF_ONLY_LOGIN_ALLOWED')) {
201
        $ok = 1; // We let working pages that ask to work even if only login enabled (logout.php)
202
    } elseif (session_id() && isset($_SESSION["dol_login"]) && $_SESSION["dol_login"] == $conf->global->MAIN_ONLY_LOGIN_ALLOWED) {
203
        $ok = 1; // We let working if user is allowed admin
204
    }
205
    if (!$ok) {
206
        if (session_id() && isset($_SESSION["dol_login"]) && $_SESSION["dol_login"] != $conf->global->MAIN_ONLY_LOGIN_ALLOWED) {
207
            print 'Sorry, your application is offline.' . "\n";
208
            print 'You are logged with user "' . $_SESSION["dol_login"] . '" and only administrator user "' . getDolGlobalString('MAIN_ONLY_LOGIN_ALLOWED') . '" is allowed to connect for the moment.' . "\n";
209
            $nexturl = constant('BASE_URL') . '/user/logout.php?token=' . newToken();
210
            print 'Please try later or <a href="' . $nexturl . '">click here to disconnect and change login user</a>...' . "\n";
211
        } else {
212
            print 'Sorry, your application is offline. Only administrator user "' . getDolGlobalString('MAIN_ONLY_LOGIN_ALLOWED') . '" is allowed to connect for the moment.' . "\n";
213
            $nexturl = constant('BASE_URL') . '/';
214
            print 'Please try later or <a href="' . $nexturl . '">click here to change login user</a>...' . "\n";
215
        }
216
        exit;
217
    }
218
}
219
220
221
// Activate end of page function
222
register_shutdown_function('dol_shutdown');
223
224
// Load debugbar
225
if (isModEnabled('debugbar') && !GETPOST('dol_use_jmobile') && empty($_SESSION['dol_use_jmobile'])) {
226
    global $debugbar;
227
228
    $debugbar = new Debug();
229
    $renderer = $debugbar->getJavascriptRenderer();
230
    if (!getDolGlobalString('MAIN_HTML_HEADER')) {
231
        $conf->global->MAIN_HTML_HEADER = '';
232
    }
233
    $conf->global->MAIN_HTML_HEADER .= $renderer->renderHead();
234
235
    $debugbar['time']->startMeasure('pageaftermaster', 'Page generation (after environment init)');
0 ignored issues
show
The method startMeasure() does not exist on DebugBar\DataCollector\DataCollectorInterface. It seems like you code against a sub-type of DebugBar\DataCollector\DataCollectorInterface such as DebugBar\DataCollector\TimeDataCollector. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

235
    $debugbar['time']->/** @scrutinizer ignore-call */ 
236
                       startMeasure('pageaftermaster', 'Page generation (after environment init)');
Loading history...
236
}
237
238
// Detection browser
239
if (isset($_SERVER["HTTP_USER_AGENT"])) {
240
    $tmp = getBrowserInfo($_SERVER["HTTP_USER_AGENT"]);
241
    $conf->browser->name = $tmp['browsername'];
242
    $conf->browser->os = $tmp['browseros'];
243
    $conf->browser->version = $tmp['browserversion'];
244
    $conf->browser->ua = $tmp['browserua'];
245
    $conf->browser->layout = $tmp['layout']; // 'classic', 'phone', 'tablet'
246
    //var_dump($conf->browser);
247
248
    if ($conf->browser->layout == 'phone') {
249
        $conf->dol_no_mouse_hover = 1;
250
    }
251
}
252
253
// If theme is forced
254
if (GETPOST('theme', 'aZ09')) {
255
    $conf->theme = GETPOST('theme', 'aZ09');
256
    $conf->css = "/theme/" . $conf->theme . "/style.css.php";
257
}
258
259
// Set global MAIN_OPTIMIZEFORTEXTBROWSER (must be before login part)
260
if (GETPOSTINT('textbrowser') || (!empty($conf->browser->name) && $conf->browser->name == 'lynxlinks')) {   // If we must enable text browser
261
    $conf->global->MAIN_OPTIMIZEFORTEXTBROWSER = 2;
262
}
263
264
// Force HTTPS if required ($conf->file->main_force_https is 0/1 or 'https dolibarr root url')
265
// $_SERVER["HTTPS"] is 'on' when link is https, otherwise $_SERVER["HTTPS"] is empty or 'off'
266
if (!empty($conf->file->main_force_https) && !isHTTPS() && !defined('NOHTTPSREDIRECT')) {
267
    $newurl = '';
268
    if (is_numeric($conf->file->main_force_https)) {
269
        if ($conf->file->main_force_https == '1' && !empty($_SERVER["SCRIPT_URI"])) {   // If SCRIPT_URI supported by server
270
            if (preg_match('/^http:/i', $_SERVER["SCRIPT_URI"]) && !preg_match('/^https:/i', $_SERVER["SCRIPT_URI"])) { // If link is http
271
                $newurl = preg_replace('/^http:/i', 'https:', $_SERVER["SCRIPT_URI"]);
272
            }
273
        } else {
274
            // If HTTPS is not defined in DOL_MAIN_URL_ROOT,
275
            // Check HTTPS environment variable (Apache/mod_ssl only)
276
            $newurl = preg_replace('/^http:/i', 'https:', DOL_MAIN_URL_ROOT) . $_SERVER["REQUEST_URI"];
277
        }
278
    } else {
279
        // Check HTTPS environment variable (Apache/mod_ssl only)
280
        $newurl = $conf->file->main_force_https . $_SERVER["REQUEST_URI"];
281
    }
282
    // Start redirect
283
    if ($newurl) {
284
        header_remove(); // Clean header already set to be sure to remove any header like "Set-Cookie: DOLSESSID_..." from non HTTPS answers
285
        dol_syslog("main.inc: dolibarr_main_force_https is on, we make a redirect to " . $newurl);
286
        header("Location: " . $newurl);
287
        exit;
288
    } else {
289
        dol_syslog("main.inc: dolibarr_main_force_https is on but we failed to forge new https url so no redirect is done", LOG_WARNING);
290
    }
291
}
292
293
if (!defined('NOLOGIN') && !defined('NOIPCHECK') && !empty($dolibarr_main_restrict_ip)) {
294
    $listofip = explode(',', $dolibarr_main_restrict_ip);
295
    $found = false;
296
    foreach ($listofip as $ip) {
297
        $ip = trim($ip);
298
        if ($ip == $_SERVER['REMOTE_ADDR']) {
299
            $found = true;
300
            break;
301
        }
302
    }
303
    if (!$found) {
304
        print 'Access refused by IP protection. Your detected IP is ' . $_SERVER['REMOTE_ADDR'];
305
        exit;
306
    }
307
}
308
309
// Loading of additional presentation includes
310
if (!defined('NOREQUIREAJAX')) {
311
    require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/ajax.lib.php'; // Need 22ko memory
312
}
313
314
// If install or upgrade process not done or not completely finished, we call the install page.
315
if (getDolGlobalString('MAIN_NOT_INSTALLED') || getDolGlobalString('MAIN_NOT_UPGRADED')) {
316
    dol_syslog("main.inc: A previous install or upgrade was not complete. Redirect to install page.", LOG_WARNING);
317
    header("Location: " . constant('BASE_URL') . "/install/index.php");
318
    exit;
319
}
320
// If an upgrade process is required, we call the install page.
321
$checkifupgraderequired = false;
322
if (getDolGlobalString('MAIN_VERSION_LAST_UPGRADE') && getDolGlobalString('MAIN_VERSION_LAST_UPGRADE') != DOL_VERSION) {
323
    $checkifupgraderequired = true;
324
}
325
if (!getDolGlobalString('MAIN_VERSION_LAST_UPGRADE') && getDolGlobalString('MAIN_VERSION_LAST_INSTALL') && getDolGlobalString('MAIN_VERSION_LAST_INSTALL') != DOL_VERSION) {
326
    $checkifupgraderequired = true;
327
}
328
if ($checkifupgraderequired) {
329
    $versiontocompare = getDolGlobalString('MAIN_VERSION_LAST_UPGRADE', getDolGlobalString('MAIN_VERSION_LAST_INSTALL'));
330
    require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/admin.lib.php';
331
    $dolibarrversionlastupgrade = preg_split('/[.-]/', $versiontocompare);
332
    $dolibarrversionprogram = preg_split('/[.-]/', DOL_VERSION);
333
    $rescomp = Version::compare($dolibarrversionprogram, $dolibarrversionlastupgrade);
334
    if ($rescomp > 0) {   // Programs have a version higher than database.
335
        if (!getDolGlobalString('MAIN_NO_UPGRADE_REDIRECT_ON_LEVEL_3_CHANGE') || $rescomp < 3) {
336
            // We did not add "&& $rescomp < 3" because we want upgrade process for build upgrades
337
            dol_syslog("main.inc: database version " . $versiontocompare . " is lower than programs version " . DOL_VERSION . ". Redirect to install/upgrade page.", LOG_WARNING);
338
            if (php_sapi_name() === "cli") {
339
                print "main.inc: database version " . $versiontocompare . " is lower than programs version " . DOL_VERSION . ". Try to run upgrade process.\n";
340
            } else {
341
                header("Location: " . constant('BASE_URL') . "/install/index.php");
342
            }
343
            exit;
344
        }
345
    }
346
}
347
348
// Creation of a token against CSRF vulnerabilities
349
if (!defined('NOTOKENRENEWAL') && !defined('NOSESSION')) {
350
    // No token renewal on .css.php, .js.php and .json.php (even if the NOTOKENRENEWAL was not provided)
351
    if (!preg_match('/\.(css|js|json)\.php$/', $_SERVER["PHP_SELF"])) {
352
        // Rolling token at each call ($_SESSION['token'] contains token of previous page)
353
        if (isset($_SESSION['newtoken'])) {
354
            $_SESSION['token'] = $_SESSION['newtoken'];
355
        }
356
357
        if (!isset($_SESSION['newtoken']) || getDolGlobalInt('MAIN_SECURITY_CSRF_TOKEN_RENEWAL_ON_EACH_CALL')) {
358
            // Note: Using MAIN_SECURITY_CSRF_TOKEN_RENEWAL_ON_EACH_CALL is not recommended: if a user succeed in entering a data from
359
            // a public page with a link that make a token regeneration, it can make use of the backoffice no more possible !
360
            // Save in $_SESSION['newtoken'] what will be next token. Into forms, we will add param token = $_SESSION['newtoken']
361
            $token = dol_hash(uniqid((string)mt_rand(), false), 'md5'); // Generates a hash of a random number. We don't need a secured hash, just a changing random value.
362
            $_SESSION['newtoken'] = $token;
363
            dol_syslog("NEW TOKEN generated by : " . $_SERVER['PHP_SELF'], LOG_DEBUG);
364
        }
365
    }
366
}
367
368
//dol_syslog("CSRF info: ".defined('NOCSRFCHECK')." - ".$dolibarr_nocsrfcheck." - ".$conf->global->MAIN_SECURITY_CSRF_WITH_TOKEN." - ".$_SERVER['REQUEST_METHOD']." - ".GETPOST('token', 'alpha'));
369
370
// Check validity of token, only if option MAIN_SECURITY_CSRF_WITH_TOKEN enabled or if constant CSRFCHECK_WITH_TOKEN is set into page
371
if ((!defined('NOCSRFCHECK') && empty($dolibarr_nocsrfcheck) && getDolGlobalInt('MAIN_SECURITY_CSRF_WITH_TOKEN')) || defined('CSRFCHECK_WITH_TOKEN')) {
372
    // Array of action code where CSRFCHECK with token will be forced (so token must be provided on url request)
373
    $sensitiveget = false;
374
    if ((GETPOSTISSET('massaction') || GETPOST('action', 'aZ09')) && getDolGlobalInt('MAIN_SECURITY_CSRF_WITH_TOKEN') >= 3) {
375
        // All GET actions (except the listed exceptions that are usually post for pre-actions and not real action) and mass actions are processed as sensitive.
376
        if (GETPOSTISSET('massaction') || !in_array(GETPOST('action', 'aZ09'), array('create', 'createsite', 'createcard', 'edit', 'editvalidator', 'file_manager', 'presend', 'presend_addmessage', 'preview', 'specimen'))) { // We exclude some action that are not sensitive so legitimate
377
            $sensitiveget = true;
378
        }
379
    } elseif (getDolGlobalInt('MAIN_SECURITY_CSRF_WITH_TOKEN') >= 2) {
380
        // Few GET actions coded with a &token into url are also processed as sensitive.
381
        $arrayofactiontoforcetokencheck = array(
382
            'activate',
383
            'doprev', 'donext', 'dvprev', 'dvnext',
384
            'freezone', 'install',
385
            'reopen'
386
        );
387
        if (in_array(GETPOST('action', 'aZ09'), $arrayofactiontoforcetokencheck)) {
388
            $sensitiveget = true;
389
        }
390
        // We also need a valid token for actions matching one of these values
391
        if (preg_match('/^(confirm_)?(add|classify|close|confirm|copy|del|disable|enable|remove|set|unset|update|save)/', GETPOST('action', 'aZ09'))) {
392
            $sensitiveget = true;
393
        }
394
    }
395
396
    // Check a token is provided for all cases that need a mandatory token
397
    // (all POST actions + all sensitive GET actions + all mass actions + all login/actions/logout on pages with CSRFCHECK_WITH_TOKEN set)
398
    if (
399
        (!empty($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST') ||
400
        $sensitiveget ||
401
        GETPOSTISSET('massaction') ||
402
        ((GETPOSTISSET('actionlogin') || GETPOSTISSET('action')) && defined('CSRFCHECK_WITH_TOKEN'))
403
    ) {
404
        // If token is not provided or empty, error (we are in case it is mandatory)
405
        if (!GETPOST('token', 'alpha') || GETPOST('token', 'alpha') == 'notrequired') {
406
            ViewMain::topHttpHead();
407
            if (GETPOSTINT('uploadform')) {
408
                dol_syslog("--- Access to " . (empty($_SERVER["REQUEST_METHOD"]) ? '' : $_SERVER["REQUEST_METHOD"] . ' ') . $_SERVER["PHP_SELF"] . " refused. File size too large or not provided.");
409
                $langs->loadLangs(array("errors", "install"));
410
                print $langs->trans("ErrorFileSizeTooLarge") . ' ';
411
                print $langs->trans("ErrorGoBackAndCorrectParameters");
412
            } else {
413
                http_response_code(403);
414
                if (defined('CSRFCHECK_WITH_TOKEN')) {
415
                    dd(['debug_backtrace in CSRF error in main.inc.php ' => debug_backtrace()]);
416
                    dol_syslog("--- Access to " . (empty($_SERVER["REQUEST_METHOD"]) ? '' : $_SERVER["REQUEST_METHOD"] . ' ') . $_SERVER["PHP_SELF"] . " refused by CSRF protection (CSRFCHECK_WITH_TOKEN protection) in main.inc.php. Token not provided.", LOG_WARNING);
417
                    print "Access to a page that needs a token (constant CSRFCHECK_WITH_TOKEN is defined) is refused by CSRF protection in main.inc.php. Token not provided.\n";
418
                } else {
419
                    dol_syslog("--- Access to " . (empty($_SERVER["REQUEST_METHOD"]) ? '' : $_SERVER["REQUEST_METHOD"] . ' ') . $_SERVER["PHP_SELF"] . " refused by CSRF protection (POST method or GET with a sensible value for 'action' parameter) in main.inc.php. Token not provided.", LOG_WARNING);
420
                    print "Access to this page this way (POST method or GET with a sensible value for 'action' parameter) is refused by CSRF protection in main.inc.php. Token not provided.\n";
421
                    print "If you access your server behind a proxy using url rewriting and the parameter is provided by caller, you might check that all HTTP header are propagated (or add the line \$dolibarr_nocsrfcheck=1 into your conf.php file or MAIN_SECURITY_CSRF_WITH_TOKEN to 0";
422
                    if (getDolGlobalString('MAIN_SECURITY_CSRF_WITH_TOKEN')) {
423
                        print " instead of " . getDolGlobalString('MAIN_SECURITY_CSRF_WITH_TOKEN');
424
                    }
425
                    print " into setup).\n";
426
                }
427
            }
428
            die;
429
        }
430
    }
431
432
    $sessiontokenforthisurl = (empty($_SESSION['token']) ? '' : $_SESSION['token']);
433
    // TODO Get the sessiontokenforthisurl into an array of session token (one array per base URL so we can use the CSRF per page and we keep ability for several tabs per url in a browser)
434
    if (GETPOSTISSET('token') && GETPOST('token') != 'notrequired' && GETPOST('token', 'alpha') != $sessiontokenforthisurl) {
435
        dol_syslog("--- Access to " . (empty($_SERVER["REQUEST_METHOD"]) ? '' : $_SERVER["REQUEST_METHOD"] . ' ') . $_SERVER["PHP_SELF"] . " refused by CSRF protection (invalid token), so we disable POST and some GET parameters - referrer=" . (empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFERER']) . ", action=" . GETPOST('action', 'aZ09') . ", _GET|POST['token']=" . GETPOST('token', 'alpha'), LOG_WARNING);
436
        //dol_syslog("_SESSION['token']=".$sessiontokenforthisurl, LOG_DEBUG);
437
        // Do not output anything on standard output because this create problems when using the BACK button on browsers. So we just set a message into session.
438
        if (!defined('NOTOKENRENEWAL')) {
439
            // If the page is not a page that disable the token renewal, we report a warning message to explain token has epired.
440
            setEventMessages('SecurityTokenHasExpiredSoActionHasBeenCanceledPleaseRetry', null, 'warnings', '', 1);
441
        }
442
        $savid = null;
443
        if (isset($_POST['id'])) {
444
            $savid = ((int)$_POST['id']);
445
        }
446
        unset($_POST);
447
        unset($_GET['confirm']);
448
        unset($_GET['action']);
449
        unset($_GET['confirmmassaction']);
450
        unset($_GET['massaction']);
451
        unset($_GET['token']);          // TODO Make a redirect if we have a token in url to remove it ?
452
        if (isset($savid)) {
453
            $_POST['id'] = ((int)$savid);
454
        }
455
        // So rest of code can know something was wrong here
456
        $_GET['errorcode'] = 'InvalidToken';
457
    }
458
459
    // Note: There is another CSRF protection into the filefunc.inc.php
460
}
461
462
// Disable modules (this must be after session_start and after conf has been loaded)
463
if (GETPOSTISSET('disablemodules')) {
464
    $_SESSION["disablemodules"] = GETPOST('disablemodules', 'alpha');
465
}
466
if (!empty($_SESSION["disablemodules"])) {
467
    $modulepartkeys = array('css', 'js', 'tabs', 'triggers', 'login', 'substitutions', 'menus', 'theme', 'sms', 'tpl', 'barcode', 'models', 'societe', 'hooks', 'dir', 'syslog', 'tpllinkable', 'contactelement', 'moduleforexternal', 'websitetemplates');
468
469
    $disabled_modules = explode(',', $_SESSION["disablemodules"]);
470
    foreach ($disabled_modules as $module) {
471
        if ($module) {
472
            if (empty($conf->$module)) {
473
                $conf->$module = new stdClass(); // To avoid warnings
474
            }
475
            $conf->$module->enabled = false;
476
            foreach ($modulepartkeys as $modulepartkey) {
477
                unset($conf->modules_parts[$modulepartkey][$module]);
478
            }
479
            if ($module == 'fournisseur') {     // Special case
480
                $conf->supplier_order->enabled = 0;
481
                $conf->supplier_invoice->enabled = 0;
482
            }
483
        }
484
    }
485
}
486
487
// Set current modulepart
488
$modulepart = explode("/", $_SERVER["PHP_SELF"]);
489
if (is_array($modulepart) && count($modulepart) > 0) {
490
    foreach ($conf->modules as $module) {
491
        if (in_array($module, $modulepart)) {
492
            $modulepart = $module;
493
            break;
494
        }
495
    }
496
}
497
if (is_array($modulepart)) {
498
    $modulepart = '';
499
}
500
501
502
/*
503
 * Phase authentication / login
504
 */
505
506
$login = '';
507
$error = 0;
508
if (!defined('NOLOGIN')) {
509
    // $authmode lists the different method of identification to be tested in order of preference.
510
    // Example: 'http', 'dolibarr', 'ldap', 'http,forceuser', '...'
511
512
    if (defined('MAIN_AUTHENTICATION_MODE')) {
513
        $dolibarr_main_authentication = constant('MAIN_AUTHENTICATION_MODE');
514
    } else {
515
        // Authentication mode
516
        if (empty($dolibarr_main_authentication)) {
517
            $dolibarr_main_authentication = 'dolibarr';
518
        }
519
        // Authentication mode: forceuser
520
        if ($dolibarr_main_authentication == 'forceuser' && empty($dolibarr_auto_user)) {
521
            $dolibarr_auto_user = 'auto';
522
        }
523
    }
524
    // Set authmode
525
    $authmode = explode(',', $dolibarr_main_authentication);
526
527
    // No authentication mode
528
    if (!count($authmode)) {
529
        $langs->load('main');
530
        dol_print_error(null, $langs->trans("ErrorConfigParameterNotDefined", 'dolibarr_main_authentication'));
531
        exit;
532
    }
533
534
    // If login request was already post, we retrieve login from the session
535
    // Call module if not realized that his request.
536
    // At the end of this phase, the variable $login is defined.
537
    $resultFetchUser = '';
538
    $test = true;
539
    if (!isset($_SESSION["dol_login"])) {
540
        // It is not already authenticated and it requests the login / password
541
        include_once DOL_DOCUMENT_ROOT . '/core/lib/security2.lib.php';
542
543
        $dol_dst_observed = GETPOSTINT("dst_observed", 3);
544
        $dol_dst_first = GETPOSTINT("dst_first", 3);
545
        $dol_dst_second = GETPOSTINT("dst_second", 3);
546
        $dol_screenwidth = GETPOSTINT("screenwidth", 3);
547
        $dol_screenheight = GETPOSTINT("screenheight", 3);
548
        $dol_hide_topmenu = GETPOSTINT('dol_hide_topmenu', 3);
549
        $dol_hide_leftmenu = GETPOSTINT('dol_hide_leftmenu', 3);
550
        $dol_optimize_smallscreen = GETPOSTINT('dol_optimize_smallscreen', 3);
551
        $dol_no_mouse_hover = GETPOSTINT('dol_no_mouse_hover', 3);
552
        $dol_use_jmobile = GETPOSTINT('dol_use_jmobile', 3); // 0=default, 1=to say we use app from a webview app, 2=to say we use app from a webview app and keep ajax
553
554
        // If in demo mode, we check we go to home page through the public/demo/index.php page
555
        if (!empty($dolibarr_main_demo) && $_SERVER['PHP_SELF'] == constant('BASE_URL') . '/index.php') {  // We ask index page
556
            if (empty($_SERVER['HTTP_REFERER']) || !preg_match('/public/', $_SERVER['HTTP_REFERER'])) {
557
                dol_syslog("Call index page from another url than demo page (call is done from page " . (empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['HTTP_REFER']) . ")");
558
                $url = '';
559
                $url .= ($url ? '&' : '') . ($dol_hide_topmenu ? 'dol_hide_topmenu=' . $dol_hide_topmenu : '');
560
                $url .= ($url ? '&' : '') . ($dol_hide_leftmenu ? 'dol_hide_leftmenu=' . $dol_hide_leftmenu : '');
561
                $url .= ($url ? '&' : '') . ($dol_optimize_smallscreen ? 'dol_optimize_smallscreen=' . $dol_optimize_smallscreen : '');
562
                $url .= ($url ? '&' : '') . ($dol_no_mouse_hover ? 'dol_no_mouse_hover=' . $dol_no_mouse_hover : '');
563
                $url .= ($url ? '&' : '') . ($dol_use_jmobile ? 'dol_use_jmobile=' . $dol_use_jmobile : '');
564
                $url = constant('BASE_URL') . '/public/demo/index.php' . ($url ? '?' . $url : '');
565
                header("Location: " . $url);
566
                exit;
567
            }
568
        }
569
570
        // Hooks for security access
571
        $action = '';
572
        $hookmanager->initHooks(array('login'));
573
        $parameters = array();
574
        $reshook = $hookmanager->executeHooks('beforeLoginAuthentication', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
575
        if ($reshook < 0) {
576
            $test = false;
577
            $error++;
578
        }
579
580
        // Verification security graphic code
581
        if ($test && GETPOST("username", "alpha", 2) && getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA') && !isset($_SESSION['dol_bypass_antispam'])) {
582
            $sessionkey = 'dol_antispam_value';
583
            $ok = (array_key_exists($sessionkey, $_SESSION) === true && (strtolower($_SESSION[$sessionkey]) === strtolower(GETPOST('code', 'restricthtml'))));
584
585
            // Check code
586
            if (!$ok) {
587
                dol_syslog('Bad value for code, connection refused', LOG_NOTICE);
588
                // Load translation files required by page
589
                $langs->loadLangs(array('main', 'errors'));
590
591
                $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorBadValueForCode");
592
                $test = false;
593
594
                // Call trigger for the "security events" log
595
                $user->context['audit'] = 'ErrorBadValueForCode - login=' . GETPOST("username", "alpha", 2);
596
597
                // Call trigger
598
                $result = $user->call_trigger('USER_LOGIN_FAILED', $user);
599
                if ($result < 0) {
600
                    $error++;
601
                }
602
                // End call triggers
603
604
                // Hooks on failed login
605
                $action = '';
606
                $hookmanager->initHooks(array('login'));
607
                $parameters = array('dol_authmode' => $authmode, 'dol_loginmesg' => $_SESSION["dol_loginmesg"]);
608
                $reshook = $hookmanager->executeHooks('afterLoginFailed', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
609
                if ($reshook < 0) {
610
                    $error++;
611
                }
612
613
                // Note: exit is done later
614
            }
615
        }
616
617
        $allowedmethodtopostusername = 3;
618
        if (defined('MAIN_AUTHENTICATION_POST_METHOD')) {
619
            $allowedmethodtopostusername = constant('MAIN_AUTHENTICATION_POST_METHOD'); // Note a value of 2 is not compatible with some authentication methods that put username as GET parameter
620
        }
621
        // TODO Remove use of $_COOKIE['login_dolibarr'] ? Replace $usertotest = with $usertotest = GETPOST("username", "alpha", $allowedmethodtopostusername);
622
        $usertotest = (!empty($_COOKIE['login_dolibarr']) ? preg_replace('/[^a-zA-Z0-9_@\-\.]/', '', $_COOKIE['login_dolibarr']) : GETPOST("username", "alpha", $allowedmethodtopostusername));
623
        $passwordtotest = GETPOST('password', 'none', $allowedmethodtopostusername);
624
        $entitytotest = (GETPOSTINT('entity') ? GETPOSTINT('entity') : (!empty($conf->entity) ? $conf->entity : 1));
625
626
        // Define if we received the correct data to go into the test of the login with the checkLoginPassEntity().
627
        $goontestloop = false;
628
        if (isset($_SERVER["REMOTE_USER"]) && in_array('http', $authmode)) {    // For http basic login test
629
            $goontestloop = true;
630
        }
631
        if ($dolibarr_main_authentication == 'forceuser' && !empty($dolibarr_auto_user)) {  // For automatic login with a forced user
632
            $goontestloop = true;
633
        }
634
        if (GETPOST("username", "alpha", $allowedmethodtopostusername)) {   // For posting the login form
635
            $goontestloop = true;
636
        }
637
        if (GETPOST('openid_mode', 'alpha', 1)) {   // For openid_connect ?
638
            $goontestloop = true;
639
        }
640
        if (GETPOST('beforeoauthloginredirect') || GETPOST('afteroauthloginreturn')) {  // For oauth login
641
            $goontestloop = true;
642
        }
643
        if (!empty($_COOKIE['login_dolibarr'])) {   // TODO For ? Remove this ?
644
            $goontestloop = true;
645
        }
646
647
        if (!is_object($langs)) { // This can occurs when calling page with NOREQUIRETRAN defined, however we need langs for error messages.
648
            $langs = new Translate("", $conf);
649
            $langcode = (GETPOST('lang', 'aZ09', 1) ? GETPOST('lang', 'aZ09', 1) : getDolGlobalString('MAIN_LANG_DEFAULT', 'auto'));
650
            if (defined('MAIN_LANG_DEFAULT')) {
651
                $langcode = constant('MAIN_LANG_DEFAULT');
652
            }
653
            $langs->setDefaultLang($langcode);
654
        }
655
656
        // Validation of login/pass/entity
657
        // If ok, the variable login will be returned
658
        // If error, we will put error message in session under the name dol_loginmesg
659
        if ($test && $goontestloop && (GETPOST('actionlogin', 'aZ09') == 'login' || $dolibarr_main_authentication != 'dolibarr')) {
660
            // Loop on each test mode defined into $authmode
661
            // $authmode is an array for example: array('0'=>'dolibarr', '1'=>'googleoauth');
662
            $oauthmodetotestarray = array('google');
663
            foreach ($oauthmodetotestarray as $oauthmodetotest) {
664
                if (in_array($oauthmodetotest . 'oauth', $authmode)) {    // This is an authmode that is currently qualified. Do we have to remove it ?
665
                    // If we click on the link to use OAuth authentication or if we goes after callback return, we do nothing
666
                    if (GETPOST('beforeoauthloginredirect') == $oauthmodetotest || GETPOST('afteroauthloginreturn')) {
667
                        // TODO Use: if (GETPOST('beforeoauthloginredirect') == $oauthmodetotest || GETPOST('afteroauthloginreturn') == $oauthmodetotest) {
668
                        continue;
669
                    }
670
                    dol_syslog("User did not click on link for OAuth or is not on the OAuth return, so we disable check using " . $oauthmodetotest);
671
                    foreach ($authmode as $tmpkey => $tmpval) {
672
                        if ($tmpval == $oauthmodetotest . 'oauth') {
673
                            unset($authmode[$tmpkey]);
674
                            break;
675
                        }
676
                    }
677
                }
678
            }
679
680
            // Check login for all qualified modes in array $authmode.
681
            $login = checkLoginPassEntity($usertotest, $passwordtotest, $entitytotest, $authmode);
682
            if ($login === '--bad-login-validity--') {
683
                $login = '';
684
            }
685
686
            $dol_authmode = '';
687
688
            if ($login) {
689
                $dol_authmode = $conf->authmode; // This properties is defined only when logged, to say what mode was successfully used
690
                $dol_tz = empty($_POST["tz"]) ? (empty($_SESSION["tz"]) ? '' : $_SESSION["tz"]) : $_POST["tz"];
691
                $dol_tz_string = empty($_POST["tz_string"]) ? (empty($_SESSION["tz_string"]) ? '' : $_SESSION["tz_string"]) : $_POST["tz_string"];
692
                $dol_tz_string = preg_replace('/\s*\(.+\)$/', '', $dol_tz_string);
693
                $dol_tz_string = preg_replace('/,/', '/', $dol_tz_string);
694
                $dol_tz_string = preg_replace('/\s/', '_', $dol_tz_string);
695
                $dol_dst = 0;
696
                // Keep $_POST here. Do not use GETPOSTISSET
697
                $dol_dst_first = empty($_POST["dst_first"]) ? (empty($_SESSION["dst_first"]) ? '' : $_SESSION["dst_first"]) : $_POST["dst_first"];
698
                $dol_dst_second = empty($_POST["dst_second"]) ? (empty($_SESSION["dst_second"]) ? '' : $_SESSION["dst_second"]) : $_POST["dst_second"];
699
                if ($dol_dst_first && $dol_dst_second) {
700
                    include_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
701
                    $datenow = dol_now();
702
                    $datefirst = dol_stringtotime($dol_dst_first);
703
                    $datesecond = dol_stringtotime($dol_dst_second);
704
                    if ($datenow >= $datefirst && $datenow < $datesecond) {
705
                        $dol_dst = 1;
706
                    }
707
                }
708
                $dol_screenheight = empty($_POST["screenheight"]) ? (empty($_SESSION["dol_screenheight"]) ? '' : $_SESSION["dol_screenheight"]) : $_POST["screenheight"];
709
                $dol_screenwidth = empty($_POST["screenwidth"]) ? (empty($_SESSION["dol_screenwidth"]) ? '' : $_SESSION["dol_screenwidth"]) : $_POST["screenwidth"];
710
                //print $datefirst.'-'.$datesecond.'-'.$datenow.'-'.$dol_tz.'-'.$dol_tzstring.'-'.$dol_dst.'-'.sdol_screenheight.'-'.sdol_screenwidth; exit;
711
            }
712
713
            if (!$login) {
714
                dol_syslog('Bad password, connection refused (see a previous notice message for more info)', LOG_NOTICE);
715
                // Load translation files required by page
716
                $langs->loadLangs(array('main', 'errors'));
717
718
                // Bad password. No authmode has found a good password.
719
                // We set a generic message if not defined inside function checkLoginPassEntity or subfunctions
720
                if (empty($_SESSION["dol_loginmesg"])) {
721
                    $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorBadLoginPassword");
722
                }
723
724
                // Call trigger for the "security events" log
725
                $user->context['audit'] = $langs->trans("ErrorBadLoginPassword") . ' - login=' . GETPOST("username", "alpha", 2);
726
727
                // Call trigger
728
                $result = $user->call_trigger('USER_LOGIN_FAILED', $user);
729
                if ($result < 0) {
730
                    $error++;
731
                }
732
                // End call triggers
733
734
                // Hooks on failed login
735
                $action = '';
736
                $hookmanager->initHooks(array('login'));
737
                $parameters = array('dol_authmode' => $dol_authmode, 'dol_loginmesg' => $_SESSION["dol_loginmesg"]);
738
                $reshook = $hookmanager->executeHooks('afterLoginFailed', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
739
                if ($reshook < 0) {
740
                    $error++;
741
                }
742
743
                // Note: exit is done in next chapter
744
            }
745
        }
746
747
        // End test login / passwords
748
        if (!$login || (in_array('ldap', $authmode) && empty($passwordtotest))) {   // With LDAP we refused empty password because some LDAP are "opened" for anonymous access so connection is a success.
749
            // No data to test login, so we show the login page.
750
            dol_syslog("--- Access to " . (empty($_SERVER["REQUEST_METHOD"]) ? '' : $_SERVER["REQUEST_METHOD"] . ' ') . $_SERVER["PHP_SELF"] . " - action=" . GETPOST('action', 'aZ09') . " - actionlogin=" . GETPOST('actionlogin', 'aZ09') . " - showing the login form and exit", LOG_NOTICE);
751
            if (defined('NOREDIRECTBYMAINTOLOGIN')) {
752
                // When used with NOREDIRECTBYMAINTOLOGIN set, the http header must already be set when including the main.
753
                // See example with selectsearchbox.php. This case is reserved for the selectesearchbox.php so we can
754
                // report a message to ask to login when search ajax component is used after a timeout.
755
                //ViewMain::topHttpHead();
756
                return 'ERROR_NOT_LOGGED';
757
            } else {
758
                if (!empty($_SERVER["HTTP_USER_AGENT"]) && $_SERVER["HTTP_USER_AGENT"] == 'securitytest') {
759
                    http_response_code(401); // It makes easier to understand if session was broken during security tests
760
                }
761
                dol_loginfunction($langs, $conf, (!empty($mysoc) ? $mysoc : ''));   // This include http headers
762
            }
763
            exit;
764
        }
765
766
        $resultFetchUser = $user->fetch('', $login, '', 1, ($entitytotest > 0 ? $entitytotest : -1)); // value for $login was retrieved previously when checking password.
767
        if ($resultFetchUser <= 0 || $user->isNotIntoValidityDateRange()) {
768
            dol_syslog('User not found or not valid, connection refused');
769
            session_destroy();
770
            session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie
771
            session_name($sessionname);
772
            dol_session_start();
773
774
            if ($resultFetchUser == 0) {
775
                // Load translation files required by page
776
                $langs->loadLangs(array('main', 'errors'));
777
778
                $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorCantLoadUserFromDolibarrDatabase", $login);
779
780
                $user->context['audit'] = 'ErrorCantLoadUserFromDolibarrDatabase - login=' . $login;
781
            } elseif ($resultFetchUser < 0) {
782
                $_SESSION["dol_loginmesg"] = $user->error;
783
784
                $user->context['audit'] = $user->error;
785
            } else {
786
                // Load translation files required by the page
787
                $langs->loadLangs(array('main', 'errors'));
788
789
                $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorLoginDateValidity");
790
791
                $user->context['audit'] = $langs->trans("ErrorLoginDateValidity") . ' - login=' . $login;
792
            }
793
794
            // Call trigger
795
            $result = $user->call_trigger('USER_LOGIN_FAILED', $user);
796
            if ($result < 0) {
797
                $error++;
798
            }
799
            // End call triggers
800
801
802
            // Hooks on failed login
803
            $action = '';
804
            $hookmanager->initHooks(array('login'));
805
            $parameters = array('dol_authmode' => $dol_authmode, 'dol_loginmesg' => $_SESSION["dol_loginmesg"]);
806
            $reshook = $hookmanager->executeHooks('afterLoginFailed', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
807
            if ($reshook < 0) {
808
                $error++;
809
            }
810
811
            $paramsurl = array();
812
            if (GETPOSTINT('textbrowser')) {
813
                $paramsurl[] = 'textbrowser=' . GETPOSTINT('textbrowser');
814
            }
815
            if (GETPOSTINT('nojs')) {
816
                $paramsurl[] = 'nojs=' . GETPOSTINT('nojs');
817
            }
818
            if (GETPOST('lang', 'aZ09')) {
819
                $paramsurl[] = 'lang=' . GETPOST('lang', 'aZ09');
820
            }
821
            header('Location: ' . constant('BASE_URL') . '/index.php' . (count($paramsurl) ? '?' . implode('&', $paramsurl) : ''));
822
            exit;
823
        } else {
824
            // User is loaded, we may need to change language for him according to its choice
825
            if (!empty($user->conf->MAIN_LANG_DEFAULT)) {
826
                $langs->setDefaultLang($user->conf->MAIN_LANG_DEFAULT);
827
            }
828
        }
829
    } else {
830
        // We are already into an authenticated session
831
        $login = $_SESSION["dol_login"];
832
        $entity = isset($_SESSION["dol_entity"]) ? $_SESSION["dol_entity"] : 0;
833
        dol_syslog("- This is an already logged session. _SESSION['dol_login']=" . $login . " _SESSION['dol_entity']=" . $entity, LOG_DEBUG);
834
835
        $resultFetchUser = $user->fetch('', $login, '', 1, ($entity > 0 ? $entity : -1));
836
837
        //var_dump(dol_print_date($user->flagdelsessionsbefore, 'dayhour', 'gmt')." ".dol_print_date($_SESSION["dol_logindate"], 'dayhour', 'gmt'));
838
839
        if (
840
            $resultFetchUser <= 0
841
            || ($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"])
842
            || ($user->status != $user::STATUS_ENABLED)
843
            || ($user->isNotIntoValidityDateRange())
844
        ) {
845
            if ($resultFetchUser <= 0) {
846
                // Account has been removed after login
847
                dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=" . $login, LOG_WARNING);
848
            } elseif ($user->flagdelsessionsbefore && !empty($_SESSION["dol_logindate"]) && $user->flagdelsessionsbefore > $_SESSION["dol_logindate"]) {
849
                // Session is no more valid
850
                dol_syslog("The user has a date for session invalidation = " . $user->flagdelsessionsbefore . " and a session date = " . $_SESSION["dol_logindate"] . ". We must invalidate its sessions.");
851
            } elseif ($user->status != $user::STATUS_ENABLED) {
852
                // User is not enabled
853
                dol_syslog("The user login is disabled");
854
            } else {
855
                // User validity dates are no more valid
856
                dol_syslog("The user login has a validity between [" . $user->datestartvalidity . " and " . $user->dateendvalidity . "], current date is " . dol_now());
857
            }
858
            session_destroy();
859
            session_set_cookie_params(0, '/', null, (empty($dolibarr_main_force_https) ? false : true), true); // Add tag secure and httponly on session cookie
860
            session_name($sessionname);
861
            dol_session_start();
862
863
            if ($resultFetchUser == 0) {
864
                $langs->loadLangs(array('main', 'errors'));
865
866
                $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorCantLoadUserFromDolibarrDatabase", $login);
867
868
                $user->context['audit'] = 'ErrorCantLoadUserFromDolibarrDatabase - login=' . $login;
869
            } elseif ($resultFetchUser < 0) {
870
                $_SESSION["dol_loginmesg"] = $user->error;
871
872
                $user->context['audit'] = $user->error;
873
            } else {
874
                $langs->loadLangs(array('main', 'errors'));
875
876
                $_SESSION["dol_loginmesg"] = $langs->transnoentitiesnoconv("ErrorSessionInvalidatedAfterPasswordChange");
877
878
                $user->context['audit'] = 'ErrorUserSessionWasInvalidated - login=' . $login;
879
            }
880
881
            // Call trigger
882
            $result = $user->call_trigger('USER_LOGIN_FAILED', $user);
883
            if ($result < 0) {
884
                $error++;
885
            }
886
            // End call triggers
887
888
            // Hooks on failed login
889
            $action = '';
890
            $hookmanager->initHooks(array('login'));
891
            $parameters = array('dol_authmode' => (isset($dol_authmode) ? $dol_authmode : ''), 'dol_loginmesg' => $_SESSION["dol_loginmesg"]);
892
            $reshook = $hookmanager->executeHooks('afterLoginFailed', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
893
            if ($reshook < 0) {
894
                $error++;
895
            }
896
897
            $paramsurl = array();
898
            if (GETPOSTINT('textbrowser')) {
899
                $paramsurl[] = 'textbrowser=' . GETPOSTINT('textbrowser');
900
            }
901
            if (GETPOSTINT('nojs')) {
902
                $paramsurl[] = 'nojs=' . GETPOSTINT('nojs');
903
            }
904
            if (GETPOST('lang', 'aZ09')) {
905
                $paramsurl[] = 'lang=' . GETPOST('lang', 'aZ09');
906
            }
907
908
            header('Location: ' . constant('BASE_URL') . '/index.php' . (count($paramsurl) ? '?' . implode('&', $paramsurl) : ''));
909
            exit;
910
        } else {
911
            // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
912
            $hookmanager->initHooks(array('main'));
913
914
            // Code for search criteria persistence.
915
            if (!empty($_GET['save_lastsearch_values']) && !empty($_SERVER["HTTP_REFERER"])) {    // We must use $_GET here
916
                $relativepathstring = preg_replace('/\?.*$/', '', $_SERVER["HTTP_REFERER"]);
917
                $relativepathstring = preg_replace('/^https?:\/\/[^\/]*/', '', $relativepathstring); // Get full path except host server
918
                // Clean $relativepathstring
919
                if (constant('DOL_URL_ROOT')) {
920
                    $relativepathstring = preg_replace('/^' . preg_quote(constant('DOL_URL_ROOT'), '/') . '/', '', $relativepathstring);
921
                }
922
                $relativepathstring = preg_replace('/^\//', '', $relativepathstring);
923
                $relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
924
                //var_dump($relativepathstring);
925
926
                // We click on a link that leave a page we have to save search criteria, contextpage, limit and page and mode. We save them from tmp to no tmp
927
                if (!empty($_SESSION['lastsearch_values_tmp_' . $relativepathstring])) {
928
                    $_SESSION['lastsearch_values_' . $relativepathstring] = $_SESSION['lastsearch_values_tmp_' . $relativepathstring];
929
                    unset($_SESSION['lastsearch_values_tmp_' . $relativepathstring]);
930
                }
931
                if (!empty($_SESSION['lastsearch_contextpage_tmp_' . $relativepathstring])) {
932
                    $_SESSION['lastsearch_contextpage_' . $relativepathstring] = $_SESSION['lastsearch_contextpage_tmp_' . $relativepathstring];
933
                    unset($_SESSION['lastsearch_contextpage_tmp_' . $relativepathstring]);
934
                }
935
                if (!empty($_SESSION['lastsearch_limit_tmp_' . $relativepathstring]) && $_SESSION['lastsearch_limit_tmp_' . $relativepathstring] != $conf->liste_limit) {
936
                    $_SESSION['lastsearch_limit_' . $relativepathstring] = $_SESSION['lastsearch_limit_tmp_' . $relativepathstring];
937
                    unset($_SESSION['lastsearch_limit_tmp_' . $relativepathstring]);
938
                }
939
                if (!empty($_SESSION['lastsearch_page_tmp_' . $relativepathstring]) && $_SESSION['lastsearch_page_tmp_' . $relativepathstring] > 0) {
940
                    $_SESSION['lastsearch_page_' . $relativepathstring] = $_SESSION['lastsearch_page_tmp_' . $relativepathstring];
941
                    unset($_SESSION['lastsearch_page_tmp_' . $relativepathstring]);
942
                }
943
                if (!empty($_SESSION['lastsearch_mode_tmp_' . $relativepathstring])) {
944
                    $_SESSION['lastsearch_mode_' . $relativepathstring] = $_SESSION['lastsearch_mode_tmp_' . $relativepathstring];
945
                    unset($_SESSION['lastsearch_mode_tmp_' . $relativepathstring]);
946
                }
947
            }
948
            if (!empty($_GET['save_pageforbacktolist']) && !empty($_SERVER["HTTP_REFERER"])) {    // We must use $_GET here
949
                if (empty($_SESSION['pageforbacktolist'])) {
950
                    $pageforbacktolistarray = array();
951
                } else {
952
                    $pageforbacktolistarray = $_SESSION['pageforbacktolist'];
953
                }
954
                $tmparray = explode(':', $_GET['save_pageforbacktolist'], 2);
955
                if (!empty($tmparray[0]) && !empty($tmparray[1])) {
956
                    $pageforbacktolistarray[$tmparray[0]] = $tmparray[1];
957
                    $_SESSION['pageforbacktolist'] = $pageforbacktolistarray;
958
                }
959
            }
960
961
            $action = '';
962
            $parameters = array();
963
            $reshook = $hookmanager->executeHooks('updateSession', $parameters, $user, $action);
964
            if ($reshook < 0) {
965
                setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
966
            }
967
        }
968
    }
969
970
    // Is it a new session that has started ?
971
    // If we are here, this means authentication was successful.
972
    if (!isset($_SESSION["dol_login"])) {
973
        // New session for this login has started.
974
        $error = 0;
975
976
        // Store value into session (values always stored)
977
        $_SESSION["dol_login"] = $user->login;
978
        $_SESSION["dol_logindate"] = dol_now('gmt');
979
        $_SESSION["dol_authmode"] = isset($dol_authmode) ? $dol_authmode : '';
980
        $_SESSION["dol_tz"] = isset($dol_tz) ? $dol_tz : '';
981
        $_SESSION["dol_tz_string"] = isset($dol_tz_string) ? $dol_tz_string : '';
982
        $_SESSION["dol_dst"] = isset($dol_dst) ? $dol_dst : '';
983
        $_SESSION["dol_dst_observed"] = isset($dol_dst_observed) ? $dol_dst_observed : '';
984
        $_SESSION["dol_dst_first"] = isset($dol_dst_first) ? $dol_dst_first : '';
985
        $_SESSION["dol_dst_second"] = isset($dol_dst_second) ? $dol_dst_second : '';
986
        $_SESSION["dol_screenwidth"] = isset($dol_screenwidth) ? $dol_screenwidth : '';
987
        $_SESSION["dol_screenheight"] = isset($dol_screenheight) ? $dol_screenheight : '';
988
        $_SESSION["dol_company"] = getDolGlobalString("MAIN_INFO_SOCIETE_NOM");
989
        $_SESSION["dol_entity"] = $conf->entity;
990
        // Store value into session (values stored only if defined)
991
        if (!empty($dol_hide_topmenu)) {
992
            $_SESSION['dol_hide_topmenu'] = $dol_hide_topmenu;
993
        }
994
        if (!empty($dol_hide_leftmenu)) {
995
            $_SESSION['dol_hide_leftmenu'] = $dol_hide_leftmenu;
996
        }
997
        if (!empty($dol_optimize_smallscreen)) {
998
            $_SESSION['dol_optimize_smallscreen'] = $dol_optimize_smallscreen;
999
        }
1000
        if (!empty($dol_no_mouse_hover)) {
1001
            $_SESSION['dol_no_mouse_hover'] = $dol_no_mouse_hover;
1002
        }
1003
        if (!empty($dol_use_jmobile)) {
1004
            $_SESSION['dol_use_jmobile'] = $dol_use_jmobile;
1005
        }
1006
1007
        dol_syslog("This is a new started user session. _SESSION['dol_login']=" . $_SESSION["dol_login"] . " Session id=" . session_id());
1008
1009
        $db->begin();
1010
1011
        $user->update_last_login_date();
1012
1013
        $loginfo = 'TZ=' . $_SESSION["dol_tz"] . ';TZString=' . $_SESSION["dol_tz_string"] . ';Screen=' . $_SESSION["dol_screenwidth"] . 'x' . $_SESSION["dol_screenheight"];
1014
        $loginfo .= ' - authmode=' . $dol_authmode . ' - entity=' . $conf->entity;
1015
1016
        // Call triggers for the "security events" log
1017
        $user->context['audit'] = $loginfo;
1018
        $user->context['authentication_method'] = $dol_authmode;
1019
1020
        // Call trigger
1021
        $result = $user->call_trigger('USER_LOGIN', $user);
1022
        if ($result < 0) {
1023
            $error++;
1024
        }
1025
        // End call triggers
1026
1027
        // Hooks on successful login
1028
        $action = '';
1029
        $hookmanager->initHooks(array('login'));
1030
        $parameters = array('dol_authmode' => $dol_authmode, 'dol_loginfo' => $loginfo);
1031
        $reshook = $hookmanager->executeHooks('afterLogin', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
1032
        if ($reshook < 0) {
1033
            $error++;
1034
        }
1035
1036
        if ($error) {
1037
            $db->rollback();
1038
            session_destroy();
1039
            dol_print_error($db, 'Error in some triggers USER_LOGIN or in some hooks afterLogin');
1040
            exit;
1041
        } else {
1042
            $db->commit();
1043
        }
1044
1045
        // Change landing page if defined.
1046
        $landingpage = (empty($user->conf->MAIN_LANDING_PAGE) ? (!getDolGlobalString('MAIN_LANDING_PAGE') ? '' : $conf->global->MAIN_LANDING_PAGE) : $user->conf->MAIN_LANDING_PAGE);
1047
        if (!empty($landingpage)) {    // Example: /index.php
1048
            $newpath = dol_buildpath($landingpage, 1);
1049
            if ($_SERVER["PHP_SELF"] != $newpath) {   // not already on landing page (avoid infinite loop)
1050
                header('Location: ' . $newpath);
1051
                exit;
1052
            }
1053
        }
1054
    }
1055
1056
1057
    // If user admin, we force the rights-based modules
1058
    if ($user->admin) {
1059
        $user->rights->user->user->lire = 1;
1060
        $user->rights->user->user->creer = 1;
1061
        $user->rights->user->user->password = 1;
1062
        $user->rights->user->user->supprimer = 1;
1063
        $user->rights->user->self->creer = 1;
1064
        $user->rights->user->self->password = 1;
1065
1066
        //Required if advanced permissions are used with MAIN_USE_ADVANCED_PERMS
1067
        if (getDolGlobalString('MAIN_USE_ADVANCED_PERMS')) {
1068
            if (!$user->hasRight('user', 'user_advance')) {
1069
                $user->rights->user->user_advance = new stdClass(); // To avoid warnings
1070
            }
1071
            if (!$user->hasRight('user', 'self_advance')) {
1072
                $user->rights->user->self_advance = new stdClass(); // To avoid warnings
1073
            }
1074
            if (!$user->hasRight('user', 'group_advance')) {
1075
                $user->rights->user->group_advance = new stdClass(); // To avoid warnings
1076
            }
1077
1078
            $user->rights->user->user_advance->readperms = 1;
1079
            $user->rights->user->user_advance->write = 1;
1080
            $user->rights->user->self_advance->readperms = 1;
1081
            $user->rights->user->self_advance->writeperms = 1;
1082
            $user->rights->user->group_advance->read = 1;
1083
            $user->rights->user->group_advance->readperms = 1;
1084
            $user->rights->user->group_advance->write = 1;
1085
            $user->rights->user->group_advance->delete = 1;
1086
        }
1087
    }
1088
1089
    /*
1090
     * Overwrite some configs globals (try to avoid this and have code to use instead $user->conf->xxx)
1091
     */
1092
1093
    // Set liste_limit
1094
    if (isset($user->conf->MAIN_SIZE_LISTE_LIMIT)) {
1095
        $conf->liste_limit = $user->conf->MAIN_SIZE_LISTE_LIMIT; // Can be 0
1096
    }
1097
    if (isset($user->conf->PRODUIT_LIMIT_SIZE)) {
1098
        $conf->product->limit_size = $user->conf->PRODUIT_LIMIT_SIZE; // Can be 0
1099
    }
1100
1101
    // Replace conf->css by personalized value if theme not forced
1102
    if (!getDolGlobalString('MAIN_FORCETHEME') && !empty($user->conf->MAIN_THEME)) {
1103
        $conf->theme = $user->conf->MAIN_THEME;
1104
        $conf->css = "/theme/" . $conf->theme . "/style.css.php";
1105
    }
1106
} else {
1107
    // We may have NOLOGIN set, but NOREQUIREUSER not
1108
    if (!empty($user) && method_exists($user, 'loadDefaultValues') && !defined('NODEFAULTVALUES')) {
1109
        $user->loadDefaultValues();     // Load default values for everybody (works even if $user->id = 0
1110
    }
1111
}
1112
1113
1114
// Case forcing style from url
1115
if (GETPOST('theme', 'aZ09')) {
1116
    $conf->theme = GETPOST('theme', 'aZ09', 1);
1117
    $conf->css = "/theme/" . $conf->theme . "/style.css.php";
1118
}
1119
1120
// Set javascript option
1121
if (GETPOSTINT('nojs')) {  // If javascript was not disabled on URL
1122
    $conf->use_javascript_ajax = 0;
1123
} else {
1124
    if (!empty($user->conf->MAIN_DISABLE_JAVASCRIPT)) {
1125
        $conf->use_javascript_ajax = !$user->conf->MAIN_DISABLE_JAVASCRIPT;
1126
    }
1127
}
1128
1129
// Set MAIN_OPTIMIZEFORTEXTBROWSER for user (must be after login part)
1130
if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER') && !empty($user->conf->MAIN_OPTIMIZEFORTEXTBROWSER)) {
1131
    $conf->global->MAIN_OPTIMIZEFORTEXTBROWSER = $user->conf->MAIN_OPTIMIZEFORTEXTBROWSER;
1132
    if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER') == 1) {
1133
        $conf->global->THEME_TOPMENU_DISABLE_IMAGE = 1;
1134
    }
1135
}
1136
//var_dump($conf->global->THEME_TOPMENU_DISABLE_IMAGE);
1137
//var_dump($user->conf->THEME_TOPMENU_DISABLE_IMAGE);
1138
1139
// set MAIN_OPTIMIZEFORCOLORBLIND for user
1140
$conf->global->MAIN_OPTIMIZEFORCOLORBLIND = empty($user->conf->MAIN_OPTIMIZEFORCOLORBLIND) ? '' : $user->conf->MAIN_OPTIMIZEFORCOLORBLIND;
1141
1142
// Set terminal output option according to conf->browser.
1143
if (GETPOSTINT('dol_hide_leftmenu') || !empty($_SESSION['dol_hide_leftmenu'])) {
1144
    $conf->dol_hide_leftmenu = 1;
1145
}
1146
if (GETPOSTINT('dol_hide_topmenu') || !empty($_SESSION['dol_hide_topmenu'])) {
1147
    $conf->dol_hide_topmenu = 1;
1148
}
1149
if (GETPOSTINT('dol_optimize_smallscreen') || !empty($_SESSION['dol_optimize_smallscreen'])) {
1150
    $conf->dol_optimize_smallscreen = 1;
1151
}
1152
if (GETPOSTINT('dol_no_mouse_hover') || !empty($_SESSION['dol_no_mouse_hover'])) {
1153
    $conf->dol_no_mouse_hover = 1;
1154
}
1155
if (GETPOSTINT('dol_use_jmobile') || !empty($_SESSION['dol_use_jmobile'])) {
1156
    $conf->dol_use_jmobile = 1;
1157
}
1158
// If not on Desktop
1159
if (!empty($conf->browser->layout) && $conf->browser->layout != 'classic') {
1160
    $conf->dol_no_mouse_hover = 1;
1161
}
1162
1163
// If on smartphone or optimized for small screen
1164
if (
1165
    (!empty($conf->browser->layout) && $conf->browser->layout == 'phone')
1166
    || (!empty($_SESSION['dol_screenwidth']) && $_SESSION['dol_screenwidth'] < 400)
1167
    || (!empty($_SESSION['dol_screenheight']) && $_SESSION['dol_screenheight'] < 400
1168
        || getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER'))
1169
) {
1170
    $conf->dol_optimize_smallscreen = 1;
1171
1172
    if (getDolGlobalInt('PRODUIT_DESC_IN_FORM') == 1) {
1173
        $conf->global->PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE = 0;
1174
    }
1175
}
1176
// Replace themes bugged with jmobile with eldy
1177
if (!empty($conf->dol_use_jmobile) && in_array($conf->theme, array('bureau2crea', 'cameleo', 'amarok'))) {
1178
    $conf->theme = 'eldy';
1179
    $conf->css = "/theme/" . $conf->theme . "/style.css.php";
1180
}
1181
1182
if (!defined('NOREQUIRETRAN')) {
1183
    if (!GETPOST('lang', 'aZ09')) { // If language was not forced on URL
1184
        // If user has chosen its own language
1185
        if (!empty($user->conf->MAIN_LANG_DEFAULT)) {
1186
            // If different than current language
1187
            //print ">>>".$langs->getDefaultLang()."-".$user->conf->MAIN_LANG_DEFAULT;
1188
            if ($langs->getDefaultLang() != $user->conf->MAIN_LANG_DEFAULT) {
1189
                $langs->setDefaultLang($user->conf->MAIN_LANG_DEFAULT);
1190
            }
1191
        }
1192
    }
1193
}
1194
1195
if (!defined('NOLOGIN')) {
1196
    // If the login is not recovered, it is identified with an account that does not exist.
1197
    // Hacking attempt?
1198
    if (!$user->login) {
1199
        accessforbidden();
1200
    }
1201
1202
    // Check if user is active
1203
    if ($user->statut < 1) {
1204
        // If not active, we refuse the user
1205
        $langs->loadLangs(array("errors", "other"));
1206
        dol_syslog("Authentication KO as login is disabled", LOG_NOTICE);
1207
        accessforbidden("ErrorLoginDisabled");
1208
    }
1209
1210
    // Load permissions
1211
    $user->getrights();
1212
}
1213
1214
dol_syslog("--- Access to " . (empty($_SERVER["REQUEST_METHOD"]) ? '' : $_SERVER["REQUEST_METHOD"] . ' ') . $_SERVER["PHP_SELF"] . ' - action=' . GETPOST('action', 'aZ09') . ', massaction=' . GETPOST('massaction', 'aZ09') . (defined('NOTOKENRENEWAL') ? ' NOTOKENRENEWAL=' . constant('NOTOKENRENEWAL') : ''), LOG_NOTICE);
1215
//Another call for easy debug
1216
//dol_syslog("Access to ".$_SERVER["PHP_SELF"].' '.$_SERVER["HTTP_REFERER"].' GET='.join(',',array_keys($_GET)).'->'.join(',',$_GET).' POST:'.join(',',array_keys($_POST)).'->'.join(',',$_POST));
1217
1218
// Load main languages files
1219
if (!defined('NOREQUIRETRAN')) {
1220
    // Load translation files required by page
1221
    $langs->loadLangs(array('main', 'dict'));
1222
}
1223
1224
// Define some constants used for style of arrays
1225
$bc = array(0 => 'class="impair"', 1 => 'class="pair"');
1226
$bcdd = array(0 => 'class="drag drop oddeven"', 1 => 'class="drag drop oddeven"');
1227
$bcnd = array(0 => 'class="nodrag nodrop nohover"', 1 => 'class="nodrag nodrop nohoverpair"'); // Used for tr to add new lines
1228
$bctag = array(0 => 'class="impair tagtr"', 1 => 'class="pair tagtr"');
1229
1230
// Define messages variables
1231
$mesg = '';
1232
$warning = '';
1233
$error = 0;
1234
// deprecated, see setEventMessages() and dol_htmloutput_events()
1235
$mesgs = array();
1236
$warnings = array();
1237
$errors = array();
1238
1239
// Constants used to defined number of lines in textarea
1240
if (empty($conf->browser->firefox)) {
1241
    define('ROWS_1', 1);
1242
    define('ROWS_2', 2);
1243
    define('ROWS_3', 3);
1244
    define('ROWS_4', 4);
1245
    define('ROWS_5', 5);
1246
    define('ROWS_6', 6);
1247
    define('ROWS_7', 7);
1248
    define('ROWS_8', 8);
1249
    define('ROWS_9', 9);
1250
} else {
1251
    define('ROWS_1', 0);
1252
    define('ROWS_2', 1);
1253
    define('ROWS_3', 2);
1254
    define('ROWS_4', 3);
1255
    define('ROWS_5', 4);
1256
    define('ROWS_6', 5);
1257
    define('ROWS_7', 6);
1258
    define('ROWS_8', 7);
1259
    define('ROWS_9', 8);
1260
}
1261
1262
$heightforframes = 50;
1263
1264
// Init menu manager
1265
if (!defined('NOREQUIREMENU')) {
1266
    if (empty($user->socid)) {    // If internal user or not defined
1267
        $conf->standard_menu = (!getDolGlobalString('MAIN_MENU_STANDARD_FORCED') ? (!getDolGlobalString('MAIN_MENU_STANDARD') ? 'eldy_menu.php' : $conf->global->MAIN_MENU_STANDARD) : $conf->global->MAIN_MENU_STANDARD_FORCED);
1268
    } else {
1269
        // If external user
1270
        $conf->standard_menu = (!getDolGlobalString('MAIN_MENUFRONT_STANDARD_FORCED') ? (!getDolGlobalString('MAIN_MENUFRONT_STANDARD') ? 'eldy_menu.php' : $conf->global->MAIN_MENUFRONT_STANDARD) : $conf->global->MAIN_MENUFRONT_STANDARD_FORCED);
1271
    }
1272
1273
    // Load the menu manager (only if not already done)
1274
    $file_menu = $conf->standard_menu;
1275
    if (GETPOST('menu', 'alpha')) {
1276
        $file_menu = GETPOST('menu', 'alpha'); // example: menu=eldy_menu.php
1277
    }
1278
    if (!class_exists('MenuManager')) {
1279
        $menufound = 0;
1280
        $dirmenus = array_merge(array("/core/menus/"), (array)$conf->modules_parts['menus']);
1281
        foreach ($dirmenus as $dirmenu) {
1282
            $menufound = dol_include_once($dirmenu . "standard/" . $file_menu);
1283
            if (class_exists('MenuManager')) {
1284
                break;
1285
            }
1286
        }
1287
        if (!class_exists('MenuManager')) { // If failed to include, we try with standard eldy_menu.php
1288
            dol_syslog("You define a menu manager '" . $file_menu . "' that can not be loaded.", LOG_WARNING);
1289
            $file_menu = 'eldy_menu.php';
1290
            include_once DOL_DOCUMENT_ROOT . "/core/menus/standard/" . $file_menu;
1291
        }
1292
    }
1293
    $menumanager = new MenuManager($db, empty($user->socid) ? 0 : 1);
1294
    $menumanager->loadMenu();
1295
}
1296
1297
if (!empty(GETPOST('seteventmessages', 'alpha'))) {
1298
    $message = GETPOST('seteventmessages', 'alpha');
1299
    $messages = explode(',', $message);
1300
    foreach ($messages as $key => $msg) {
1301
        $tmp = explode(':', $msg);
1302
        setEventMessages($tmp[0], null, !empty($tmp[1]) ? $tmp[1] : 'mesgs');
1303
    }
1304
}
1305