Passed
Push — master ( 3cffbe...0f9140 )
by Alxarafe
23:50
created

Base/AlixarController.php (1 issue)

Labels
Severity
1
<?php
2
/* Copyright (C) 2019       Alxarafe                    <[email protected]>
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16
 */
17
namespace Alixar\Base;
18
19
use Alxarafe\Helpers\Debug;
20
use Alxarafe\Helpers\Config;
21
use Alixar\Helpers\Globals;
22
use Alixar\Helpers\AlDolUtils;
23
use Alixar\Helpers\AlSecurity;
24
use Alixar\Helpers\AlSecurity2;
25
use Alixar\Helpers\DateLib;
26
use Alixar\Base\AlInterfaces;
27
use Alixar\Base\MenuManager;
28
29
/**
30
 * This class contains the methods and attributes common to all Alixar controllers
31
 *
32
 * @author Alxarafe
33
 */
34
class AlixarController extends \Alxarafe\Base\Controller
35
{
36
37
    public $authmode;
38
    public $dol_authmode;
39
    public $sessionname;
40
41
    function __construct()
42
    {
43
        parent::__construct();
44
45
        $this->checkRequires();
46
47
        // Include the conf.php and functions.lib.php
48
        // require_once DOL_BASE_PATH . '/filefunc.inc.php';
49
        Globals::initGlobals();
50
51
        // Init session. Name of session is specific to Dolibarr instance.
52
        // Note: the function dol_getprefix may have been redefined to return a different key to manage another area to protect.
53
        $prefix = AlDolUtils::dol_getprefix('');
54
55
        $this->sessionname = 'DOLSESSID_' . $prefix;
56
        $sessiontimeout = 'DOLSESSTIMEOUT_' . $prefix;
57
        if (!empty($_COOKIE[$sessiontimeout])) {
58
            ini_set('session.gc_maxlifetime', $_COOKIE[$sessiontimeout]);
59
        }
60
        session_name($this->sessionname);
61
        session_set_cookie_params(0, '/', null, false, true);   // Add tag httponly on session cookie (same as setting session.cookie_httponly into php.ini). Must be called before the session_start.
62
        // This create lock, released when session_write_close() or end of page.
63
        // We need this lock as long as we read/write $_SESSION ['vars']. We can remove lock when finished.
64
        if (!defined('NOSESSION')) {
65
            session_start();
66
            /* if (ini_get('register_globals'))    // Deprecated in 5.3 and removed in 5.4. To solve bug in using $_SESSION
67
              {
68
              foreach ($_SESSION as $key=>$value)
69
              {
70
              if (isset($GLOBALS[$key])) unset($GLOBALS[$key]);
71
              }
72
              } */
73
        }
74
        // Init the 5 global objects, this include will make the new and set properties for: Globals::$conf, $db, Globals::$langs, Globals::$user, $mysoc
75
        // require_once 'master.inc.php';
76
        // Activate end of page function
77
        // register_shutdown_function('dol_shutdown');
78
        // Detection browser
79
        if (isset($_SERVER["HTTP_USER_AGENT"])) {
80
            $tmp = AlDolUtils::getBrowserInfo($_SERVER["HTTP_USER_AGENT"]);
81
            Globals::$conf->browser->name = $tmp['browsername'];
82
            Globals::$conf->browser->os = $tmp['browseros'];
83
            Globals::$conf->browser->version = $tmp['browserversion'];
84
            Globals::$conf->browser->layout = $tmp['layout'];     // 'classic', 'phone', 'tablet'
85
            //var_dump(Globals::$conf->browser);
86
87
            if (Globals::$conf->browser->layout == 'phone') {
88
                Globals::$conf->dol_no_mouse_hover = 1;
89
            }
90
            if (Globals::$conf->browser->layout == 'phone') {
91
                Globals::$conf->global->MAIN_TESTMENUHIDER = 1;
92
            }
93
        }
94
95
        // Force HTTPS if required (Globals::$conf->file->main_force_https is 0/1 or https dolibarr root url)
96
        // $_SERVER["HTTPS"] is 'on' when link is https, otherwise $_SERVER["HTTPS"] is empty or 'off'
97
        if (!empty(Globals::$conf->file->main_force_https) && (empty($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] != 'on')) {
98
            $newurl = '';
99
            if (is_numeric(Globals::$conf->file->main_force_https)) {
100
                if (Globals::$conf->file->main_force_https == '1' && !empty($_SERVER["SCRIPT_URI"])) { // If SCRIPT_URI supported by server
101
                    if (preg_match('/^http:/i', $_SERVER["SCRIPT_URI"]) && !preg_match('/^https:/i', $_SERVER["SCRIPT_URI"])) { // If link is http
102
                        $newurl = preg_replace('/^http:/i', 'https:', $_SERVER["SCRIPT_URI"]);
103
                    }
104
                } else { // Check HTTPS environment variable (Apache/mod_ssl only)
105
                    $newurl = preg_replace('/^http:/i', 'https:', DOL_MAIN_URL_ROOT) . $_SERVER["REQUEST_URI"];
106
                }
107
            } else {
108
                // Check HTTPS environment variable (Apache/mod_ssl only)
109
                $newurl = Globals::$conf->file->main_force_https . $_SERVER["REQUEST_URI"];
110
            }
111
            // Start redirect
112
            if ($newurl) {
113
                AlDolUtils::dol_syslog("main.inc: dolibarr_main_force_https is on, we make a redirect to " . $newurl);
114
                echo $newurl;
115
                throw Exception('x');
116
                header("Location: " . $newurl);
117
                exit;
118
            } else {
119
                AlDolUtils::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);
120
            }
121
        }
122
123
        if (!defined('NOLOGIN') && !defined('NOIPCHECK') && !empty($dolibarr_main_restrict_ip)) {
124
            $listofip = explode(',', $dolibarr_main_restrict_ip);
125
            $found = false;
126
            foreach ($listofip as $ip) {
127
                $ip = trim($ip);
128
                if ($ip == $_SERVER['REMOTE_ADDR']) {
129
                    $found = true;
130
                    break;
131
                }
132
            }
133
            if (!$found) {
134
                print 'Access refused by IP protection';
135
                exit;
136
            }
137
        }
138
139
        // Loading of additional presentation includes
140
        if (!defined('NOREQUIREHTML')) {
141
            require_once DOL_BASE_PATH . '/core/class/html.form.class.php';     // Need 660ko memory (800ko in 2.2)
142
        }
143
        if (!defined('NOREQUIREAJAX') && Globals::$conf->use_javascript_ajax) {
144
            require_once DOL_BASE_PATH . '/core/lib/ajax.lib.php'; // Need 22ko memory
145
        }
146
        // If install or upgrade process not done or not completely finished, we call the install page.
147
        if (!empty(Globals::$conf->global->MAIN_NOT_INSTALLED) || !empty(Globals::$conf->global->MAIN_NOT_UPGRADED)) {
148
            AlDolUtils::dol_syslog("main.inc: A previous install or upgrade was not complete. Redirect to install page.", LOG_WARNING);
149
            throw Exception('x');
150
            header("Location: " . DOL_BASE_URI . "/install/index.php");
151
            exit;
152
        }
153
        // If an upgrade process is required, we call the install page.
154
        if ((!empty(Globals::$conf->global->MAIN_VERSION_LAST_UPGRADE) && (Globals::$conf->global->MAIN_VERSION_LAST_UPGRADE != DOL_VERSION)) || (empty(Globals::$conf->global->MAIN_VERSION_LAST_UPGRADE) && !empty(Globals::$conf->global->MAIN_VERSION_LAST_INSTALL) && (Globals::$conf->global->MAIN_VERSION_LAST_INSTALL != DOL_VERSION))) {
155
            $versiontocompare = empty(Globals::$conf->global->MAIN_VERSION_LAST_UPGRADE) ? Globals::$conf->global->MAIN_VERSION_LAST_INSTALL : Globals::$conf->global->MAIN_VERSION_LAST_UPGRADE;
156
            require_once DOL_BASE_PATH . '/core/lib/admin.lib.php';
157
            $dolibarrversionlastupgrade = preg_split('/[.-]/', $versiontocompare);
158
            $dolibarrversionprogram = preg_split('/[.-]/', DOL_VERSION);
159
            $rescomp = versioncompare($dolibarrversionprogram, $dolibarrversionlastupgrade);
160
            if ($rescomp > 0) {   // Programs have a version higher than database. We did not add "&& $rescomp < 3" because we want upgrade process for build upgrades
161
                AlDolUtils::dol_syslog("main.inc: database version " . $versiontocompare . " is lower than programs version " . DOL_VERSION . ". Redirect to install page.", LOG_WARNING);
162
                throw Exception('x');
163
                header("Location: " . DOL_BASE_URI . "/install/index.php");
164
                exit;
165
            }
166
        }
167
168
        // Creation of a token against CSRF vulnerabilities
169
        if (!defined('NOTOKENRENEWAL')) {
170
            // roulement des jetons car cree a chaque appel
171
            if (isset($_SESSION['newtoken'])) {
172
                $_SESSION['token'] = $_SESSION['newtoken'];
173
            }
174
175
            // Save in $_SESSION['newtoken'] what will be next token. Into forms, we will add param token = $_SESSION['newtoken']
176
            $token = AlSecurity::dol_hash(uniqid(mt_rand(), true)); // Generates a hash of a random number
177
            $_SESSION['newtoken'] = $token;
178
        }
179
        if ((!defined('NOCSRFCHECK') && empty($dolibarr_nocsrfcheck) && !empty(Globals::$conf->global->MAIN_SECURITY_CSRF_WITH_TOKEN)) || defined('CSRFCHECK_WITH_TOKEN')) { // Check validity of token, only if option MAIN_SECURITY_CSRF_WITH_TOKEN enabled or if constant CSRFCHECK_WITH_TOKEN is set
180
            if ($_SERVER['REQUEST_METHOD'] == 'POST' && !AlDolUtils::GETPOST('token', 'alpha')) { // Note, offender can still send request by GET
181
                print "Access refused by CSRF protection in main.inc.php. Token not provided.\n";
182
                print "If you access your server behind a proxy using url rewriting, you might check that all HTTP header is propagated (or add the line \$dolibarr_nocsrfcheck=1 into your conf.php file).\n";
183
                die;
184
            }
185
            if ($_SERVER['REQUEST_METHOD'] === 'POST') {  // This test must be after loading $_SESSION['token'].
186
                if (AlDolUtils::GETPOST('token', 'alpha') != $_SESSION['token']) {
187
                    AlDolUtils::dol_syslog("Invalid token in " . $_SERVER['HTTP_REFERER'] . ", action=" . AlDolUtils::GETPOST('action', 'aZ09') . ", _POST['token']=" . AlDolUtils::GETPOST('token', 'alpha') . ", _SESSION['token']=" . $_SESSION['token'], LOG_WARNING);
188
                    //print 'Unset POST by CSRF protection in main.inc.php.';	// Do not output anything because this create problems when using the BACK button on browsers.
189
                    unset($_POST);
190
                }
191
            }
192
        }
193
194
        // Disable modules (this must be after session_start and after conf has been loaded)
195
        if (AlDolUtils::GETPOST('disablemodules', 'alpha')) {
196
            $_SESSION["disablemodules"] = AlDolUtils::GETPOST('disablemodules', 'alpha');
197
        }
198
        if (!empty($_SESSION["disablemodules"])) {
199
            $disabled_modules = explode(',', $_SESSION["disablemodules"]);
200
            foreach ($disabled_modules as $module) {
201
                if ($module) {
202
                    if (empty(Globals::$conf->$module)) {
203
                        Globals::$conf->$module = new stdClass();
204
                    }
205
                    Globals::$conf->$module->enabled = false;
206
                    if ($module == 'fournisseur') {  // Special case
207
                        Globals::$conf->supplier_order->enabled = 0;
208
                        Globals::$conf->supplier_invoice->enabled = 0;
209
                    }
210
                }
211
            }
212
        }
213
214
        $this->testLogin();
215
216
        // Case forcing style from url
217
        if (AlDolUtils::GETPOST('theme', 'alpha')) {
218
            Globals::$conf->theme = AlDolUtils::GETPOST('theme', 'alpha', 1);
219
            // Globals::$conf->css = "/theme/" . Globals::$conf->theme . "/style.css.php";
220
            Globals::$conf->css = '?controller=theme/' . Globals::$conf->theme . '&method=style.css';
221
        }
222
223
224
        // Set javascript option
225
        if (!AlDolUtils::GETPOST('nojs', 'int')) {   // If javascript was not disabled on URL
226
            if (!empty(Globals::$user->conf->MAIN_DISABLE_JAVASCRIPT)) {
227
                Globals::$conf->use_javascript_ajax = !$user->conf->MAIN_DISABLE_JAVASCRIPT;
228
            }
229
        } else {
230
            Globals::$conf->use_javascript_ajax = 0;
231
        }
232
        // Set MAIN_OPTIMIZEFORTEXTBROWSER
233
        if (AlDolUtils::GETPOST('textbrowser', 'int') || (!empty(Globals::$conf->browser->name) && Globals::$conf->browser->name == 'lynxlinks') || !empty(Globals::$user->conf->MAIN_OPTIMIZEFORTEXTBROWSER)) {   // If we must enable text browser
234
            Globals::$conf->global->MAIN_OPTIMIZEFORTEXTBROWSER = 1;
235
        } elseif (!empty(Globals::$user->conf->MAIN_OPTIMIZEFORTEXTBROWSER)) {
236
            Globals::$conf->global->MAIN_OPTIMIZEFORTEXTBROWSER = Globals::$user->conf->MAIN_OPTIMIZEFORTEXTBROWSER;
237
        }
238
239
        // Set terminal output option according to conf->browser.
240
        if (AlDolUtils::GETPOST('dol_hide_leftmenu', 'int') || !empty($_SESSION['dol_hide_leftmenu'])) {
241
            Globals::$conf->dol_hide_leftmenu = 1;
242
        }
243
        if (AlDolUtils::GETPOST('dol_hide_topmenu', 'int') || !empty($_SESSION['dol_hide_topmenu'])) {
244
            Globals::$conf->dol_hide_topmenu = 1;
245
        }
246
        if (AlDolUtils::GETPOST('dol_optimize_smallscreen', 'int') || !empty($_SESSION['dol_optimize_smallscreen'])) {
247
            Globals::$conf->dol_optimize_smallscreen = 1;
248
        }
249
        if (AlDolUtils::GETPOST('dol_no_mouse_hover', 'int') || !empty($_SESSION['dol_no_mouse_hover'])) {
250
            Globals::$conf->dol_no_mouse_hover = 1;
251
        }
252
        if (AlDolUtils::GETPOST('dol_use_jmobile', 'int') || !empty($_SESSION['dol_use_jmobile'])) {
253
            Globals::$conf->dol_use_jmobile = 1;
254
        }
255
        if (!empty(Globals::$conf->browser->layout) && Globals::$conf->browser->layout != 'classic') {
256
            Globals::$conf->dol_no_mouse_hover = 1;
257
        }
258
        if ((!empty(Globals::$conf->browser->layout) && Globals::$conf->browser->layout == 'phone') || (!empty($_SESSION['dol_screenwidth']) && $_SESSION['dol_screenwidth'] < 400) || (!empty($_SESSION['dol_screenheight']) && $_SESSION['dol_screenheight'] < 400)
259
        ) {
260
            Globals::$conf->dol_optimize_smallscreen = 1;
261
        }
262
        // If we force to use jmobile, then we reenable javascript
263
        if (!empty(Globals::$conf->dol_use_jmobile)) {
264
            Globals::$conf->use_javascript_ajax = 1;
265
        }
266
        // Replace themes bugged with jmobile with eldy
267
        if (!empty(Globals::$conf->dol_use_jmobile) && in_array(Globals::$conf->theme, array('bureau2crea', 'cameleo', 'amarok'))) {
268
            Globals::$conf->theme = 'eldy';
269
            // Globals::$conf->css = "/theme/" . Globals::$conf->theme . "/style.css.php";
270
            Globals::$conf->css = '?controller=theme/' . Globals::$conf->theme . '&method=style.css';
271
        }
272
273
        if (!defined('NOREQUIRETRAN')) {
274
            if (!AlDolUtils::GETPOST('lang', 'aZ09')) { // If language was not forced on URL
275
                // If user has chosen its own language
276
                if (!empty(Globals::$user->conf->MAIN_LANG_DEFAULT)) {
277
                    // If different than current language
278
                    //print ">>>".Globals::$langs->getDefaultLang()."-".$user->conf->MAIN_LANG_DEFAULT;
279
                    if (Globals::$langs->getDefaultLang() != Globals::$user->conf->MAIN_LANG_DEFAULT) {
280
                        Globals::$langs->setDefaultLang(Globals::$user->conf->MAIN_LANG_DEFAULT);
281
                    }
282
                }
283
            }
284
        }
285
286
        if (!defined('NOLOGIN')) {
287
            // If the login is not recovered, it is identified with an account that does not exist.
288
            // Hacking attempt?
289
            if (!Globals::$user->login) {
290
                accessforbidden();
291
            }
292
293
            // Check if user is active
294
            if (Globals::$user->statut < 1) {
295
                // If not active, we refuse the user
296
                Globals::$langs->load("other");
297
                AlDolUtils::dol_syslog("Authentification ko as login is disabled");
298
                accessforbidden(Globals::$langs->trans("ErrorLoginDisabled"));
299
                exit;
300
            }
301
302
            // Load permissions
303
            Globals::$user->getrights();
304
        }
305
306
307
        AlDolUtils::dol_syslog("--- Access to " . $_SERVER["PHP_SELF"] . ' - action=' . AlDolUtils::GETPOST('action', 'az09') . ', massaction=' . AlDolUtils::GETPOST('massaction', 'az09'));
308
        //Another call for easy debugg
309
        //dol_syslog("Access to ".$_SERVER["PHP_SELF"].' GET='.join(',',array_keys($_GET)).'->'.join(',',$_GET).' POST:'.join(',',array_keys($_POST)).'->'.join(',',$_POST));
310
        // Load main languages files
311
        if (!defined('NOREQUIRETRAN')) {
312
            // Load translation files required by page
313
            Globals::$langs->loadLangs(array('main', 'dict'));
314
        }
315
316
        // Define some constants used for style of arrays
317
        $bc = array(0 => 'class="impair"', 1 => 'class="pair"');
318
        $bcdd = array(0 => 'class="drag drop oddeven"', 1 => 'class="drag drop oddeven"');
319
        $bcnd = array(0 => 'class="nodrag nodrop nohover"', 1 => 'class="nodrag nodrop nohoverpair"');  // Used for tr to add new lines
320
        $bctag = array(0 => 'class="impair tagtr"', 1 => 'class="pair tagtr"');
321
322
        // Define messages variables
323
        $mesg = '';
324
        $warning = '';
325
        $error = 0;
326
        // deprecated, see setEventMessages() and dol_htmloutput_events()
327
        $mesgs = array();
328
        $warnings = array();
329
        $errors = array();
330
331
        // Constants used to defined number of lines in textarea
332
        if (empty(Globals::$conf->browser->firefox)) {
333
            define('ROWS_1', 1);
334
            define('ROWS_2', 2);
335
            define('ROWS_3', 3);
336
            define('ROWS_4', 4);
337
            define('ROWS_5', 5);
338
            define('ROWS_6', 6);
339
            define('ROWS_7', 7);
340
            define('ROWS_8', 8);
341
            define('ROWS_9', 9);
342
        } else {
343
            define('ROWS_1', 0);
344
            define('ROWS_2', 1);
345
            define('ROWS_3', 2);
346
            define('ROWS_4', 3);
347
            define('ROWS_5', 4);
348
            define('ROWS_6', 5);
349
            define('ROWS_7', 6);
350
            define('ROWS_8', 7);
351
            define('ROWS_9', 8);
352
        }
353
354
        $heightforframes = 50;
355
356
// Init menu manager
357
        if (!defined('NOREQUIREMENU')) {
358
            if (empty(Globals::$user->societe_id)) {    // If internal user or not defined
359
                Globals::$conf->standard_menu = (empty(Globals::$conf->global->MAIN_MENU_STANDARD_FORCED) ? (empty(Globals::$conf->global->MAIN_MENU_STANDARD) ? 'eldy_menu.php' : Globals::$conf->global->MAIN_MENU_STANDARD) : Globals::$conf->global->MAIN_MENU_STANDARD_FORCED);
360
            } else {                        // If external user
361
                Globals::$conf->standard_menu = (empty(Globals::$conf->global->MAIN_MENUFRONT_STANDARD_FORCED) ? (empty(Globals::$conf->global->MAIN_MENUFRONT_STANDARD) ? 'eldy_menu.php' : Globals::$conf->global->MAIN_MENUFRONT_STANDARD) : Globals::$conf->global->MAIN_MENUFRONT_STANDARD_FORCED);
362
            }
363
364
// Load the menu manager (only if not already done)
365
            $file_menu = Globals::$conf->standard_menu;
366
            if (AlDolUtils::GETPOST('menu', 'alpha')) {
367
                $file_menu = AlDolUtils::GETPOST('menu', 'alpha');     // example: menu=eldy_menu.php
368
            }
369
            if (!class_exists('MenuManager')) {
370
                $menufound = 0;
371
                $dirmenus = array_merge(array("/core/menus/"), (array) Globals::$conf->modules_parts['menus']);
372
                foreach ($dirmenus as $dirmenu) {
373
                    // $menufound = dol_include_once($dirmenu . "standard/" . $file_menu);
374
                    if (class_exists('MenuManager')) {
375
                        break;
376
                    }
377
                }
378
                if (!class_exists('MenuManager')) { // If failed to include, we try with standard eldy_menu.php
379
                    AlDolUtils::dol_syslog("You define a menu manager '" . $file_menu . "' that can not be loaded.", LOG_WARNING);
380
                    $file_menu = 'eldy_menu.php';
381
                    // include_once DOL_DOCUMENT_ROOT . "/core/menus/standard/" . $file_menu;
382
                }
383
            }
384
            Globals::$menuManager = new MenuManager(empty(Globals::$user->societe_id) ? 0 : 1);
385
            Globals::$menuManager->loadMenu();
386
        }
387
    }
388
389
    function checkRequires()
390
    {
391
        /**
392
         * $_GET = array_map('stripslashes_deep', $_GET);
393
         * $_POST = array_map('stripslashes_deep', $_POST);
394
         * $_FILES = array_map('stripslashes_deep', $_FILES);
395
         * // $_COOKIE  = array_map('stripslashes_deep', $_COOKIE); // Useless because a cookie should never be outputed on screen nor used into sql
396
         * @set_magic_quotes_runtime(0);
397
         */
398
        // Check consistency of NOREQUIREXXX DEFINES
399
        if ((defined('NOREQUIREDB') || defined('NOREQUIRETRAN')) && !defined('NOREQUIREMENU')) {
400
            print 'If define NOREQUIREDB or NOREQUIRETRAN are set, you must also set NOREQUIREMENU or not set them';
401
            exit;
402
        }
403
404
        // Sanity check on URL
405
        if (!empty($_SERVER["PHP_SELF"])) {
406
            $morevaltochecklikepost = array($_SERVER["PHP_SELF"]);
407
            $this->analyseVarsForSqlAndScriptsInjection($morevaltochecklikepost, 2);
408
        }
409
410
        // Sanity check on GET parameters
411
        if (!defined('NOSCANGETFORINJECTION') && !empty($_SERVER["QUERY_STRING"])) {
412
            $morevaltochecklikeget = array($_SERVER["QUERY_STRING"]);
413
            $this->analyseVarsForSqlAndScriptsInjection($morevaltochecklikeget, 1);
414
        }
415
416
        // Sanity check on POST
417
        if (!defined('NOSCANPOSTFORINJECTION')) {
418
            $this->analyseVarsForSqlAndScriptsInjection($_POST, 0);
419
        }
420
421
        // This is to make Dolibarr working with Plesk
422
        if (!empty($_SERVER['DOCUMENT_ROOT']) && substr($_SERVER['DOCUMENT_ROOT'], -6) !== 'htdocs') {
423
            set_include_path($_SERVER['DOCUMENT_ROOT'] . '/htdocs');
424
        }
425
426
        // If there is a POST parameter to tell to save automatically some POST parameters into cookies, we do it.
427
        // This is used for example by form of boxes to save personalization of some options.
428
        // DOL_AUTOSET_COOKIE=cookiename:val1,val2 and  cookiename_val1=aaa cookiename_val2=bbb will set cookie_name with value json_encode(array('val1'=> , ))
429
        if (!empty($_POST["DOL_AUTOSET_COOKIE"])) {
430
            $tmpautoset = explode(':', $_POST["DOL_AUTOSET_COOKIE"], 2);
431
            $tmplist = explode(',', $tmpautoset[1]);
432
            $cookiearrayvalue = array();
433
            foreach ($tmplist as $tmpkey) {
434
                $postkey = $tmpautoset[0] . '_' . $tmpkey;
435
//var_dump('tmpkey='.$tmpkey.' postkey='.$postkey.' value='.$_POST[$postkey]);
436
                if (!empty($_POST[$postkey])) {
437
                    $cookiearrayvalue[$tmpkey] = $_POST[$postkey];
438
                }
439
            }
440
            $cookiename = $tmpautoset[0];
441
            $cookievalue = json_encode($cookiearrayvalue);
442
//var_dump('setcookie cookiename='.$cookiename.' cookievalue='.$cookievalue);
443
            setcookie($cookiename, empty($cookievalue) ? '' : $cookievalue, empty($cookievalue) ? 0 : (time() + (86400 * 354)), '/', null, false, true); // keep cookie 1 year and add tag httponly
444
            if (empty($cookievalue)) {
445
                unset($_COOKIE[$cookiename]);
446
            }
447
        }
448
    }
449
450
    /**
451
     * DEPRECATED?
452
     *
453
     * Forcing parameter setting magic_quotes_gpc and cleaning parameters
454
     * (Otherwise he would have for each position, condition
455
     * Reading stripslashes variable according to state get_magic_quotes_gpc).
456
     * Off mode recommended (just do Config::$dbEngine->escape for insert / update).
457
     */
458
    function stripslashes_deep($value)
459
    {
460
        return (is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value));
461
    }
462
463
    /**
464
     * AlSecurity: SQL Injection and XSS Injection (scripts) protection (Filters on GET, POST, PHP_SELF).
465
     *
466
     * @param       string      $val        Value
467
     * @param       string      $type       1=GET, 0=POST, 2=PHP_SELF, 3=GET without sql reserved keywords (the less tolerant test)
468
     * @return      int                     >0 if there is an injection, 0 if none
469
     * @deprecated                          use $this->testSqlAndScriptInject
470
     * @see $this->testSqlAndScriptInject($val, $type)
471
     */
472
    function test_sql_and_script_inject($val, $type)
473
    {
474
// phpcs:enable
475
        return $this->testSqlAndScriptInject($val, $type);
476
    }
477
478
    /**
479
     * AlSecurity: SQL Injection and XSS Injection (scripts) protection (Filters on GET, POST, PHP_SELF).
480
     *
481
     * @param		string		$val		Value
482
     * @param		string		$type		1=GET, 0=POST, 2=PHP_SELF, 3=GET without sql reserved keywords (the less tolerant test)
483
     * @return		int						>0 if there is an injection, 0 if none
484
     */
485
    function testSqlAndScriptInject($val, $type)
486
    {
487
        $inj = 0;
488
// For SQL Injection (only GET are used to be included into bad escaped SQL requests)
489
        if ($type == 1 || $type == 3) {
490
            $inj += preg_match('/delete\s+from/i', $val);
491
            $inj += preg_match('/create\s+table/i', $val);
492
            $inj += preg_match('/insert\s+into/i', $val);
493
            $inj += preg_match('/select\s+from/i', $val);
494
            $inj += preg_match('/into\s+(outfile|dumpfile)/i', $val);
495
            $inj += preg_match('/user\s*\(/i', $val);      // avoid to use function user() that return current database login
496
            $inj += preg_match('/information_schema/i', $val);    // avoid to use request that read information_schema database
497
        }
498
        if ($type == 3) {
499
            $inj += preg_match('/select|update|delete|replace|group\s+by|concat|count|from/i', $val);
500
        }
501
        if ($type != 2) { // Not common key strings, so we can check them both on GET and POST
502
            $inj += preg_match('/updatexml\(/i', $val);
503
            $inj += preg_match('/update.+set.+=/i', $val);
504
            $inj += preg_match('/union.+select/i', $val);
505
            $inj += preg_match('/(\.\.%2f)+/i', $val);
506
        }
507
// For XSS Injection done by adding javascript with script
508
// This is all cases a browser consider text is javascript:
509
// When it found '<script', 'javascript:', '<style', 'onload\s=' on body tag, '="&' on a tag size with old browsers
510
// All examples on page: http://ha.ckers.org/xss.html#XSScalc
511
// More on https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
512
        $inj += preg_match('/<script/i', $val);
513
        $inj += preg_match('/<iframe/i', $val);
514
        $inj += preg_match('/<audio/i', $val);
515
        $inj += preg_match('/Set\.constructor/i', $val); // ECMA script 6
516
        if (!defined('NOSTYLECHECK')) {
517
            $inj += preg_match('/<style/i', $val);
518
        }
519
        $inj += preg_match('/base[\s]+href/si', $val);
520
        $inj += preg_match('/<.*onmouse/si', $val);       // onmousexxx can be set on img or any html tag like <img title='...' onmouseover=alert(1)>
521
        $inj += preg_match('/onerror\s*=/i', $val);       // onerror can be set on img or any html tag like <img title='...' onerror = alert(1)>
522
        $inj += preg_match('/onfocus\s*=/i', $val);       // onfocus can be set on input text html tag like <input type='text' value='...' onfocus = alert(1)>
523
        $inj += preg_match('/onload\s*=/i', $val);        // onload can be set on svg tag <svg/onload=alert(1)> or other tag like body <body onload=alert(1)>
524
        $inj += preg_match('/onloadstart\s*=/i', $val);   // onload can be set on audio tag <audio onloadstart=alert(1)>
525
        $inj += preg_match('/onclick\s*=/i', $val);       // onclick can be set on img text html tag like <img onclick = alert(1)>
526
        $inj += preg_match('/onscroll\s*=/i', $val);      // onscroll can be on textarea
527
//$inj += preg_match('/on[A-Z][a-z]+\*=/', $val);   // To lock event handlers onAbort(), ...
528
        $inj += preg_match('/&#58;|&#0000058|&#x3A/i', $val);  // refused string ':' encoded (no reason to have it encoded) to lock 'javascript:...'
529
//if ($type == 1)
530
//{
531
        $inj += preg_match('/javascript:/i', $val);
532
        $inj += preg_match('/vbscript:/i', $val);
533
//}
534
// For XSS Injection done by adding javascript closing html tags like with onmousemove, etc... (closing a src or href tag with not cleaned param)
535
        if ($type == 1) {
536
            $inj += preg_match('/"/i', $val);  // We refused " in GET parameters value
537
        }
538
        if ($type == 2) {
539
            $inj += preg_match('/[;"]/', $val);  // PHP_SELF is a file system path. It can contains spaces.
540
        }
541
        return $inj;
542
    }
543
544
    /**
545
     * Return true if security check on parameters are OK, false otherwise.
546
     *
547
     * @param		string			$var		Variable name
548
     * @param		string			$type		1=GET, 0=POST, 2=PHP_SELF
549
     * @return		boolean|null				true if there is no injection. Stop code if injection found.
550
     */
551
    function analyseVarsForSqlAndScriptsInjection(&$var, $type)
552
    {
553
        if (is_array($var)) {
554
            foreach ($var as $key => $value) { // Warning, $key may also be used for attacks
555
                if ($this->analyseVarsForSqlAndScriptsInjection($key, $type) && $this->analyseVarsForSqlAndScriptsInjection($value, $type)) {
556
//$var[$key] = $value;	// This is useless
557
                } else {
558
                    print 'Access refused by SQL/Script injection protection in main.inc.php (type=' . htmlentities($type) . ' key=' . htmlentities($key) . ' value=' . htmlentities($value) . ' page=' . htmlentities($_SERVER["REQUEST_URI"]) . ')';
559
                    exit;
560
                }
561
            }
562
            return true;
563
        } else {
564
            return ($this->testSqlAndScriptInject($var, $type) <= 0);
565
        }
566
    }
567
568
    /**
569
     * Phase authentication / login
570
     * 
571
     * @return string
572
     * @throws type
573
     */
574
    function testLogin()
575
    {
576
        $login = '';
577
        if (defined('NOLOGIN')) {
578
            return;
579
        }
580
581
        // $authmode lists the different means of identification to be tested in order of preference.
582
        // Example: 'http', 'dolibarr', 'ldap', 'http,forceuser', '...'
583
        if (defined('MAIN_AUTHENTICATION_MODE')) {
584
            $dolibarr_main_authentication = constant('MAIN_AUTHENTICATION_MODE');
585
        } else {
586
            // Authentication mode
587
            if (empty($dolibarr_main_authentication)) {
588
                $dolibarr_main_authentication = 'http,dolibarr';
589
            }
590
            // Authentication mode: forceuser
591
            if ($dolibarr_main_authentication == 'forceuser' && empty($dolibarr_auto_user)) {
592
                $dolibarr_auto_user = 'auto';
593
            }
594
        }
595
596
        // Set authmode
597
        $this->authmode = explode(',', $dolibarr_main_authentication);
598
599
        // No authentication mode
600
        if (!count($this->authmode)) {
601
            Globals::$langs->load('main');
602
            dol_print_error('', Globals::$langs->trans("ErrorConfigParameterNotDefined", 'dolibarr_main_authentication'));
603
            die('No authmode has been defined!');
604
        }
605
606
        // If login request was already post, we retrieve login from the session
607
        // Call module if not realized that his request.
608
        // At the end of this phase, the variable $login is defined.
609
        $resultFetchUser = '';
610
        $test = true;
611
612
        if (!isset($_SESSION["dol_login"])) {
613
            // It is not already authenticated and it requests the login / password
614
            // include_once DOL_BASE_PATH . '/core/lib/security2.lib.php';
615
616
            $dol_dst_observed = AlDolUtils::GETPOST("dst_observed", 'int', 3);
617
            $dol_dst_first = AlDolUtils::GETPOST("dst_first", 'int', 3);
618
            $dol_dst_second = AlDolUtils::GETPOST("dst_second", 'int', 3);
619
            $dol_screenwidth = AlDolUtils::GETPOST("screenwidth", 'int', 3);
620
            $dol_screenheight = AlDolUtils::GETPOST("screenheight", 'int', 3);
621
            $dol_hide_topmenu = AlDolUtils::GETPOST('dol_hide_topmenu', 'int', 3);
622
            $dol_hide_leftmenu = AlDolUtils::GETPOST('dol_hide_leftmenu', 'int', 3);
623
            $dol_optimize_smallscreen = AlDolUtils::GETPOST('dol_optimize_smallscreen', 'int', 3);
624
            $dol_no_mouse_hover = AlDolUtils::GETPOST('dol_no_mouse_hover', 'int', 3);
625
            $dol_use_jmobile = AlDolUtils::GETPOST('dol_use_jmobile', 'int', 3);
626
627
            // dol_syslog("POST key=".join(array_keys($_POST),',').' value='.join($_POST,','));
628
            // If in demo mode, we check we go to home page through the public/demo/index.php page
629
            if (!empty($dolibarr_main_demo) && $_SERVER['PHP_SELF'] == DOL_BASE_URI . '/index.php') {
630
                // We ask index page
631
                if (empty($_SERVER['HTTP_REFERER']) || !preg_match('/public/', $_SERVER['HTTP_REFERER'])) {
632
                    AlDolUtils::dol_syslog("Call index page from another url than demo page (call is done from page " . $_SERVER['HTTP_REFERER'] . ")");
633
                    $url = '';
634
                    $url .= ($url ? '&' : '') . ($dol_hide_topmenu ? 'dol_hide_topmenu=' . $dol_hide_topmenu : '');
635
                    $url .= ($url ? '&' : '') . ($dol_hide_leftmenu ? 'dol_hide_leftmenu=' . $dol_hide_leftmenu : '');
636
                    $url .= ($url ? '&' : '') . ($dol_optimize_smallscreen ? 'dol_optimize_smallscreen=' . $dol_optimize_smallscreen : '');
637
                    $url .= ($url ? '&' : '') . ($dol_no_mouse_hover ? 'dol_no_mouse_hover=' . $dol_no_mouse_hover : '');
638
                    $url .= ($url ? '&' : '') . ($dol_use_jmobile ? 'dol_use_jmobile=' . $dol_use_jmobile : '');
639
                    $url = DOL_BASE_URI . '/public/demo/index.php' . ($url ? '?' . $url : '');
640
                    echo $url;
641
                    throw Exception('x');
642
                    header("Location: " . $url);
643
                    exit;
644
                }
645
            }
646
647
            // Verification security graphic code
648
            if (AlDolUtils::GETPOST("username", "alpha", 2) && !empty(Globals::$conf->global->MAIN_SECURITY_ENABLECAPTCHA)) {
649
                $sessionkey = 'dol_antispam_value';
650
                $ok = (array_key_exists($sessionkey, $_SESSION) === true && (strtolower($_SESSION[$sessionkey]) == strtolower($_POST['code'])));
651
652
                // Check code
653
                if (!$ok) {
654
                    AlDolUtils::dol_syslog('Bad value for code, connexion refused');
655
656
                    // Load translation files required by page
657
                    Globals::$langs->loadLangs(array('main', 'errors'));
658
659
                    $_SESSION["dol_loginmesg"] = Globals::$langs->trans("ErrorBadValueForCode");
660
                    $test = false;
661
662
                    // Call trigger for the "security events" log
663
                    Globals::$user->trigger_mesg = 'ErrorBadValueForCode - login=' . AlDolUtils::GETPOST("username", "alpha", 2);
664
665
                    // Call of triggers
666
                    //include_once DOL_BASE_PATH . '/core/class/interfaces.class.php';
667
                    $interface = new Interfaces($db);
0 ignored issues
show
The type Alixar\Base\Interfaces was not found. Did you mean Interfaces? If so, make sure to prefix the type with \.
Loading history...
668
                    $result = $interface->run_triggers('USER_LOGIN_FAILED', Globals::$user, Globals::$user, Globals::$langs, Globals::$conf);
669
                    if ($result < 0) {
670
                        $error++;
671
                    }
672
673
                    // End Call of triggers
674
                    // Hooks on failed login
675
                    $action = '';
676
                    Globals::$hookManager->initHooks(array('login'));
677
                    $parameters = array('dol_authmode' => $this->dol_authmode, 'dol_loginmesg' => $_SESSION["dol_loginmesg"]);
678
                    $reshook = Globals::$hookManager->executeHooks('afterLoginFailed', $parameters, Globals::$user, $action);    // Note that $action and $object may have been modified by some hooks
679
                    if ($reshook < 0) {
680
                        $error++;
681
                    }
682
683
                    // Note: exit is done later
684
                }
685
            }
686
687
            $allowedmethodtopostusername = 2;
688
            if (defined('MAIN_AUTHENTICATION_POST_METHOD')) {
689
                $allowedmethodtopostusername = constant('MAIN_AUTHENTICATION_POST_METHOD');
690
            }
691
            $usertotest = (!empty($_COOKIE['login_dolibarr']) ? $_COOKIE['login_dolibarr'] : AlDolUtils::GETPOST("username", "alpha", $allowedmethodtopostusername));
692
            $passwordtotest = AlDolUtils::GETPOST('password', 'none', $allowedmethodtopostusername);
693
            $entitytotest = (AlDolUtils::GETPOST('entity', 'int') ? AlDolUtils::GETPOST('entity', 'int') : (!empty(Globals::$conf->entity) ? Globals::$conf->entity : 1));
694
695
            // Define if we received data to test the login.
696
            /*
697
              $goontestloop = false;
698
              if (isset($_SERVER["REMOTE_USER"]) && in_array('http', $this->authmode)) {
699
              $goontestloop = true;
700
              }
701
              if ($dolibarr_main_authentication == 'forceuser' && !empty($dolibarr_auto_user)) {
702
              $goontestloop = true;
703
              }
704
              if(AlDolUtils::GETPOST("username", "alpha", $allowedmethodtopostusername) || !empty($_COOKIE['login_dolibarr']) || AlDolUtils::GETPOST('openid_mode', 'alpha', 1)) {
705
              $goontestloop = true;
706
              }
707
             */
708
709
            $goontestloop = (isset($_SERVER["REMOTE_USER"]) && in_array('http', $this->authmode)) ||
710
                ($dolibarr_main_authentication == 'forceuser' && !empty($dolibarr_auto_user)) ||
711
               (AlDolUtils::GETPOST("username", "alpha", $allowedmethodtopostusername) ||
712
                !empty($_COOKIE['login_dolibarr']) ||
713
                AlDolUtils::GETPOST('openid_mode', 'alpha', 1));
714
715
            if (!is_object(Globals::$langs)) { // This can occurs when calling page with NOREQUIRETRAN defined, however we need langs for error messages.
716
                // include_once DOL_BASE_PATH . '/core/class/translate.class.php';
717
                Globals::$langs = new Translate("", Globals::$conf);
718
                $langcode = (AlDolUtils::GETPOST('lang', 'aZ09', 1) ? AlDolUtils::GETPOST('lang', 'aZ09', 1) : (empty(Globals::$conf->global->MAIN_LANG_DEFAULT) ? 'auto' : Globals::$conf->global->MAIN_LANG_DEFAULT));
719
                if (defined('MAIN_LANG_DEFAULT')) {
720
                    $langcode = constant('MAIN_LANG_DEFAULT');
721
                }
722
                Globals::$langs->setDefaultLang($langcode);
723
            }
724
725
            // Validation of login/pass/entity
726
            // If ok, the variable login will be returned
727
            // If error, we will put error message in session under the name dol_loginmesg
728
            if ($test && $goontestloop) {
729
                $login = AlSecurity2::checkLoginPassEntity($usertotest, $passwordtotest, $entitytotest, $this->authmode);
730
731
                if ($login) {
732
                    $this->dol_authmode = Globals::$conf->authmode; // This properties is defined only when logged, to say what mode was successfully used
733
                    $dol_tz = $_POST["tz"];
734
                    $dol_tz_string = $_POST["tz_string"];
735
                    $dol_tz_string = preg_replace('/\s*\(.+\)$/', '', $dol_tz_string);
736
                    $dol_tz_string = preg_replace('/,/', '/', $dol_tz_string);
737
                    $dol_tz_string = preg_replace('/\s/', '_', $dol_tz_string);
738
                    $dol_dst = 0;
739
                    if (isset($_POST["dst_first"]) && isset($_POST["dst_second"])) {
740
                        // include_once DOL_BASE_PATH . '/core/lib/date.lib.php';
741
                        $datenow = AlDolUtils::dol_now();
742
                        $datefirst = DateLib::dol_stringtotime($_POST["dst_first"]);
743
                        $datesecond = DateLib::dol_stringtotime($_POST["dst_second"]);
744
                        if ($datenow >= $datefirst && $datenow < $datesecond) {
745
                            $dol_dst = 1;
746
                        }
747
                    }
748
//print $datefirst.'-'.$datesecond.'-'.$datenow.'-'.$dol_tz.'-'.$dol_tzstring.'-'.$dol_dst; exit;
749
                }
750
751
                if (!$login) {
752
                    AlDolUtils::dol_syslog('Bad password, connexion refused', LOG_DEBUG);
753
// Load translation files required by page
754
                    Globals::$langs->loadLangs(array('main', 'errors'));
755
756
// Bad password. No authmode has found a good password.
757
// We set a generic message if not defined inside function checkLoginPassEntity or subfunctions
758
                    if (empty($_SESSION["dol_loginmesg"])) {
759
                        $_SESSION["dol_loginmesg"] = Globals::$langs->trans("ErrorBadLoginPassword");
760
                    }
761
762
                    // Call trigger for the "security events" log
763
                    Globals::$user->trigger_mesg = Globals::$langs->trans("ErrorBadLoginPassword") . ' - login=' . AlDolUtils::GETPOST("username", "alpha", 2);
764
765
                    // Call of triggers
766
                    //include_once DOL_BASE_PATH . '/core/class/interfaces.class.php';
767
                    $interface = new Interfaces();
768
                    $result = $interface->run_triggers('USER_LOGIN_FAILED', Globals::$user, Globals::$user, Globals::$langs, Globals::$conf, AlDolUtils::GETPOST("username", "alpha", 2));
769
                    if ($result < 0) {
770
                        $error++;
771
                    }
772
                    // End Call of triggers
773
                    // Hooks on failed login
774
                    $action = '';
775
                    Globals::$hookManager->initHooks(array('login'));
776
                    $parameters = array('dol_authmode' => $this->dol_authmode, 'dol_loginmesg' => $_SESSION["dol_loginmesg"]);
777
                    $reshook = Globals::$hookManager->executeHooks('afterLoginFailed', $parameters, Globals::$user, $action);    // Note that $action and $object may have been modified by some hooks
778
                    if ($reshook < 0) {
779
                        $error++;
780
                    }
781
782
                    // Note: exit is done in next chapter
783
                }
784
            }
785
786
            // End test login / passwords
787
            if (!$login || (in_array('ldap', $this->authmode) && empty($passwordtotest))) { // With LDAP we refused empty password because some LDAP are "opened" for anonymous access so connexion is a success.
788
                // No data to test login, so we show the login page
789
                AlDolUtils::dol_syslog("--- Access to " . $_SERVER["PHP_SELF"] . " showing the login form and exit");
790
                if (defined('NOREDIRECTBYMAINTOLOGIN')) {
791
                    return 'ERROR_NOT_LOGGED';
792
                } else {
793
                    AlSecurity2::dol_loginfunction($this);
794
                }
795
                exit;
796
            }
797
798
            $resultFetchUser = Globals::$user->fetch('', $login, '', 1, ($entitytotest > 0 ? $entitytotest : -1));
799
            if ($resultFetchUser <= 0) {
800
                AlDolUtils::dol_syslog('User not found, connexion refused');
801
                session_destroy();
802
                session_name($this->sessionname);
803
                session_set_cookie_params(0, '/', null, false, true);   // Add tag httponly on session cookie
804
                session_start();    // Fixing the bug of register_globals here is useless since session is empty
805
806
                if ($resultFetchUser == 0) {
807
                // Load translation files required by page
808
                    Globals::$langs->loadLangs(array('main', 'errors'));
809
810
                    $_SESSION["dol_loginmesg"] = Globals::$langs->trans("ErrorCantLoadUserFromDolibarrDatabase", $login);
811
812
                    Globals::$user->trigger_mesg = 'ErrorCantLoadUserFromDolibarrDatabase - login=' . $login;
813
                }
814
                if ($resultFetchUser < 0) {
815
                    $_SESSION["dol_loginmesg"] = Globals::$user->error;
816
817
                    Globals::$user->trigger_mesg = Globals::$user->error;
818
                }
819
820
                // Call triggers for the "security events" log
821
                //include_once DOL_BASE_PATH . '/core/class/interfaces.class.php';
822
                $interface = new Interfaces();
823
                $result = $interface->run_triggers('USER_LOGIN_FAILED', Globals::$user, Globals::$user, Globals::$langs, Globals::$conf);
824
                if ($result < 0) {
825
                    $error++;
826
                }
827
                // End call triggers
828
                // Hooks on failed login
829
                $action = '';
830
                Globals::$hookManager->initHooks(array('login'));
831
                $parameters = array('dol_authmode' => $this->dol_authmode, 'dol_loginmesg' => $_SESSION["dol_loginmesg"]);
832
                $reshook = Globals::$hookManager->executeHooks('afterLoginFailed', $parameters, Globals::$user, $action);    // Note that $action and $object may have been modified by some hooks
833
                if ($reshook < 0) {
834
                    $error++;
835
                }
836
837
                $paramsurl = array();
838
                if (AlDolUtils::GETPOST('textbrowser', 'int')) {
839
                    $paramsurl[] = 'textbrowser=' . AlDolUtils::GETPOST('textbrowser', 'int');
840
                }
841
                if (AlDolUtils::GETPOST('nojs', 'int')) {
842
                    $paramsurl[] = 'nojs=' . AlDolUtils::GETPOST('nojs', 'int');
843
                }
844
                if (AlDolUtils::GETPOST('lang', 'aZ09')) {
845
                    $paramsurl[] = 'lang=' . AlDolUtils::GETPOST('lang', 'aZ09');
846
                }
847
                echo 'Location: ' . DOL_BASE_URI . '/index.php' . (count($paramsurl) ? '?' . implode('&', $paramsurl) : '');
848
                throw Exception('x');
849
                header('Location: ' . DOL_BASE_URI . '/index.php' . (count($paramsurl) ? '?' . implode('&', $paramsurl) : ''));
850
                exit;
851
            }
852
        }
853
854
        if (isset($_SESSION['dol_login'])) {
855
            // We are already into an authenticated session
856
            $login = $_SESSION["dol_login"];
857
            $entity = $_SESSION["dol_entity"];
858
            AlDolUtils::dol_syslog("- This is an already logged session. _SESSION['dol_login']=" . $login . " _SESSION['dol_entity']=" . $entity, LOG_DEBUG);
859
860
            $resultFetchUser = Globals::$user->fetch('', $login, '', 1, ($entity > 0 ? $entity : -1));
861
            if ($resultFetchUser <= 0) {
862
                // Account has been removed after login
863
                AlDolUtils::dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=" . $login, LOG_WARNING);
864
                session_destroy();
865
                session_name($this->sessionname);
866
                session_set_cookie_params(0, '/', null, false, true);   // Add tag httponly on session cookie
867
                session_start();    // Fixing the bug of register_globals here is useless since session is empty
868
869
                if ($resultFetchUser == 0) {
870
                    // Load translation files required by page
871
                    Globals::$langs->loadLangs(array('main', 'errors'));
872
873
                    $_SESSION["dol_loginmesg"] = Globals::$langs->trans("ErrorCantLoadUserFromDolibarrDatabase", $login);
874
875
                    Globals::$user->trigger_mesg = 'ErrorCantLoadUserFromDolibarrDatabase - login=' . $login;
876
                }
877
                if ($resultFetchUser < 0) {
878
                    $_SESSION["dol_loginmesg"] = Globals::$user->error;
879
880
                    Globals::$user->trigger_mesg = Globals::$user->error;
881
                }
882
883
// Call triggers for the "security events" log
884
                //include_once DOL_BASE_PATH . '/core/class/interfaces.class.php';
885
                $interface = new Interfaces($db);
886
                $result = $interface->run_triggers('USER_LOGIN_FAILED', Globals::$user, Globals::$user, Globals::$langs, Globals::$conf);
887
                if ($result < 0) {
888
                    $error++;
889
                }
890
// End call triggers
891
// Hooks on failed login
892
                $action = '';
893
                Globals::$hookManager->initHooks(array('login'));
894
                $parameters = array('dol_authmode' => $this->dol_authmode, 'dol_loginmesg' => $_SESSION["dol_loginmesg"]);
895
                $reshook = Globals::$hookManager->executeHooks('afterLoginFailed', $parameters, Globals::$user, $action);    // Note that $action and $object may have been modified by some hooks
896
                if ($reshook < 0) {
897
                    $error++;
898
                }
899
900
                $paramsurl = array();
901
                if (AlDolUtils::GETPOST('textbrowser', 'int')) {
902
                    $paramsurl[] = 'textbrowser=' . AlDolUtils::GETPOST('textbrowser', 'int');
903
                }
904
                if (AlDolUtils::GETPOST('nojs', 'int')) {
905
                    $paramsurl[] = 'nojs=' . AlDolUtils::GETPOST('nojs', 'int');
906
                }
907
                if (AlDolUtils::GETPOST('lang', 'aZ09')) {
908
                    $paramsurl[] = 'lang=' . AlDolUtils::GETPOST('lang', 'aZ09');
909
                }
910
                echo 'Location: ' . DOL_BASE_URI . '/index.php' . (count($paramsurl) ? '?' . implode('&', $paramsurl) : '');
911
                throw Exception('x');
912
                header('Location: ' . DOL_BASE_URI . '/index.php' . (count($paramsurl) ? '?' . implode('&', $paramsurl) : ''));
913
                exit;
914
            } else {
915
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
916
                Globals::$hookManager->initHooks(array('main'));
917
918
// Code for search criteria persistence.
919
                if (!empty($_GET['save_lastsearch_values'])) {    // We must use $_GET here
920
                    $relativepathstring = preg_replace('/\?.*$/', '', $_SERVER["HTTP_REFERER"]);
921
                    $relativepathstring = preg_replace('/^https?:\/\/[^\/]*/', '', $relativepathstring);     // Get full path except host server
922
// Clean $relativepathstring
923
                    if (constant('DOL_BASE_URI')) {
924
                        $relativepathstring = preg_replace('/^' . preg_quote(constant('DOL_BASE_URI'), '/') . '/', '', $relativepathstring);
925
                    }
926
                    $relativepathstring = preg_replace('/^\//', '', $relativepathstring);
927
                    $relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
928
//var_dump($relativepathstring);
929
// We click on a link that leave a page we have to save search criteria, contextpage, limit and page. We save them from tmp to no tmp
930
                    if (!empty($_SESSION['lastsearch_values_tmp_' . $relativepathstring])) {
931
                        $_SESSION['lastsearch_values_' . $relativepathstring] = $_SESSION['lastsearch_values_tmp_' . $relativepathstring];
932
                        unset($_SESSION['lastsearch_values_tmp_' . $relativepathstring]);
933
                    }
934
                    if (!empty($_SESSION['lastsearch_contextpage_tmp_' . $relativepathstring])) {
935
                        $_SESSION['lastsearch_contextpage_' . $relativepathstring] = $_SESSION['lastsearch_contextpage_tmp_' . $relativepathstring];
936
                        unset($_SESSION['lastsearch_contextpage_tmp_' . $relativepathstring]);
937
                    }
938
                    if (!empty($_SESSION['lastsearch_page_tmp_' . $relativepathstring]) && $_SESSION['lastsearch_page_tmp_' . $relativepathstring] > 1) {
939
                        $_SESSION['lastsearch_page_' . $relativepathstring] = $_SESSION['lastsearch_page_tmp_' . $relativepathstring];
940
                        unset($_SESSION['lastsearch_page_tmp_' . $relativepathstring]);
941
                    }
942
                    if (!empty($_SESSION['lastsearch_limit_tmp_' . $relativepathstring]) && $_SESSION['lastsearch_limit_tmp_' . $relativepathstring] != Globals::$conf->liste_limit) {
943
                        $_SESSION['lastsearch_limit_' . $relativepathstring] = $_SESSION['lastsearch_limit_tmp_' . $relativepathstring];
944
                        unset($_SESSION['lastsearch_limit_tmp_' . $relativepathstring]);
945
                    }
946
                }
947
948
                $action = '';
949
                $reshook = Globals::$hookManager->executeHooks('updateSession', array(), Globals::$user, $action);
950
                if ($reshook < 0) {
951
                    setEventMessages(Globals::$hookManager->error, Globals::$hookManager->errors, 'errors');
952
                }
953
            }
954
        }
955
956
        // Is it a new session that has started ?
957
        // If we are here, this means authentication was successfull.
958
        if (!isset($_SESSION["dol_login"])) {
959
            // New session for this login has started.
960
            $error = 0;
961
962
            // Store value into session (values always stored)
963
            $_SESSION["dol_login"] = Globals::$user->login;
964
            $_SESSION["dol_authmode"] = isset($this->dol_authmode) ? $this->dol_authmode : '';
965
            $_SESSION["dol_tz"] = isset($dol_tz) ? $dol_tz : '';
966
            $_SESSION["dol_tz_string"] = isset($dol_tz_string) ? $dol_tz_string : '';
967
            $_SESSION["dol_dst"] = isset($dol_dst) ? $dol_dst : '';
968
            $_SESSION["dol_dst_observed"] = isset($dol_dst_observed) ? $dol_dst_observed : '';
969
            $_SESSION["dol_dst_first"] = isset($dol_dst_first) ? $dol_dst_first : '';
970
            $_SESSION["dol_dst_second"] = isset($dol_dst_second) ? $dol_dst_second : '';
971
            $_SESSION["dol_screenwidth"] = isset($dol_screenwidth) ? $dol_screenwidth : '';
972
            $_SESSION["dol_screenheight"] = isset($dol_screenheight) ? $dol_screenheight : '';
973
            $_SESSION["dol_company"] = Globals::$conf->global->MAIN_INFO_SOCIETE_NOM ?? '';
974
            $_SESSION["dol_entity"] = Globals::$conf->entity;
975
976
            // Store value into session (values stored only if defined)
977
            if (!empty($dol_hide_topmenu)) {
978
                $_SESSION['dol_hide_topmenu'] = $dol_hide_topmenu;
979
            }
980
            if (!empty($dol_hide_leftmenu)) {
981
                $_SESSION['dol_hide_leftmenu'] = $dol_hide_leftmenu;
982
            }
983
            if (!empty($dol_optimize_smallscreen)) {
984
                $_SESSION['dol_optimize_smallscreen'] = $dol_optimize_smallscreen;
985
            }
986
            if (!empty($dol_no_mouse_hover)) {
987
                $_SESSION['dol_no_mouse_hover'] = $dol_no_mouse_hover;
988
            }
989
            if (!empty($dol_use_jmobile)) {
990
                $_SESSION['dol_use_jmobile'] = $dol_use_jmobile;
991
            }
992
993
            AlDolUtils::dol_syslog("This is a new started user session. _SESSION['dol_login']=" . $_SESSION["dol_login"] . " Session id=" . session_id());
994
995
            // Config::$dbEngine->begin();
996
            Config::$dbEngine->beginTransaction();
997
998
            Globals::$user->update_last_login_date();
999
1000
            $loginfo = 'TZ=' . $_SESSION["dol_tz"] . ';TZString=' . $_SESSION["dol_tz_string"] . ';Screen=' . $_SESSION["dol_screenwidth"] . 'x' . $_SESSION["dol_screenheight"];
1001
1002
            // Call triggers for the "security events" log
1003
            Globals::$user->trigger_mesg = $loginfo;
1004
            // Call triggers
1005
            //include_once DOL_BASE_PATH . '/core/class/interfaces.class.php';
1006
            $interface = new Interfaces(/* $db */);
1007
            $result = $interface->run_triggers('USER_LOGIN', Globals::$user /* , Globals::$user, Globals::$langs, Globals::$conf */);
1008
            if ($result < 0) {
1009
                $error++;
1010
            }
1011
            // End call triggers
1012
            // Hooks on successfull login
1013
            $action = '';
1014
            Globals::$hookManager->initHooks(array('login'));
1015
            $parameters = array('dol_authmode' => $this->dol_authmode, 'dol_loginfo' => $loginfo);
1016
            $reshook = Globals::$hookManager->executeHooks('afterLogin', $parameters, Globals::$user, $action);    // Note that $action and $object may have been modified by some hooks
1017
            if ($reshook < 0) {
1018
                $error++;
1019
            }
1020
1021
            if ($error) {
1022
                Config::$dbEngine->rollBack();
1023
                session_destroy();
1024
                dol_print_error($db, 'Error in some triggers USER_LOGIN or in some hooks afterLogin');
1025
                exit;
1026
            } else {
1027
                Config::$dbEngine->commit();
1028
            }
1029
1030
            // Change landing page if defined.
1031
            $landingpage = (empty(Globals::$user->conf->MAIN_LANDING_PAGE) ? (empty(Globals::$conf->global->MAIN_LANDING_PAGE) ? '' : Globals::$conf->global->MAIN_LANDING_PAGE) : Globals::$user->conf->MAIN_LANDING_PAGE);
1032
            if (!empty($landingpage)) {    // Example: /index.php
1033
                $newpath = dol_buildpath($landingpage, 1);
1034
                if ($_SERVER["PHP_SELF"] != $newpath) {   // not already on landing page (avoid infinite loop)
1035
                    echo $newpath;
1036
                    throw Exception('x');
1037
                    header('Location: ' . $newpath);
1038
                    exit;
1039
                }
1040
            }
1041
        }
1042
1043
        // If user admin, we force the rights-based modules
1044
        if (Globals::$user->admin) {
1045
            Globals::$user->rights->user->user->lire = 1;
1046
            Globals::$user->rights->user->user->creer = 1;
1047
            Globals::$user->rights->user->user->password = 1;
1048
            Globals::$user->rights->user->user->supprimer = 1;
1049
            Globals::$user->rights->user->self->creer = 1;
1050
            Globals::$user->rights->user->self->password = 1;
1051
        }
1052
1053
        /*
1054
         * Overwrite some configs globals (try to avoid this and have code to use instead Globals::$user->conf->xxx)
1055
         */
1056
1057
// Set liste_limit
1058
        if (isset(Globals::$user->conf->MAIN_SIZE_LISTE_LIMIT)) {
1059
            Globals::$conf->liste_limit = Globals::$user->conf->MAIN_SIZE_LISTE_LIMIT; // Can be 0
1060
        }
1061
        if (isset(Globals::$user->conf->PRODUIT_LIMIT_SIZE)) {
1062
            Globals::$conf->product->limit_size = Globals::$user->conf->PRODUIT_LIMIT_SIZE; // Can be 0
1063
// Replace conf->css by personalized value if theme not forced
1064
        }
1065
        if (empty(Globals::$conf->global->MAIN_FORCETHEME) && !empty(Globals::$user->conf->MAIN_THEME)) {
1066
            Globals::$conf->theme = Globals::$user->conf->MAIN_THEME;
1067
// Globals::$conf->css = "/theme/" . Globals::$conf->theme . "/style.css.php";
1068
            Globals::$conf->css = '?controller=theme/' . Globals::$conf->theme . '&method=style.css';
1069
        }
1070
    }
1071
}
1072