Passed
Push — master ( 49af33...3cffbe )
by Alxarafe
21:21
created

AlixarController   F

Complexity

Total Complexity 248

Size/Duplication

Total Lines 1035
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 559
dl 0
loc 1035
rs 2
c 0
b 0
f 0
wmc 248

7 Methods

Rating   Name   Duplication   Size   Complexity  
A test_sql_and_script_inject() 0 4 1
A analyseVarsForSqlAndScriptsInjection() 0 14 5
F testLogin() 0 495 117
A stripslashes_deep() 0 3 2
F __construct() 0 345 99
B testSqlAndScriptInject() 0 57 8
C checkRequires() 0 57 16

How to fix   Complexity   

Complex Class

Complex classes like AlixarController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AlixarController, and based on these observations, apply Extract Interface, too.

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\DolUtils;
23
use Alixar\Helpers\Security;
24
use Alixar\Helpers\Security2;
25
use Alixar\Helpers\DateLib;
26
use Alixar\Base\Interfaces;
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 = DolUtils::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 = DolUtils::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
                DolUtils::dol_syslog("main.inc: dolibarr_main_force_https is on, we make a redirect to " . $newurl);
114
                echo $newurl;
115
                throw Exception('x');
0 ignored issues
show
Bug introduced by
The function Exception was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

115
                throw /** @scrutinizer ignore-call */ Exception('x');
Loading history...
116
                header("Location: " . $newurl);
0 ignored issues
show
Unused Code introduced by
header('Location: ' . $newurl) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
117
                exit;
118
            } else {
119
                DolUtils::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)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_restrict_ip seems to never exist and therefore empty should always be true.
Loading history...
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;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
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
            DolUtils::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
                DolUtils::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 = Security::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
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_nocsrfcheck seems to never exist and therefore empty should always be true.
Loading history...
180
            if ($_SERVER['REQUEST_METHOD'] == 'POST' && !DolUtils::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;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
184
            }
185
            if ($_SERVER['REQUEST_METHOD'] === 'POST') {  // This test must be after loading $_SESSION['token'].
186
                if (DolUtils::GETPOST('token', 'alpha') != $_SESSION['token']) {
187
                    DolUtils::dol_syslog("Invalid token in " . $_SERVER['HTTP_REFERER'] . ", action=" . DolUtils::GETPOST('action', 'aZ09') . ", _POST['token']=" . DolUtils::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 (DolUtils::GETPOST('disablemodules', 'alpha')) {
196
            $_SESSION["disablemodules"] = DolUtils::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();
0 ignored issues
show
Bug introduced by
The type Alixar\Base\stdClass was not found. Did you mean stdClass? If so, make sure to prefix the type with \.
Loading history...
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 (DolUtils::GETPOST('theme', 'alpha')) {
218
            Globals::$conf->theme = DolUtils::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 (!DolUtils::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;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
228
            }
229
        } else {
230
            Globals::$conf->use_javascript_ajax = 0;
231
        }
232
        // Set MAIN_OPTIMIZEFORTEXTBROWSER
233
        if (DolUtils::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 (DolUtils::GETPOST('dol_hide_leftmenu', 'int') || !empty($_SESSION['dol_hide_leftmenu'])) {
241
            Globals::$conf->dol_hide_leftmenu = 1;
242
        }
243
        if (DolUtils::GETPOST('dol_hide_topmenu', 'int') || !empty($_SESSION['dol_hide_topmenu'])) {
244
            Globals::$conf->dol_hide_topmenu = 1;
245
        }
246
        if (DolUtils::GETPOST('dol_optimize_smallscreen', 'int') || !empty($_SESSION['dol_optimize_smallscreen'])) {
247
            Globals::$conf->dol_optimize_smallscreen = 1;
248
        }
249
        if (DolUtils::GETPOST('dol_no_mouse_hover', 'int') || !empty($_SESSION['dol_no_mouse_hover'])) {
250
            Globals::$conf->dol_no_mouse_hover = 1;
251
        }
252
        if (DolUtils::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 (!DolUtils::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
                DolUtils::dol_syslog("Authentification ko as login is disabled");
298
                accessforbidden(Globals::$langs->trans("ErrorLoginDisabled"));
299
                exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
300
            }
301
302
            // Load permissions
303
            Globals::$user->getrights();
304
        }
305
306
307
        DolUtils::dol_syslog("--- Access to " . $_SERVER["PHP_SELF"] . ' - action=' . DolUtils::GETPOST('action', 'az09') . ', massaction=' . DolUtils::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 (DolUtils::GETPOST('menu', 'alpha')) {
367
                $file_menu = DolUtils::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
                    DolUtils::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;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
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
     * Security: 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
     * Security: 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;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
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)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_authentication seems to never exist and therefore empty should always be true.
Loading history...
588
                $dolibarr_main_authentication = 'http,dolibarr';
589
            }
590
            // Authentication mode: forceuser
591
            if ($dolibarr_main_authentication == 'forceuser' && empty($dolibarr_auto_user)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_auto_user seems to never exist and therefore empty should always be true.
Loading history...
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!');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
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 = DolUtils::GETPOST("dst_observed", 'int', 3);
617
            $dol_dst_first = DolUtils::GETPOST("dst_first", 'int', 3);
618
            $dol_dst_second = DolUtils::GETPOST("dst_second", 'int', 3);
619
            $dol_screenwidth = DolUtils::GETPOST("screenwidth", 'int', 3);
620
            $dol_screenheight = DolUtils::GETPOST("screenheight", 'int', 3);
621
            $dol_hide_topmenu = DolUtils::GETPOST('dol_hide_topmenu', 'int', 3);
622
            $dol_hide_leftmenu = DolUtils::GETPOST('dol_hide_leftmenu', 'int', 3);
623
            $dol_optimize_smallscreen = DolUtils::GETPOST('dol_optimize_smallscreen', 'int', 3);
624
            $dol_no_mouse_hover = DolUtils::GETPOST('dol_no_mouse_hover', 'int', 3);
625
            $dol_use_jmobile = DolUtils::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') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_demo does not exist. Did you maybe mean $dolibarr_main_authentication?
Loading history...
630
                // We ask index page
631
                if (empty($_SERVER['HTTP_REFERER']) || !preg_match('/public/', $_SERVER['HTTP_REFERER'])) {
632
                    DolUtils::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');
0 ignored issues
show
Bug introduced by
The function Exception was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

641
                    throw /** @scrutinizer ignore-call */ Exception('x');
Loading history...
642
                    header("Location: " . $url);
0 ignored issues
show
Unused Code introduced by
header('Location: ' . $url) is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
643
                    exit;
644
                }
645
            }
646
647
            // Verification security graphic code
648
            if (DolUtils::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
                    DolUtils::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=' . DolUtils::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
Comprehensibility Best Practice introduced by
The variable $db seems to be never defined.
Loading history...
668
                    $result = $interface->run_triggers('USER_LOGIN_FAILED', Globals::$user, Globals::$user, Globals::$langs, Globals::$conf);
669
                    if ($result < 0) {
670
                        $error++;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $error seems to be never defined.
Loading history...
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'] : DolUtils::GETPOST("username", "alpha", $allowedmethodtopostusername));
692
            $passwordtotest = DolUtils::GETPOST('password', 'none', $allowedmethodtopostusername);
693
            $entitytotest = (DolUtils::GETPOST('entity', 'int') ? DolUtils::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 (DolUtils::GETPOST("username", "alpha", $allowedmethodtopostusername) || !empty($_COOKIE['login_dolibarr']) || DolUtils::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
                (DolUtils::GETPOST("username", "alpha", $allowedmethodtopostusername) ||
712
                !empty($_COOKIE['login_dolibarr']) ||
713
                DolUtils::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);
0 ignored issues
show
Bug introduced by
The type Alixar\Base\Translate was not found. Did you mean Translate? If so, make sure to prefix the type with \.
Loading history...
718
                $langcode = (DolUtils::GETPOST('lang', 'aZ09', 1) ? DolUtils::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 = Security2::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 = DolUtils::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
                    DolUtils::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=' . DolUtils::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, DolUtils::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
                DolUtils::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
                    Security2::dol_loginfunction($this);
794
                }
795
                exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
796
            }
797
798
            $resultFetchUser = Globals::$user->fetch('', $login, '', 1, ($entitytotest > 0 ? $entitytotest : -1));
799
            if ($resultFetchUser <= 0) {
800
                DolUtils::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 (DolUtils::GETPOST('textbrowser', 'int')) {
839
                    $paramsurl[] = 'textbrowser=' . DolUtils::GETPOST('textbrowser', 'int');
840
                }
841
                if (DolUtils::GETPOST('nojs', 'int')) {
842
                    $paramsurl[] = 'nojs=' . DolUtils::GETPOST('nojs', 'int');
843
                }
844
                if (DolUtils::GETPOST('lang', 'aZ09')) {
845
                    $paramsurl[] = 'lang=' . DolUtils::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
            DolUtils::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
                DolUtils::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 (DolUtils::GETPOST('textbrowser', 'int')) {
902
                    $paramsurl[] = 'textbrowser=' . DolUtils::GETPOST('textbrowser', 'int');
903
                }
904
                if (DolUtils::GETPOST('nojs', 'int')) {
905
                    $paramsurl[] = 'nojs=' . DolUtils::GETPOST('nojs', 'int');
906
                }
907
                if (DolUtils::GETPOST('lang', 'aZ09')) {
908
                    $paramsurl[] = 'lang=' . DolUtils::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
            DolUtils::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;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
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