Completed
Branch develop (edb367)
by
unknown
28:40
created

main.inc.php ➔ test_sql_and_script_inject()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/* Copyright (C) 2002-2007  Rodolphe Quiedeville    <[email protected]>
3
 * Copyright (C) 2003       Xavier Dutoit           <[email protected]>
4
 * Copyright (C) 2004-2015  Laurent Destailleur     <[email protected]>
5
 * Copyright (C) 2004       Sebastien Di Cintio     <[email protected]>
6
 * Copyright (C) 2004       Benoit Mortier          <[email protected]>
7
 * Copyright (C) 2005-2015  Regis Houssin           <[email protected]>
8
 * Copyright (C) 2011-2014  Philippe Grand          <[email protected]>
9
 * Copyright (C) 2008       Matteli
10
 * Copyright (C) 2011-2016  Juanjo Menent           <[email protected]>
11
 * Copyright (C) 2012       Christophe Battarel     <[email protected]>
12
 * Copyright (C) 2014-2015  Marcos García           <[email protected]>
13
 * Copyright (C) 2015       Raphaël Doursenaud      <[email protected]>
14
 *
15
 * This program is free software; you can redistribute it and/or modify
16
 * it under the terms of the GNU General Public License as published by
17
 * the Free Software Foundation; either version 3 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU General Public License
26
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27
 */
28
29
/**
30
 *	\file       htdocs/main.inc.php
31
 *	\ingroup	core
32
 *	\brief      File that defines environment for Dolibarr GUI pages only (file not required by scripts)
33
 */
34
35
//@ini_set('memory_limit', '128M');	// This may be useless if memory is hard limited by your PHP
36
37
// For optional tuning. Enabled if environment variable MAIN_SHOW_TUNING_INFO is defined.
38
$micro_start_time=0;
39
if (! empty($_SERVER['MAIN_SHOW_TUNING_INFO']))
40
{
41
	list($usec, $sec) = explode(" ", microtime());
42
	$micro_start_time=((float) $usec + (float) $sec);
43
	// Add Xdebug code coverage
44
	//define('XDEBUGCOVERAGE',1);
45
	if (defined('XDEBUGCOVERAGE')) {
46
		xdebug_start_code_coverage();
47
	}
48
}
49
50
// Removed magic_quotes
51
if (function_exists('get_magic_quotes_gpc'))	// magic_quotes_* deprecated in PHP 5.0 and removed in PHP 5.5
52
{
53
	if (get_magic_quotes_gpc())
54
	{
55
		// Forcing parameter setting magic_quotes_gpc and cleaning parameters
56
		// (Otherwise he would have for each position, condition
57
		// Reading stripslashes variable according to state get_magic_quotes_gpc).
58
		// Off mode recommended (just do $db->escape for insert / update).
59
		function stripslashes_deep($value)
0 ignored issues
show
Best Practice introduced by
The function stripslashes_deep() has been defined more than once; this definition is ignored, only the first definition in htdocs/install/inc.php (L265-268) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

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

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
1002
	{
1003
		global $conf;
1004
1005
		// html header
1006
		top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
1007
1008
		print '<body id="mainbody"'.($morecssonbody?' class="'.$morecssonbody.'"':'').'>' . "\n";
1009
1010
		// top menu and left menu area
1011
		if (empty($conf->dol_hide_topmenu) || GETPOST('dol_invisible_topmenu','int'))
1012
		{
1013
			top_menu($head, $title, $target, $disablejs, $disablehead, $arrayofjs, $arrayofcss, $morequerystring, $help_url);
1014
		}
1015
1016
		if (empty($conf->dol_hide_leftmenu))
1017
		{
1018
			left_menu('', $help_url, '', '', 1, $title, 1);
1019
		}
1020
1021
		// main area
1022
		if ($replacemainareaby)
1023
		{
1024
			print $replacemainareaby;
1025
			return;
1026
		}
1027
		main_area($title);
1028
	}
1029
}
1030
1031
1032
/**
1033
 *  Show HTTP header
1034
 *
1035
 *  @param  string  $contenttype    Content type. For example, 'text/html'
1036
 *  @param	int		$forcenocache	Force disabling of cache for the page
1037
 *  @return	void
1038
 */
1039
function top_httphead($contenttype='text/html', $forcenocache=0)
1040
{
1041
	global $db, $conf, $hookmanager;
1042
1043
	if ($contenttype == 'text/html' ) header("Content-Type: text/html; charset=".$conf->file->character_set_client);
1044
	else header("Content-Type: ".$contenttype);
1045
	// Security options
1046
	header("X-Content-Type-Options: nosniff");  // With the nosniff option, if the server says the content is text/html, the browser will render it as text/html (note that most browsers now force this option to on)
1047
	header("X-Frame-Options: SAMEORIGIN");      // Frames allowed only if on same domain (stop some XSS attacks)
1048
	//header("X-XSS-Protection: 1");      		// XSS protection of some browsers (note: use of Content-Security-Policy is more efficient). Disabled as deprecated.
1049
	if (! defined('FORCECSP'))
1050
	{
1051
		//if (! isset($conf->global->MAIN_HTTP_CONTENT_SECURITY_POLICY))
1052
		//{
1053
		//	// A default security policy that keep usage of js external component like ckeditor, stripe, google, working
1054
		//	$contentsecuritypolicy = "font-src *; img-src *; style-src * 'unsafe-inline' 'unsafe-eval'; default-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; script-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; frame-src 'self' *.stripe.com; connect-src 'self';";
1055
		//}
1056
		//else $contentsecuritypolicy = $conf->global->MAIN_HTTP_CONTENT_SECURITY_POLICY;
1057
		$contentsecuritypolicy = $conf->global->MAIN_HTTP_CONTENT_SECURITY_POLICY;
1058
1059
		if (! is_object($hookmanager)) $hookmanager = new HookManager($db);
1060
		$hookmanager->initHooks("main");
1061
1062
		$parameters=array('contentsecuritypolicy'=>$contentsecuritypolicy);
1063
		$result=$hookmanager->executeHooks('setContentSecurityPolicy',$parameters);    // Note that $action and $object may have been modified by some hooks
1064
		if ($result > 0) $contentsecuritypolicy = $hookmanager->resPrint;	// Replace CSP
1065
		else $contentsecuritypolicy .= $hookmanager->resPrint;				// Concat CSP
1066
1067
		if (! empty($contentsecuritypolicy))
1068
		{
1069
			// For example, to restrict 'script', 'object', 'frames' or 'img' to some domains:
1070
			// script-src https://api.google.com https://anotherhost.com; object-src https://youtube.com; frame-src https://youtube.com; img-src: https://static.example.com
1071
			// For example, to restrict everything to one domain, except 'object', ...:
1072
			// default-src https://cdn.example.net; object-src 'none'
1073
			// For example, to restrict everything to itself except img that can be on other servers:
1074
			// default-src 'self'; img-src *;
1075
			// Pre-existing site that uses too much inline code to fix but wants to ensure resources are loaded only over https and disable plugins:
1076
			// default-src http: https: 'unsafe-eval' 'unsafe-inline'; object-src 'none'
1077
			header("Content-Security-Policy: ".$contentsecuritypolicy);
1078
		}
1079
	}
1080
	elseif (constant('FORCECSP'))
1081
	{
1082
		header("Content-Security-Policy: ".constant('FORCECSP'));
1083
	}
1084
	if ($forcenocache)
1085
	{
1086
		header("Cache-Control: no-cache, no-store, must-revalidate, max-age=0");
1087
	}
1088
}
1089
1090
/**
1091
 * Ouput html header of a page.
1092
 * This code is also duplicated into security2.lib.php::dol_loginfunction
1093
 *
1094
 * @param 	string 	$head			 Optionnal head lines
1095
 * @param 	string 	$title			 HTML title
1096
 * @param 	int    	$disablejs		 Disable js output
1097
 * @param 	int    	$disablehead	 Disable head output
1098
 * @param 	array  	$arrayofjs		 Array of complementary js files
1099
 * @param 	array  	$arrayofcss		 Array of complementary css files
1100
 * @param 	int    	$disablejmobile	 Disable jmobile (No more used)
1101
 * @param   int     $disablenofollow Disable no follow tag
1102
 * @return	void
1103
 */
1104
function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $disablejmobile=0, $disablenofollow=0)
1105
{
1106
	global $db, $conf, $langs, $user, $hookmanager;
1107
1108
	top_httphead();
1109
1110
	if (empty($conf->css)) $conf->css = '/theme/eldy/style.css.php';	// If not defined, eldy by default
1111
1112
	print '<!doctype html>'."\n";
1113
1114
	if (! empty($conf->global->MAIN_USE_CACHE_MANIFEST)) print '<html lang="'.substr($langs->defaultlang,0,2).'" manifest="'.DOL_URL_ROOT.'/cache.manifest">'."\n";
1115
	else print '<html lang="'.substr($langs->defaultlang,0,2).'">'."\n";
1116
	//print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">'."\n";
1117
	if (empty($disablehead))
1118
	{
1119
		$ext='layout='.$conf->browser->layout.'&version='.urlencode(DOL_VERSION);
1120
1121
		print "<head>\n";
1122
1123
		if (GETPOST('dol_basehref','alpha')) print '<base href="'.dol_escape_htmltag(GETPOST('dol_basehref','alpha')).'">'."\n";
1124
1125
		// Displays meta
1126
		print '<meta charset="UTF-8">'."\n";
1127
		print '<meta name="robots" content="noindex'.($disablenofollow?'':',nofollow').'">'."\n";	// Do not index
1128
		print '<meta name="viewport" content="width=device-width, initial-scale=1.0">'."\n";		// Scale for mobile device
1129
		print '<meta name="author" content="Dolibarr Development Team">'."\n";
1130
1131
		// Favicon
1132
		$favicon=dol_buildpath('/theme/'.$conf->theme.'/img/favicon.ico',1);
1133
		if (! empty($conf->global->MAIN_FAVICON_URL)) $favicon=$conf->global->MAIN_FAVICON_URL;
1134
		if (empty($conf->dol_use_jmobile)) print '<link rel="shortcut icon" type="image/x-icon" href="'.$favicon.'"/>'."\n";	// Not required into an Android webview
1135
		//if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) print '<link rel="top" title="'.$langs->trans("Home").'" href="'.(DOL_URL_ROOT?DOL_URL_ROOT:'/').'">'."\n";
1136
		//if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) print '<link rel="copyright" title="GNU General Public License" href="http://www.gnu.org/copyleft/gpl.html#SEC1">'."\n";
1137
		//if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) print '<link rel="author" title="Dolibarr Development Team" href="https://www.dolibarr.org">'."\n";
1138
1139
		// Auto refresh page
1140
		if (GETPOST('autorefresh','int') > 0) print '<meta http-equiv="refresh" content="'.GETPOST('autorefresh','int').'">';
1141
1142
		// Displays title
1143
		$appli=constant('DOL_APPLICATION_TITLE');
1144
		if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $appli=$conf->global->MAIN_APPLICATION_TITLE;
1145
1146
		print '<title>';
1147
		$titletoshow='';
1148
		if ($title && ! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/noapp/',$conf->global->MAIN_HTML_TITLE)) $titletoshow = dol_htmlentities($title);
1149
		else if ($title) $titletoshow = dol_htmlentities($appli.' - '.$title);
1150
		else $titletoshow = dol_htmlentities($appli);
1151
1152
		if (! is_object($hookmanager)) $hookmanager = new HookManager($db);
1153
		$hookmanager->initHooks("main");
1154
		$parameters=array('title'=>$titletoshow);
1155
		$result=$hookmanager->executeHooks('setHtmlTitle',$parameters);		// Note that $action and $object may have been modified by some hooks
1156
		if ($result > 0) $titletoshow = $hookmanager->resPrint;				// Replace Title to show
1157
		else $titletoshow .= $hookmanager->resPrint;						// Concat to Title to show
1158
1159
		print $titletoshow;
1160
		print '</title>';
1161
1162
		print "\n";
1163
1164
		if (GETPOST('version','int')) $ext='version='.GETPOST('version','int');	// usefull to force no cache on css/js
1165
		if (GETPOST('testmenuhider','int') || ! empty($conf->global->MAIN_TESTMENUHIDER)) $ext.='&testmenuhider='.(GETPOST('testmenuhider','int')?GETPOST('testmenuhider','int'):$conf->global->MAIN_TESTMENUHIDER);
1166
1167
		$themeparam='?lang='.$langs->defaultlang.'&amp;theme='.$conf->theme.(GETPOST('optioncss','aZ09')?'&amp;optioncss='.GETPOST('optioncss','aZ09',1):'').'&amp;userid='.$user->id.'&amp;entity='.$conf->entity;
1168
		$themeparam.=($ext?'&amp;'.$ext:'');
1169
		if (! empty($_SESSION['dol_resetcache'])) $themeparam.='&amp;dol_resetcache='.$_SESSION['dol_resetcache'];
1170
		if (GETPOST('dol_hide_topmenu','int'))           { $themeparam.='&amp;dol_hide_topmenu='.GETPOST('dol_hide_topmenu','int'); }
1171
		if (GETPOST('dol_hide_leftmenu','int'))          { $themeparam.='&amp;dol_hide_leftmenu='.GETPOST('dol_hide_leftmenu','int'); }
1172
		if (GETPOST('dol_optimize_smallscreen','int'))   { $themeparam.='&amp;dol_optimize_smallscreen='.GETPOST('dol_optimize_smallscreen','int'); }
1173
		if (GETPOST('dol_no_mouse_hover','int'))         { $themeparam.='&amp;dol_no_mouse_hover='.GETPOST('dol_no_mouse_hover','int'); }
1174
		if (GETPOST('dol_use_jmobile','int'))            { $themeparam.='&amp;dol_use_jmobile='.GETPOST('dol_use_jmobile','int'); $conf->dol_use_jmobile=GETPOST('dol_use_jmobile','int'); }
1175
1176
		if (! defined('DISABLE_JQUERY') && ! $disablejs && $conf->use_javascript_ajax)
1177
		{
1178
			print '<!-- Includes CSS for JQuery (Ajax library) -->'."\n";
1179
			$jquerytheme = 'base';
1180
			if (!empty($conf->global->MAIN_USE_JQUERY_THEME)) $jquerytheme = $conf->global->MAIN_USE_JQUERY_THEME;
1181
			if (constant('JS_JQUERY_UI')) print '<link rel="stylesheet" type="text/css" href="'.JS_JQUERY_UI.'css/'.$jquerytheme.'/jquery-ui.min.css'.($ext?'?'.$ext:'').'">'."\n";  // JQuery
1182
			else print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/css/'.$jquerytheme.'/jquery-ui.css'.($ext?'?'.$ext:'').'">'."\n";    // JQuery
1183
			if (! defined('DISABLE_JQUERY_JNOTIFY')) print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/jnotify/jquery.jnotify-alt.min.css'.($ext?'?'.$ext:'').'">'."\n";          // JNotify
1184
			if (! defined('DISABLE_SELECT2') && (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT')))     // jQuery plugin "mutiselect", "multiple-select", "select2"...
1185
			{
1186
				$tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?constant('REQUIRE_JQUERY_MULTISELECT'):$conf->global->MAIN_USE_JQUERY_MULTISELECT;
1187
				print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/'.$tmpplugin.'/dist/css/'.$tmpplugin.'.css'.($ext?'?'.$ext:'').'">'."\n";
1188
			}
1189
		}
1190
1191
		if (! defined('DISABLE_FONT_AWSOME'))
1192
		{
1193
			print '<!-- Includes CSS for font awesome -->'."\n";
1194
			print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/theme/common/fontawesome/css/font-awesome.min.css'.($ext?'?'.$ext:'').'">'."\n";
1195
		}
1196
1197
		print '<!-- Includes CSS for Dolibarr theme -->'."\n";
1198
		// Output style sheets (optioncss='print' or ''). Note: $conf->css looks like '/theme/eldy/style.css.php'
1199
		$themepath=dol_buildpath($conf->css,1);
1200
		$themesubdir='';
1201
		if (! empty($conf->modules_parts['theme']))	// This slow down
1202
		{
1203
			foreach($conf->modules_parts['theme'] as $reldir)
1204
			{
1205
				if (file_exists(dol_buildpath($reldir.$conf->css, 0)))
1206
				{
1207
					$themepath=dol_buildpath($reldir.$conf->css, 1);
1208
					$themesubdir=$reldir;
1209
					break;
1210
				}
1211
			}
1212
		}
1213
1214
		//print 'themepath='.$themepath.' themeparam='.$themeparam;exit;
1215
		print '<link rel="stylesheet" type="text/css" href="'.$themepath.$themeparam.'">'."\n";
1216
		if (! empty($conf->global->MAIN_FIX_FLASH_ON_CHROME)) print '<!-- Includes CSS that does not exists as a workaround of flash bug of chrome -->'."\n".'<link rel="stylesheet" type="text/css" href="filethatdoesnotexiststosolvechromeflashbug">'."\n";
1217
1218
		// CSS forced by modules (relative url starting with /)
1219
		if (! empty($conf->modules_parts['css']))
1220
		{
1221
			$arraycss=(array) $conf->modules_parts['css'];
1222
			foreach($arraycss as $modcss => $filescss)
1223
			{
1224
				$filescss=(array) $filescss;	// To be sure filecss is an array
1225
				foreach($filescss as $cssfile)
1226
				{
1227
					if (empty($cssfile)) dol_syslog("Warning: module ".$modcss." declared a css path file into its descriptor that is empty.", LOG_WARNING);
1228
					// cssfile is a relative path
1229
					print '<!-- Includes CSS added by module '.$modcss. ' -->'."\n".'<link rel="stylesheet" type="text/css" href="'.dol_buildpath($cssfile,1);
1230
					// We add params only if page is not static, because some web server setup does not return content type text/css if url has parameters, so browser cache is not used.
1231
					if (!preg_match('/\.css$/i',$cssfile)) print $themeparam;
1232
					print '">'."\n";
1233
				}
1234
			}
1235
		}
1236
		// CSS forced by page in top_htmlhead call (relative url starting with /)
1237
		if (is_array($arrayofcss))
1238
		{
1239
			foreach($arrayofcss as $cssfile)
1240
			{
1241
				print '<!-- Includes CSS added by page -->'."\n".'<link rel="stylesheet" type="text/css" title="default" href="'.dol_buildpath($cssfile,1);
1242
				// We add params only if page is not static, because some web server setup does not return content type text/css if url has parameters and browser cache is not used.
1243
				if (!preg_match('/\.css$/i',$cssfile)) print $themeparam;
1244
				print '">'."\n";
1245
			}
1246
		}
1247
1248
		// Output standard javascript links
1249
		if (! defined('DISABLE_JQUERY') && ! $disablejs && ! empty($conf->use_javascript_ajax))
1250
		{
1251
			// JQuery. Must be before other includes
1252
			print '<!-- Includes JS for JQuery -->'."\n";
1253
			if (defined('JS_JQUERY') && constant('JS_JQUERY')) print '<script type="text/javascript" src="'.JS_JQUERY.'jquery.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1254
			else print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/js/jquery.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1255
			if (! empty($conf->global->MAIN_FEATURES_LEVEL) && ! defined('JS_JQUERY_MIGRATE_DISABLED'))
1256
			{
1257
				if (defined('JS_JQUERY_MIGRATE') && constant('JS_JQUERY_MIGRATE')) print '<script type="text/javascript" src="'.JS_JQUERY_MIGRATE.'jquery-migrate.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1258
				else print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/js/jquery-migrate.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1259
			}
1260
			if (defined('JS_JQUERY_UI') && constant('JS_JQUERY_UI')) print '<script type="text/javascript" src="'.JS_JQUERY_UI.'jquery-ui.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1261
			else print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/js/jquery-ui.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1262
			if (! defined('DISABLE_JQUERY_TABLEDND')) print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/tablednd/jquery.tablednd.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1263
			// jQuery jnotify
1264
			if (empty($conf->global->MAIN_DISABLE_JQUERY_JNOTIFY) && ! defined('DISABLE_JQUERY_JNOTIFY'))
1265
			{
1266
				print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jnotify/jquery.jnotify.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1267
			}
1268
			// Flot
1269
			if (empty($conf->global->MAIN_DISABLE_JQUERY_FLOT) && ! defined('DISABLE_JQUERY_FLOT'))
1270
			{
1271
				if (constant('JS_JQUERY_FLOT'))
1272
				{
1273
					print '<script type="text/javascript" src="'.JS_JQUERY_FLOT.'jquery.flot.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1274
					print '<script type="text/javascript" src="'.JS_JQUERY_FLOT.'jquery.flot.pie.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1275
					print '<script type="text/javascript" src="'.JS_JQUERY_FLOT.'jquery.flot.stack.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1276
				}
1277
				else
1278
				{
1279
					print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/flot/jquery.flot.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1280
					print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/flot/jquery.flot.pie.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1281
					print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/flot/jquery.flot.stack.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1282
				}
1283
			}
1284
			// jQuery jeditable
1285
			if (! empty($conf->global->MAIN_USE_JQUERY_JEDITABLE) && ! defined('DISABLE_JQUERY_JEDITABLE'))
1286
			{
1287
				print '<!-- JS to manage editInPlace feature -->'."\n";
1288
				print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1289
				print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.ui-datepicker.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1290
				print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.ui-autocomplete.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1291
				print '<script type="text/javascript">'."\n";
1292
				print 'var urlSaveInPlace = \''.DOL_URL_ROOT.'/core/ajax/saveinplace.php\';'."\n";
1293
				print 'var urlLoadInPlace = \''.DOL_URL_ROOT.'/core/ajax/loadinplace.php\';'."\n";
1294
				print 'var tooltipInPlace = \''.$langs->transnoentities('ClickToEdit').'\';'."\n";	// Added in title attribute of span
1295
				print 'var placeholderInPlace = \'&nbsp;\';'."\n";	// If we put another string than $langs->trans("ClickToEdit") here, nothing is shown. If we put empty string, there is error, Why ?
1296
				print 'var cancelInPlace = \''.$langs->trans('Cancel').'\';'."\n";
1297
				print 'var submitInPlace = \''.$langs->trans('Ok').'\';'."\n";
1298
				print 'var indicatorInPlace = \'<img src="'.DOL_URL_ROOT."/theme/".$conf->theme."/img/working.gif".'">\';'."\n";
1299
				print 'var withInPlace = 300;';		// width in pixel for default string edit
1300
				print '</script>'."\n";
1301
				print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/editinplace.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1302
				print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.ckeditor.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1303
			}
1304
            // jQuery Timepicker
1305
            if (! empty($conf->global->MAIN_USE_JQUERY_TIMEPICKER) || defined('REQUIRE_JQUERY_TIMEPICKER'))
1306
            {
1307
            	print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/timepicker/jquery-ui-timepicker-addon.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1308
            	print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/timepicker.js.php?lang='.$langs->defaultlang.($ext?'&amp;'.$ext:'').'"></script>'."\n";
1309
            }
1310
            if (! defined('DISABLE_SELECT2') && (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT')))     // jQuery plugin "mutiselect", "multiple-select", "select2", ...
1311
            {
1312
            	$tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?constant('REQUIRE_JQUERY_MULTISELECT'):$conf->global->MAIN_USE_JQUERY_MULTISELECT;
1313
            	print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/'.$tmpplugin.'/dist/js/'.$tmpplugin.'.full.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";	// We include full because we need the support of containerCssClass
1314
            }
1315
            if (! defined('DISABLE_MULTISELECT'))     // jQuery plugin "mutiselect" to select with checkboxes
1316
            {
1317
            	print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/multiselect/jquery.multi-select.js'.($ext?'?'.$ext:'').'"></script>'."\n";
1318
            }
1319
		}
1320
1321
        if (! $disablejs && ! empty($conf->use_javascript_ajax))
1322
        {
1323
            // CKEditor
1324
            if (! empty($conf->fckeditor->enabled) && (empty($conf->global->FCKEDITOR_EDITORNAME) || $conf->global->FCKEDITOR_EDITORNAME == 'ckeditor') && ! defined('DISABLE_CKEDITOR'))
1325
            {
1326
                print '<!-- Includes JS for CKEditor -->'."\n";
1327
                $pathckeditor = DOL_URL_ROOT . '/includes/ckeditor/ckeditor/';
1328
                $jsckeditor='ckeditor.js';
1329
                if (constant('JS_CKEDITOR'))	// To use external ckeditor 4 js lib
1330
                {
1331
                	$pathckeditor=constant('JS_CKEDITOR');
1332
                }
1333
                print '<script type="text/javascript">';
1334
                print 'var CKEDITOR_BASEPATH = \''.$pathckeditor.'\';'."\n";
1335
                print 'var ckeditorConfig = \''.dol_buildpath($themesubdir.'/theme/'.$conf->theme.'/ckeditor/config.js'.($ext?'?'.$ext:''),1).'\';'."\n";		// $themesubdir='' in standard usage
1336
                print 'var ckeditorFilebrowserBrowseUrl = \''.DOL_URL_ROOT.'/core/filemanagerdol/browser/default/browser.php?Connector='.DOL_URL_ROOT.'/core/filemanagerdol/connectors/php/connector.php\';'."\n";
1337
                print 'var ckeditorFilebrowserImageBrowseUrl = \''.DOL_URL_ROOT.'/core/filemanagerdol/browser/default/browser.php?Type=Image&Connector='.DOL_URL_ROOT.'/core/filemanagerdol/connectors/php/connector.php\';'."\n";
1338
                print '</script>'."\n";
1339
                print '<script type="text/javascript" src="'.$pathckeditor.$jsckeditor.($ext?'?'.$ext:'').'"></script>'."\n";
1340
            }
1341
1342
            // Browser notifications
1343
            if (! defined('DISABLE_BROWSER_NOTIF'))
1344
            {
1345
                $enablebrowsernotif=false;
1346
                if (! empty($conf->agenda->enabled) && ! empty($conf->global->AGENDA_REMINDER_BROWSER)) $enablebrowsernotif=true;
1347
                if ($conf->browser->layout == 'phone') $enablebrowsernotif=false;
1348
                if ($enablebrowsernotif)
1349
                {
1350
                    print '<!-- Includes JS of Dolibarr (brwoser layout = '.$conf->browser->layout.')-->'."\n";
1351
                    print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/lib_notification.js.php'.($ext?'?'.$ext:'').'"></script>'."\n";
1352
                }
1353
            }
1354
1355
            // Global js function
1356
            print '<!-- Includes JS of Dolibarr -->'."\n";
1357
            print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/lib_head.js.php?lang='.$langs->defaultlang.($ext?'&'.$ext:'').'"></script>'."\n";
1358
1359
            // JS forced by modules (relative url starting with /)
1360
            if (! empty($conf->modules_parts['js']))		// $conf->modules_parts['js'] is array('module'=>array('file1','file2'))
1361
        	{
1362
        		$arrayjs=(array) $conf->modules_parts['js'];
1363
	            foreach($arrayjs as $modjs => $filesjs)
1364
	            {
1365
        			$filesjs=(array) $filesjs;	// To be sure filejs is an array
1366
		            foreach($filesjs as $jsfile)
1367
		            {
1368
	    	    		// jsfile is a relative path
1369
	        	    	print '<!-- Include JS added by module '.$modjs. '-->'."\n".'<script type="text/javascript" src="'.dol_buildpath($jsfile,1).'"></script>'."\n";
1370
		            }
1371
	            }
1372
        	}
1373
            // JS forced by page in top_htmlhead (relative url starting with /)
1374
            if (is_array($arrayofjs))
1375
            {
1376
                print '<!-- Includes JS added by page -->'."\n";
1377
                foreach($arrayofjs as $jsfile)
1378
                {
1379
                    if (preg_match('/^http/i',$jsfile))
1380
                    {
1381
                        print '<script type="text/javascript" src="'.$jsfile.'"></script>'."\n";
1382
                    }
1383
                    else
1384
                    {
1385
                        if (! preg_match('/^\//',$jsfile)) $jsfile='/'.$jsfile;	// For backward compatibility
1386
                        print '<script type="text/javascript" src="'.dol_buildpath($jsfile,1).'"></script>'."\n";
1387
                    }
1388
                }
1389
            }
1390
        }
1391
1392
        if (! empty($head)) print $head."\n";
1393
        if (! empty($conf->global->MAIN_HTML_HEADER)) print $conf->global->MAIN_HTML_HEADER."\n";
1394
1395
        print "</head>\n\n";
1396
    }
1397
1398
    $conf->headerdone=1;	// To tell header was output
1399
}
1400
1401
1402
/**
1403
 *  Show an HTML header + a BODY + The top menu bar
1404
 *
1405
 *  @param      string	$head    			Lines in the HEAD
1406
 *  @param      string	$title   			Title of web page
1407
 *  @param      string	$target  			Target to use in menu links (Example: '' or '_top')
1408
 *	@param		int		$disablejs			Do not output links to js (Ex: qd fonction utilisee par sous formulaire Ajax)
1409
 *	@param		int		$disablehead		Do not output head section
1410
 *	@param		array	$arrayofjs			Array of js files to add in header
1411
 *	@param		array	$arrayofcss			Array of css files to add in header
1412
 *  @param		string	$morequerystring	Query string to add to the link "print" to get same parameters (use only if autodetect fails)
1413
 *  @param      string	$helppagename    	Name of wiki page for help ('' by default).
1414
 * 				     		                Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage
1415
 * 						                    For other external page: http://server/url
1416
 *  @return		void
1417
 */
1418
function top_menu($head, $title='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $helppagename='')
1419
{
1420
	global $user, $conf, $langs, $db;
1421
	global $dolibarr_main_authentication, $dolibarr_main_demo;
1422
	global $hookmanager,$menumanager;
1423
1424
	$searchform='';
1425
	$bookmarks='';
1426
1427
	// Instantiate hooks of thirdparty module
1428
	$hookmanager->initHooks(array('toprightmenu'));
1429
1430
	$toprightmenu='';
1431
1432
	// For backward compatibility with old modules
1433
	if (empty($conf->headerdone))
1434
	{
1435
		top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
1436
		print '<body id="mainbody">';
1437
	}
1438
1439
	/*
1440
     * Top menu
1441
     */
1442
	if ((empty($conf->dol_hide_topmenu) || GETPOST('dol_invisible_topmenu','int')) && (! defined('NOREQUIREMENU') || ! constant('NOREQUIREMENU')))
1443
	{
1444
		print "\n".'<!-- Start top horizontal -->'."\n";
1445
1446
		print '<div class="side-nav-vert'.(GETPOST('dol_invisible_topmenu','int')?' hidden':'').'"><div id="id-top">';		// dol_invisible_topmenu differs from dol_hide_topmenu: dol_invisible_topmenu means we output menu but we make it invisible.
1447
1448
		// Show menu entries
1449
		print '<div id="tmenu_tooltip'.(empty($conf->global->MAIN_MENU_INVERT)?'':'invert').'" class="tmenu">'."\n";
1450
		$menumanager->atarget=$target;
1451
		$menumanager->showmenu('top', array('searchform'=>$searchform, 'bookmarks'=>$bookmarks));      // This contains a \n
1452
		print "</div>\n";
1453
1454
		// Define link to login card
1455
		$appli=constant('DOL_APPLICATION_TITLE');
1456
		if (! empty($conf->global->MAIN_APPLICATION_TITLE))
1457
		{
1458
			$appli=$conf->global->MAIN_APPLICATION_TITLE;
1459
			if (preg_match('/\d\.\d/', $appli))
1460
			{
1461
				if (! preg_match('/'.preg_quote(DOL_VERSION).'/', $appli)) $appli.=" (".DOL_VERSION.")";	// If new title contains a version that is different than core
1462
			}
1463
			else $appli.=" ".DOL_VERSION;
1464
		}
1465
		else $appli.=" ".DOL_VERSION;
1466
1467
		if (! empty($conf->global->MAIN_FEATURES_LEVEL)) $appli.="<br>".$langs->trans("LevelOfFeature").': '.$conf->global->MAIN_FEATURES_LEVEL;
1468
1469
		$logouttext='';
1470
		if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1471
		{
1472
			//$logouthtmltext=$appli.'<br>';
1473
			if ($_SESSION["dol_authmode"] != 'forceuser' && $_SESSION["dol_authmode"] != 'http')
1474
			{
1475
				$logouthtmltext.=$langs->trans("Logout").'<br>';
0 ignored issues
show
Bug introduced by
The variable $logouthtmltext does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1476
1477
				$logouttext .='<a href="'.DOL_URL_ROOT.'/user/logout.php">';
1478
				//$logouttext .= img_picto($langs->trans('Logout').":".$langs->trans('Logout'), 'logout_top.png', 'class="login"', 0, 0, 1);
1479
				$logouttext .='<span class="fa fa-sign-out atoplogin"></span>';
1480
				$logouttext .='</a>';
1481
			}
1482
			else
1483
			{
1484
				$logouthtmltext.=$langs->trans("NoLogoutProcessWithAuthMode",$_SESSION["dol_authmode"]);
1485
				$logouttext .= img_picto($langs->trans('Logout').":".$langs->trans('Logout'), 'logout_top.png', 'class="login"', 0, 0, 1);
1486
			}
1487
		}
1488
1489
		print '<div class="login_block">'."\n";
1490
1491
		// Add login user link
1492
		$toprightmenu.='<div class="login_block_user">';
1493
1494
		// Login name with photo and tooltip
1495
		$mode=-1;
1496
		$toprightmenu.='<div class="inline-block nowrap"><div class="inline-block login_block_elem login_block_elem_name" style="padding: 0px;">';
1497
		$toprightmenu.=$user->getNomUrl($mode, '', 1, 0, 11, 0, ($user->firstname ? 'firstname' : -1),'atoplogin');
1498
		$toprightmenu.='</div></div>';
1499
1500
		$toprightmenu.='</div>'."\n";
1501
1502
		$toprightmenu.='<div class="login_block_other">';
1503
1504
		// Execute hook printTopRightMenu (hooks should output string like '<div class="login"><a href="">mylink</a></div>')
1505
		$parameters=array();
1506
		$result=$hookmanager->executeHooks('printTopRightMenu',$parameters);    // Note that $action and $object may have been modified by some hooks
1507
		if (is_numeric($result))
1508
		{
1509
			if ($result == 0)
1510
				$toprightmenu.=$hookmanager->resPrint;		// add
1511
			else
1512
				$toprightmenu=$hookmanager->resPrint;						// replace
1513
		}
1514
		else
1515
		{
1516
			$toprightmenu.=$result;	// For backward compatibility
1517
		}
1518
1519
		// Link to module builder
1520
		if (! empty($conf->modulebuilder->enabled))
1521
		{
1522
			$text ='<a href="'.DOL_URL_ROOT.'/modulebuilder/index.php?mainmenu=home&leftmenu=admintools" target="_modulebuilder">';
1523
			//$text.= img_picto(":".$langs->trans("ModuleBuilder"), 'printer_top.png', 'class="printer"');
1524
			$text.='<span class="fa fa-bug atoplogin"></span>';
1525
			$text.='</a>';
1526
			$toprightmenu.=@Form::textwithtooltip('',$langs->trans("ModuleBuilder"),2,1,$text,'login_block_elem',2);
1527
		}
1528
1529
		// Link to print main content area
1530
		if (empty($conf->global->MAIN_PRINT_DISABLELINK) && empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $conf->browser->layout != 'phone')
1531
		{
1532
			$qs=dol_escape_htmltag($_SERVER["QUERY_STRING"]);
1533
1534
			if (is_array($_POST))
1535
			{
1536
				foreach($_POST as $key=>$value) {
1537
					if ($key!=='action' && $key!=='password' && !is_array($value)) $qs.='&'.$key.'='.urlencode($value);
1538
				}
1539
			}
1540
			$qs.=(($qs && $morequerystring)?'&':'').$morequerystring;
1541
			$text ='<a href="'.dol_escape_htmltag($_SERVER["PHP_SELF"]).'?'.$qs.($qs?'&':'').'optioncss=print" target="_blank">';
1542
			//$text.= img_picto(":".$langs->trans("PrintContentArea"), 'printer_top.png', 'class="printer"');
1543
			$text.='<span class="fa fa-print atoplogin"></span>';
1544
			$text.='</a>';
1545
			$toprightmenu.=@Form::textwithtooltip('',$langs->trans("PrintContentArea"),2,1,$text,'login_block_elem',2);
1546
		}
1547
1548
		// Link to Dolibarr wiki pages
1549
		if (empty($conf->global->MAIN_HELP_DISABLELINK) && empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1550
		{
1551
			$langs->load("help");
1552
1553
			$helpbaseurl='';
1554
			$helppage='';
1555
			$mode='';
1556
1557
			if (empty($helppagename)) $helppagename='EN:User_documentation|FR:Documentation_utilisateur|ES:Documentación_usuarios';
1558
1559
			// Get helpbaseurl, helppage and mode from helppagename and langs
1560
			$arrayres=getHelpParamFor($helppagename,$langs);
1561
			$helpbaseurl=$arrayres['helpbaseurl'];
1562
			$helppage=$arrayres['helppage'];
1563
			$mode=$arrayres['mode'];
1564
1565
			// Link to help pages
1566
			if ($helpbaseurl && $helppage)
1567
			{
1568
				$text='';
1569
	            if(!empty($conf->global->MAIN_SHOWDATABASENAMEINHELPPAGESLINK)) {
1570
                    $langs->load('admin');
1571
                    $appli .= '<br>' . $langs->trans("Database") . ': ' . $db->database_name;
1572
                }
1573
				$title=$appli.'<br>';
1574
				$title.=$langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage');
1575
				if ($mode == 'wiki') $title.=' - '.$langs->trans("PageWiki").' &quot;'.dol_escape_htmltag(strtr($helppage,'_',' ')).'&quot;';
1576
				$text.='<a class="help" target="_blank" rel="noopener" href="';
1577
				if ($mode == 'wiki') $text.=sprintf($helpbaseurl,urlencode(html_entity_decode($helppage)));
1578
				else $text.=sprintf($helpbaseurl,$helppage);
1579
				$text.='">';
1580
				//$text.=img_picto('', 'helpdoc_top').' ';
1581
				$text.='<span class="fa fa-question-circle atoplogin"></span>';
1582
				//$toprightmenu.=$langs->trans($mode == 'wiki' ? 'OnlineHelp': 'Help');
1583
				//if ($mode == 'wiki') $text.=' ('.dol_trunc(strtr($helppage,'_',' '),8).')';
1584
				$text.='</a>';
1585
				//$toprightmenu.='</div>'."\n";
1586
				$toprightmenu.=@Form::textwithtooltip('',$title,2,1,$text,'login_block_elem',2);
1587
			}
1588
		}
1589
1590
		// Logout link
1591
		$toprightmenu.=@Form::textwithtooltip('',$logouthtmltext,2,1,$logouttext,'login_block_elem',2);
1592
1593
		$toprightmenu.='</div>';
1594
1595
		print $toprightmenu;
1596
1597
		print "</div>\n";		// end div class="login_block"
1598
1599
		print '</div></div>';
1600
1601
		print '<div style="clear: both;"></div>';
1602
		print "<!-- End top horizontal menu -->\n\n";
1603
	}
1604
1605
	if (empty($conf->dol_hide_leftmenu) && empty($conf->dol_use_jmobile)) print '<!-- Begin div id-container --><div id="id-container" class="id-container'.($morecss?' '.$morecss:'').'">';
0 ignored issues
show
Bug introduced by
The variable $morecss does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1606
}
1607
1608
1609
/**
1610
 *  Show left menu bar
1611
 *
1612
 *  @param  array	$menu_array_before 	       	Table of menu entries to show before entries of menu handler. This param is deprectaed and must be provided to ''.
1613
 *  @param  string	$helppagename    	       	Name of wiki page for help ('' by default).
1614
 * 				     		                   	Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage
1615
 * 									         	For other external page: http://server/url
1616
 *  @param  string	$notused             		Deprecated. Used in past to add content into left menu. Hooks can be used now.
1617
 *  @param  array	$menu_array_after           Table of menu entries to show after entries of menu handler
1618
 *  @param  int		$leftmenuwithoutmainarea    Must be set to 1. 0 by default for backward compatibility with old modules.
1619
 *  @param  string	$title                      Title of web page
1620
 *  @param  string  $acceptdelayedhtml          1 if caller request to have html delayed content not returned but saved into global $delayedhtmlcontent (so caller can show it at end of page to avoid flash FOUC effect)
1621
 *  @return	void
1622
 */
1623
function left_menu($menu_array_before, $helppagename='', $notused='', $menu_array_after='', $leftmenuwithoutmainarea=0, $title='', $acceptdelayedhtml=0)
1624
{
1625
	global $user, $conf, $langs, $db, $form;
1626
	global $hookmanager, $menumanager;
1627
1628
	$searchform='';
1629
	$bookmarks='';
1630
1631
	if (! empty($menu_array_before)) dol_syslog("Deprecated parameter menu_array_before was used when calling main::left_menu function. Menu entries of module should now be defined into module descriptor and not provided when calling left_menu.", LOG_WARNING);
1632
1633
	if (empty($conf->dol_hide_leftmenu) && (! defined('NOREQUIREMENU') || ! constant('NOREQUIREMENU')))
1634
	{
1635
		// Instantiate hooks of thirdparty module
1636
		$hookmanager->initHooks(array('searchform','leftblock'));
1637
1638
		print "\n".'<!-- Begin side-nav id-left -->'."\n".'<div class="side-nav"><div id="id-left">'."\n";
1639
1640
		if ($conf->browser->layout == 'phone') $conf->global->MAIN_USE_OLD_SEARCH_FORM=1;	// Select into select2 is awfull on smartphone. TODO Is this still true with select2 v4 ?
1641
1642
		print "\n";
1643
1644
		if (! is_object($form)) $form=new Form($db);
1645
		$selected=-1;
1646
		$usedbyinclude=1;
1647
		include_once DOL_DOCUMENT_ROOT.'/core/ajax/selectsearchbox.php';	// This set $arrayresult
1648
1649
		if ($conf->use_javascript_ajax && empty($conf->global->MAIN_USE_OLD_SEARCH_FORM))
1650
		{
1651
			//$searchform.=$form->selectArrayAjax('searchselectcombo', DOL_URL_ROOT.'/core/ajax/selectsearchbox.php', $selected, '', '', 0, 1, 'vmenusearchselectcombo', 1, $langs->trans("Search"), 1);
1652
			$searchform.=$form->selectArrayFilter('searchselectcombo', $arrayresult, $selected, '', 1, 0, (empty($conf->global->MAIN_SEARCHBOX_CONTENT_LOADED_BEFORE_KEY)?1:0), 'vmenusearchselectcombo', 1, $langs->trans("Search"), 1);
0 ignored issues
show
Bug introduced by
The variable $arrayresult does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
1653
		}
1654
		else
1655
		{
1656
			foreach($arrayresult as $key => $val)
1657
			{
1658
				//$searchform.=printSearchForm($val['url'], $val['url'], $val['label'], 'maxwidth100', 'sall', $val['shortcut'], 'searchleft', img_picto('',$val['img']));
1659
				$searchform.=printSearchForm($val['url'], $val['url'], $val['label'], 'maxwidth125', 'sall', $val['shortcut'], 'searchleft', img_picto('', $val['img'], '', false, 1, 1));
1660
			}
1661
		}
1662
1663
		// Execute hook printSearchForm
1664
		$parameters=array('searchform'=>$searchform);
1665
		$reshook=$hookmanager->executeHooks('printSearchForm',$parameters);    // Note that $action and $object may have been modified by some hooks
1666
		if (empty($reshook))
1667
		{
1668
			$searchform.=$hookmanager->resPrint;
1669
		}
1670
		else $searchform=$hookmanager->resPrint;
1671
1672
		// Force special value for $searchform
1673
		if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) || empty($conf->use_javascript_ajax))
1674
		{
1675
			$urltosearch=DOL_URL_ROOT.'/core/search_page.php?showtitlebefore=1';
1676
			$searchform='<div class="blockvmenuimpair blockvmenusearchphone"><div id="divsearchforms1"><a href="'.$urltosearch.'" alt="'.dol_escape_htmltag($langs->trans("ShowSearchFields")).'">'.$langs->trans("Search").'...</a></div></div>';
1677
		}
1678
		elseif ($conf->use_javascript_ajax && ! empty($conf->global->MAIN_USE_OLD_SEARCH_FORM))
1679
		{
1680
			$searchform='<div class="blockvmenuimpair blockvmenusearchphone"><div id="divsearchforms1"><a href="#" alt="'.dol_escape_htmltag($langs->trans("ShowSearchFields")).'">'.$langs->trans("Search").'...</a></div><div id="divsearchforms2" style="display: none">'.$searchform.'</div>';
1681
			$searchform.='<script type="text/javascript">
1682
            	jQuery(document).ready(function () {
1683
            		jQuery("#divsearchforms1").click(function(){
1684
	                   jQuery("#divsearchforms2").toggle();
1685
	               });
1686
            	});
1687
                </script>' . "\n";
1688
			$searchform.='</div>';
1689
		}
1690
1691
		// Define $bookmarks
1692
		if (! empty($conf->bookmark->enabled) && $user->rights->bookmark->lire)
1693
		{
1694
			include_once DOL_DOCUMENT_ROOT.'/bookmarks/bookmarks.lib.php';
1695
			$langs->load("bookmarks");
1696
1697
			$bookmarks=printBookmarksList($db, $langs);
1698
		}
1699
1700
		// Left column
1701
		print '<!-- Begin left menu -->'."\n";
1702
1703
		print '<div class="vmenu"'.(empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)?'':' title="Left menu"').'>'."\n\n";
1704
1705
		// Show left menu with other forms
1706
		$menumanager->menu_array = $menu_array_before;
1707
		$menumanager->menu_array_after = $menu_array_after;
1708
		$menumanager->showmenu('left', array('searchform'=>$searchform, 'bookmarks'=>$bookmarks)); // output menu_array and menu found in database
1709
1710
		// Dolibarr version + help + bug report link
1711
		print "\n";
1712
		print "<!-- Begin Help Block-->\n";
1713
		print '<div id="blockvmenuhelp" class="blockvmenuhelp">'."\n";
1714
1715
		// Version
1716
		if (empty($conf->global->MAIN_HIDE_VERSION))    // Version is already on help picto and on login page.
1717
		{
1718
			$doliurl='https://www.dolibarr.org';
1719
			//local communities
1720
			if (preg_match('/fr/i',$langs->defaultlang)) $doliurl='https://www.dolibarr.fr';
1721
			if (preg_match('/es/i',$langs->defaultlang)) $doliurl='https://www.dolibarr.es';
1722
			if (preg_match('/de/i',$langs->defaultlang)) $doliurl='https://www.dolibarr.de';
1723
			if (preg_match('/it/i',$langs->defaultlang)) $doliurl='https://www.dolibarr.it';
1724
			if (preg_match('/gr/i',$langs->defaultlang)) $doliurl='https://www.dolibarr.gr';
1725
1726
			$appli=constant('DOL_APPLICATION_TITLE');
1727
			if (! empty($conf->global->MAIN_APPLICATION_TITLE))
1728
			{
1729
				$appli=$conf->global->MAIN_APPLICATION_TITLE; $doliurl='';
1730
				if (preg_match('/\d\.\d/', $appli))
1731
				{
1732
					if (! preg_match('/'.preg_quote(DOL_VERSION).'/', $appli)) $appli.=" (".DOL_VERSION.")";	// If new title contains a version that is different than core
1733
				}
1734
				else $appli.=" ".DOL_VERSION;
1735
			}
1736
			else $appli.=" ".DOL_VERSION;
1737
			print '<div id="blockvmenuhelpapp" class="blockvmenuhelp">';
1738
			if ($doliurl) print '<a class="help" target="_blank" rel="noopener" href="'.$doliurl.'">';
1739
			else print '<span class="help">';
1740
			print $appli;
1741
			if ($doliurl) print '</a>';
1742
			else print '</span>';
1743
			print '</div>'."\n";
1744
		}
1745
1746
		// Link to bugtrack
1747
		if (! empty($conf->global->MAIN_BUGTRACK_ENABLELINK))
1748
		{
1749
			require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1750
1751
			$bugbaseurl = 'https://github.com/Dolibarr/dolibarr/issues/new';
1752
			$bugbaseurl.= '?title=';
1753
			$bugbaseurl.= urlencode("Bug: ");
1754
			$bugbaseurl.= '&body=';
1755
			$bugbaseurl.= urlencode("# Bug\n");
1756
			$bugbaseurl.= urlencode("\n");
1757
			$bugbaseurl.= urlencode("## Environment\n");
1758
			$bugbaseurl.= urlencode("- **Version**: " . DOL_VERSION . "\n");
1759
			$bugbaseurl.= urlencode("- **OS**: " . php_uname('s') . "\n");
1760
			$bugbaseurl.= urlencode("- **Web server**: " . $_SERVER["SERVER_SOFTWARE"] . "\n");
1761
			$bugbaseurl.= urlencode("- **PHP**: " . php_sapi_name() . ' ' . phpversion() . "\n");
1762
			$bugbaseurl.= urlencode("- **Database**: " . $db::LABEL . ' ' . $db->getVersion() . "\n");
1763
			$bugbaseurl.= urlencode("- **URL**: " . $_SERVER["REQUEST_URI"] . "\n");
1764
			$bugbaseurl.= urlencode("\n");
1765
			$bugbaseurl.= urlencode("## Report\n");
1766
			print '<div id="blockvmenuhelpbugreport" class="blockvmenuhelp">';
1767
			print '<a class="help" target="_blank" rel="noopener" href="'.$bugbaseurl.'">'.$langs->trans("FindBug").'</a>';
1768
			print '</div>';
1769
		}
1770
1771
		print "</div>\n";
1772
		print "<!-- End Help Block-->\n";
1773
		print "\n";
1774
1775
		print "</div>\n";
1776
		print "<!-- End left menu -->\n";
1777
		print "\n";
1778
1779
		// Execute hook printLeftBlock
1780
		$parameters=array();
1781
		$reshook=$hookmanager->executeHooks('printLeftBlock',$parameters);    // Note that $action and $object may have been modified by some hooks
1782
		print $hookmanager->resPrint;
1783
1784
		print '</div></div> <!-- End side-nav id-left -->';	// End div id="side-nav" div id="id-left"
1785
	}
1786
1787
	print "\n";
1788
	print '<!-- Begin right area -->'."\n";
1789
1790
	if (empty($leftmenuwithoutmainarea)) main_area($title);
1791
}
1792
1793
1794
/**
1795
 *  Begin main area
1796
 *
1797
 *  @param	string	$title		Title
1798
 *  @return	void
1799
 */
1800
function main_area($title='')
1801
{
1802
	global $conf, $langs;
1803
1804
	if (empty($conf->dol_hide_leftmenu)) print '<div id="id-right">';
1805
1806
	print "\n";
1807
1808
	print '<!-- Begin div class="fiche" -->'."\n".'<div class="fiche">'."\n";
1809
1810
	if (! empty($conf->global->MAIN_ONLY_LOGIN_ALLOWED)) print info_admin($langs->trans("WarningYouAreInMaintenanceMode",$conf->global->MAIN_ONLY_LOGIN_ALLOWED));
1811
}
1812
1813
1814
/**
1815
 *  Return helpbaseurl, helppage and mode
1816
 *
1817
 *  @param	string		$helppagename		Page name ('EN:xxx,ES:eee,FR:fff...' or 'http://localpage')
1818
 *  @param  Translate	$langs				Language
1819
 *  @return	array		Array of help urls
1820
 */
1821
function getHelpParamFor($helppagename,$langs)
1822
{
1823
	$helpbaseurl='';
1824
	$helppage='';
1825
	$mode='';
1826
1827
	if (preg_match('/^http/i',$helppagename))
1828
	{
1829
		// If complete URL
1830
		$helpbaseurl='%s';
1831
		$helppage=$helppagename;
1832
		$mode='local';
1833
	}
1834
	else
1835
	{
1836
		// If WIKI URL
1837
		if (preg_match('/^es/i',$langs->defaultlang))
1838
		{
1839
			$helpbaseurl='http://wiki.dolibarr.org/index.php/%s';
1840
			if (preg_match('/ES:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1];
1841
		}
1842
		if (preg_match('/^fr/i',$langs->defaultlang))
1843
		{
1844
			$helpbaseurl='http://wiki.dolibarr.org/index.php/%s';
1845
			if (preg_match('/FR:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1];
1846
		}
1847
		if (empty($helppage))	// If help page not already found
1848
		{
1849
			$helpbaseurl='http://wiki.dolibarr.org/index.php/%s';
1850
			if (preg_match('/EN:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1];
1851
		}
1852
		$mode='wiki';
1853
	}
1854
	return array('helpbaseurl'=>$helpbaseurl,'helppage'=>$helppage,'mode'=>$mode);
1855
}
1856
1857
1858
/**
1859
 *  Show a search area.
1860
 *  Used when the javascript quick search is not used.
1861
 *
1862
 *  @param  string	$urlaction          Url post
1863
 *  @param  string	$urlobject          Url of the link under the search box
1864
 *  @param  string	$title              Title search area
1865
 *  @param  string	$htmlmorecss        Add more css
1866
 *  @param  string	$htmlinputname      Field Name input form
1867
 *  @param	string	$accesskey			Accesskey
1868
 *  @param  string  $prefhtmlinputname  Complement for id to avoid multiple same id in the page
1869
 *  @param	string	$img				Image to use
1870
 *  @param	string	$showtitlebefore	Show title before input text instead of into placeholder. This can be set when output is dedicated for text browsers.
1871
 *  @return	string
1872
 */
1873
function printSearchForm($urlaction, $urlobject, $title, $htmlmorecss, $htmlinputname, $accesskey='', $prefhtmlinputname='',$img='', $showtitlebefore=0)
1874
{
1875
	global $conf,$langs,$user;
1876
1877
	$ret='';
1878
	$ret.='<form action="'.$urlaction.'" method="post" class="searchform">';
1879
	$ret.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1880
	$ret.='<input type="hidden" name="mode" value="search">';
1881
	$ret.='<input type="hidden" name="savelogin" value="'.dol_escape_htmltag($user->login).'">';
1882
	if ($showtitlebefore) $ret.=$title.' ';
1883
	$ret.='<input type="text" class="flat '.$htmlmorecss.'"';
1884
	$ret.=' style="text-indent: 22px; background-image: url(\''.$img.'\'); background-repeat: no-repeat; background-position: 3px;"';
1885
	$ret.=($accesskey?' accesskey="'.$accesskey.'"':'');
1886
	$ret.=' placeholder="'.strip_tags($title).'"';
1887
	$ret.=' name="'.$htmlinputname.'" id="'.$prefhtmlinputname.$htmlinputname.'" />';
1888
	//$ret.='<input type="submit" class="button" style="padding-top: 4px; padding-bottom: 4px; padding-left: 6px; padding-right: 6px" value="'.$langs->trans("Go").'">';
1889
	$ret.='<button type="submit" class="button" style="padding-top: 4px; padding-bottom: 4px; padding-left: 6px; padding-right: 6px">';
1890
	$ret.='<span class="fa fa-search"></span>';
1891
	$ret.='</button>';
1892
	$ret.="</form>\n";
1893
	return $ret;
1894
}
1895
1896
1897
if (! function_exists("llxFooter"))
1898
{
1899
	/**
1900
	 * Show HTML footer
1901
	 * Close div /DIV class=fiche + /DIV id-right + /DIV id-container + /BODY + /HTML.
1902
	 * If global var $delayedhtmlcontent was filled, we output it just before closing the body.
1903
	 *
1904
	 * @param	string	$comment    				A text to add as HTML comment into HTML generated page
1905
	 * @param	string	$zone						'private' (for private pages) or 'public' (for public pages)
1906
	 * @param	int		$disabledoutputofmessages	Clear all messages stored into session without diplaying them
1907
	 * @return	void
1908
	 */
1909
	function llxFooter($comment='',$zone='private', $disabledoutputofmessages=0)
1910
	{
1911
		global $conf, $langs, $user, $object;
1912
		global $delayedhtmlcontent, $contextpage;
1913
1914
		$ext='layout='.$conf->browser->layout.'&version='.urlencode(DOL_VERSION);
1915
1916
		// Global html output events ($mesgs, $errors, $warnings)
1917
		dol_htmloutput_events($disabledoutputofmessages);
1918
1919
		// Code for search criteria persistence.
1920
		// $user->lastsearch_values was set by the GETPOST when form field search_xxx exists
1921
		if (is_object($user) && ! empty($user->lastsearch_values_tmp) && is_array($user->lastsearch_values_tmp))
1922
		{
1923
			// Clean and save data
1924
			foreach($user->lastsearch_values_tmp as $key => $val)
1925
			{
1926
				unset($_SESSION['lastsearch_values_tmp_'.$key]);			// Clean array to rebuild it just after
1927
				if (count($val) && empty($_POST['button_removefilter']))	// If there is search criteria to save and we did not click on 'Clear filter' button
1928
				{
1929
					if (empty($val['sortfield'])) unset($val['sortfield']);
1930
					if (empty($val['sortorder'])) unset($val['sortorder']);
1931
					dol_syslog('Save lastsearch_values_tmp_'.$key.'='.json_encode($val, 0)." (systematic recording of last search criterias)");
1932
					$_SESSION['lastsearch_values_tmp_'.$key]=json_encode($val);
1933
					unset($_SESSION['lastsearch_values_'.$key]);
1934
				}
1935
			}
1936
		}
1937
1938
1939
		$relativepathstring = $_SERVER["PHP_SELF"];
1940
		// Clean $relativepathstring
1941
		if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'),'/').'/', '', $relativepathstring);
1942
		$relativepathstring = preg_replace('/^\//', '', $relativepathstring);
1943
		$relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
1944
		if (preg_match('/list\.php$/', $relativepathstring))
1945
		{
1946
			unset($_SESSION['lastsearch_contextpage_tmp_'.$relativepathstring]);
1947
			if (! empty($contextpage)) $_SESSION['lastsearch_contextpage_tmp_'.$relativepathstring]=$contextpage;
1948
			unset($_SESSION['lastsearch_contextpage_'.$relativepathstring]);
1949
		}
1950
1951
		// Core error message
1952
		if (! empty($conf->global->MAIN_CORE_ERROR))
1953
		{
1954
			// Ajax version
1955
			if ($conf->use_javascript_ajax)
1956
			{
1957
				$title = img_warning().' '.$langs->trans('CoreErrorTitle');
1958
				print ajax_dialog($title, $langs->trans('CoreErrorMessage'));
1959
			}
1960
			// html version
1961
			else
1962
			{
1963
				$msg = img_warning().' '.$langs->trans('CoreErrorMessage');
1964
				print '<div class="error">'.$msg.'</div>';
1965
			}
1966
1967
			//define("MAIN_CORE_ERROR",0);      // Constant was defined and we can't change value of a constant
1968
		}
1969
1970
		print "\n\n";
1971
1972
		print '</div> <!-- End div class="fiche" -->'."\n"; // End div fiche
1973
1974
		if (empty($conf->dol_hide_leftmenu)) print '</div> <!-- End div id-right -->'."\n"; // End div id-right
1975
1976
		if (empty($conf->dol_hide_leftmenu) && empty($conf->dol_use_jmobile)) print '</div> <!-- End div id-container -->'."\n";	// End div container
1977
1978
		print "\n";
1979
		if ($comment) print '<!-- '.$comment.' -->'."\n";
1980
1981
		printCommonFooter($zone);
1982
1983
		if (! empty($delayedhtmlcontent)) print $delayedhtmlcontent;
1984
1985
		if (! empty($conf->use_javascript_ajax))
1986
		{
1987
			print "\n".'<!-- Includes JS Footer of Dolibarr -->'."\n";
1988
			print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/lib_foot.js.php?lang='.$langs->defaultlang.($ext?'&'.$ext:'').'"></script>'."\n";
1989
		}
1990
1991
		// Wrapper to add log when clicking on download or preview
1992
		if (! empty($conf->blockedlog->enabled) && is_object($object) && $object->id > 0 && $object->statut > 0)
1993
		{
1994
			if (in_array($object->element, array('facture')))       // Restrict for the moment to element 'facture'
1995
			{
1996
				print "\n<!-- JS CODE TO ENABLE log when making a download or a preview of a document -->\n";
1997
				?>
1998
    			<script type="text/javascript">
1999
    			jQuery(document).ready(function () {
2000
    				$('a.documentpreview').click(function() {
2001
    					$.post('<?php echo DOL_URL_ROOT."/blockedlog/ajax/block-add.php" ?>'
2002
    							, {
2003
    								id:<?php echo $object->id; ?>
2004
    								, element:'<?php echo $object->element ?>'
2005
    								, action:'DOC_PREVIEW'
2006
    							}
2007
    					);
2008
    				});
2009
    				$('a.documentdownload').click(function() {
2010
    					$.post('<?php echo DOL_URL_ROOT."/blockedlog/ajax/block-add.php" ?>'
2011
    							, {
2012
    								id:<?php echo $object->id; ?>
2013
    								, element:'<?php echo $object->element ?>'
2014
    								, action:'DOC_DOWNLOAD'
2015
    							}
2016
    					);
2017
    				});
2018
    			});
2019
    			</script>
2020
				<?php
2021
			}
2022
	   	}
2023
2024
		// A div for the address popup
2025
		print "\n<!-- A div to allow dialog popup -->\n";
2026
		print '<div id="dialogforpopup" style="display: none;"></div>'."\n";
2027
2028
		print "</body>\n";
2029
		print "</html>\n";
2030
	}
2031
}
2032