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) |
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('/:|:|:/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
|
|
|
// Call trigger for the "security events" log |
504
|
|
|
$user->trigger_mesg='ErrorBadValueForCode - login='.GETPOST("username","alpha",2); |
505
|
|
|
// Call of triggers |
506
|
|
|
include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; |
507
|
|
|
$interface=new Interfaces($db); |
508
|
|
|
$result=$interface->run_triggers('USER_LOGIN_FAILED',$user,$user,$langs,$conf); |
509
|
|
|
if ($result < 0) { |
510
|
|
|
$error++; |
511
|
|
|
} |
512
|
|
|
// End Call of triggers |
513
|
|
|
|
514
|
|
|
// Hooks on failed login |
515
|
|
|
$action=''; |
516
|
|
|
$hookmanager->initHooks(array('login')); |
517
|
|
|
$parameters=array('dol_authmode'=>$dol_authmode, 'dol_loginmesg'=>$_SESSION["dol_loginmesg"]); |
518
|
|
|
$reshook=$hookmanager->executeHooks('afterLoginFailed',$parameters,$user,$action); // Note that $action and $object may have been modified by some hooks |
519
|
|
|
if ($reshook < 0) $error++; |
520
|
|
|
|
521
|
|
|
// Note: exit is done later |
522
|
|
|
} |
523
|
|
|
} |
524
|
|
|
|
525
|
|
|
$allowedmethodtopostusername = 2; |
526
|
|
|
if (defined('MAIN_AUTHENTICATION_POST_METHOD')) $allowedmethodtopostusername = constant('MAIN_AUTHENTICATION_POST_METHOD'); |
527
|
|
|
$usertotest = (! empty($_COOKIE['login_dolibarr']) ? $_COOKIE['login_dolibarr'] : GETPOST("username","alpha",$allowedmethodtopostusername)); |
528
|
|
|
$passwordtotest = GETPOST('password','none',$allowedmethodtopostusername); |
529
|
|
|
$entitytotest = (GETPOST('entity','int') ? GETPOST('entity','int') : (!empty($conf->entity) ? $conf->entity : 1)); |
530
|
|
|
|
531
|
|
|
// Define if we received data to test the login. |
532
|
|
|
$goontestloop=false; |
533
|
|
|
if (isset($_SERVER["REMOTE_USER"]) && in_array('http',$authmode)) $goontestloop=true; |
534
|
|
|
if ($dolibarr_main_authentication == 'forceuser' && ! empty($dolibarr_auto_user)) $goontestloop=true; |
535
|
|
|
if (GETPOST("username","alpha",$allowedmethodtopostusername) || ! empty($_COOKIE['login_dolibarr']) || GETPOST('openid_mode','alpha',1)) $goontestloop=true; |
536
|
|
|
|
537
|
|
|
if (! is_object($langs)) // This can occurs when calling page with NOREQUIRETRAN defined, however we need langs for error messages. |
538
|
|
|
{ |
539
|
|
|
include_once DOL_DOCUMENT_ROOT.'/core/class/translate.class.php'; |
540
|
|
|
$langs=new Translate("",$conf); |
541
|
|
|
$langcode=(GETPOST('lang','aZ09',1)?GETPOST('lang','aZ09',1):(empty($conf->global->MAIN_LANG_DEFAULT)?'auto':$conf->global->MAIN_LANG_DEFAULT)); |
542
|
|
|
if (defined('MAIN_LANG_DEFAULT')) $langcode=constant('MAIN_LANG_DEFAULT'); |
543
|
|
|
$langs->setDefaultLang($langcode); |
544
|
|
|
} |
545
|
|
|
|
546
|
|
|
// Validation of login/pass/entity |
547
|
|
|
// If ok, the variable login will be returned |
548
|
|
|
// If error, we will put error message in session under the name dol_loginmesg |
549
|
|
|
if ($test && $goontestloop) |
550
|
|
|
{ |
551
|
|
|
$login = checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode); |
552
|
|
|
if ($login) |
553
|
|
|
{ |
554
|
|
|
$dol_authmode=$conf->authmode; // This properties is defined only when logged, to say what mode was successfully used |
555
|
|
|
$dol_tz=$_POST["tz"]; |
556
|
|
|
$dol_tz_string=$_POST["tz_string"]; |
557
|
|
|
$dol_tz_string=preg_replace('/\s*\(.+\)$/','',$dol_tz_string); |
558
|
|
|
$dol_tz_string=preg_replace('/,/','/',$dol_tz_string); |
559
|
|
|
$dol_tz_string=preg_replace('/\s/','_',$dol_tz_string); |
560
|
|
|
$dol_dst=0; |
561
|
|
|
if (isset($_POST["dst_first"]) && isset($_POST["dst_second"])) |
562
|
|
|
{ |
563
|
|
|
include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; |
564
|
|
|
$datenow=dol_now(); |
565
|
|
|
$datefirst=dol_stringtotime($_POST["dst_first"]); |
566
|
|
|
$datesecond=dol_stringtotime($_POST["dst_second"]); |
567
|
|
|
if ($datenow >= $datefirst && $datenow < $datesecond) $dol_dst=1; |
568
|
|
|
} |
569
|
|
|
//print $datefirst.'-'.$datesecond.'-'.$datenow.'-'.$dol_tz.'-'.$dol_tzstring.'-'.$dol_dst; exit; |
570
|
|
|
} |
571
|
|
|
|
572
|
|
|
if (! $login) |
573
|
|
|
{ |
574
|
|
|
dol_syslog('Bad password, connexion refused',LOG_DEBUG); |
575
|
|
|
// Load translation files required by page |
576
|
|
|
$langs->loadLangs(array('main', 'errors')); |
577
|
|
|
|
578
|
|
|
// Bad password. No authmode has found a good password. |
579
|
|
|
// We set a generic message if not defined inside function checkLoginPassEntity or subfunctions |
580
|
|
|
if (empty($_SESSION["dol_loginmesg"])) $_SESSION["dol_loginmesg"]=$langs->trans("ErrorBadLoginPassword"); |
581
|
|
|
|
582
|
|
|
// Call trigger for the "security events" log |
583
|
|
|
$user->trigger_mesg=$langs->trans("ErrorBadLoginPassword").' - login='.GETPOST("username","alpha",2); |
584
|
|
|
// Call of triggers |
585
|
|
|
include_once DOL_DOCUMENT_ROOT.'/core/class/interfaces.class.php'; |
586
|
|
|
$interface=new Interfaces($db); |
587
|
|
|
$result=$interface->run_triggers('USER_LOGIN_FAILED',$user,$user,$langs,$conf,GETPOST("username","alpha",2)); |
588
|
|
|
if ($result < 0) { |
589
|
|
|
$error++; |
590
|
|
|
} |
591
|
|
|
// End Call of triggers |
592
|
|
|
|
593
|
|
|
// Hooks on failed login |
594
|
|
|
$action=''; |
595
|
|
|
$hookmanager->initHooks(array('login')); |
596
|
|
|
$parameters=array('dol_authmode'=>$dol_authmode, 'dol_loginmesg'=>$_SESSION["dol_loginmesg"]); |
597
|
|
|
$reshook=$hookmanager->executeHooks('afterLoginFailed',$parameters,$user,$action); // Note that $action and $object may have been modified by some hooks |
598
|
|
|
if ($reshook < 0) $error++; |
599
|
|
|
|
600
|
|
|
// Note: exit is done in next chapter |
601
|
|
|
} |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
// End test login / passwords |
605
|
|
|
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. |
606
|
|
|
{ |
607
|
|
|
// No data to test login, so we show the login page |
608
|
|
|
dol_syslog("--- Access to ".$_SERVER["PHP_SELF"]." showing the login form and exit"); |
609
|
|
|
if (defined('NOREDIRECTBYMAINTOLOGIN')) return 'ERROR_NOT_LOGGED'; |
610
|
|
|
else dol_loginfunction($langs,$conf,(! empty($mysoc)?$mysoc:'')); |
611
|
|
|
exit; |
612
|
|
|
} |
613
|
|
|
|
614
|
|
|
$resultFetchUser=$user->fetch('', $login, '', 1, ($entitytotest > 0 ? $entitytotest : -1)); |
615
|
|
|
if ($resultFetchUser <= 0) |
616
|
|
|
{ |
617
|
|
|
dol_syslog('User not found, connexion refused'); |
618
|
|
|
session_destroy(); |
619
|
|
|
session_name($sessionname); |
620
|
|
|
session_set_cookie_params(0, '/', null, false, true); // Add tag httponly on session cookie |
621
|
|
|
session_start(); // Fixing the bug of register_globals here is useless since session is empty |
622
|
|
|
|
623
|
|
|
if ($resultFetchUser == 0) |
624
|
|
|
{ |
625
|
|
|
// Load translation files required by page |
626
|
|
|
$langs->loadLangs(array('main', 'errors')); |
627
|
|
|
|
628
|
|
|
$_SESSION["dol_loginmesg"]=$langs->trans("ErrorCantLoadUserFromDolibarrDatabase",$login); |
629
|
|
|
|
630
|
|
|
$user->trigger_mesg='ErrorCantLoadUserFromDolibarrDatabase - login='.$login; |
631
|
|
|
} |
632
|
|
|
if ($resultFetchUser < 0) |
633
|
|
|
{ |
634
|
|
|
$_SESSION["dol_loginmesg"]=$user->error; |
635
|
|
|
|
636
|
|
|
$user->trigger_mesg=$user->error; |
637
|
|
|
} |
638
|
|
|
|
639
|
|
|
// Call triggers for the "security events" log |
640
|
|
|
include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; |
641
|
|
|
$interface=new Interfaces($db); |
642
|
|
|
$result=$interface->run_triggers('USER_LOGIN_FAILED',$user,$user,$langs,$conf); |
643
|
|
|
if ($result < 0) { |
644
|
|
|
$error++; |
645
|
|
|
} |
646
|
|
|
// End call triggers |
647
|
|
|
|
648
|
|
|
// Hooks on failed login |
649
|
|
|
$action=''; |
650
|
|
|
$hookmanager->initHooks(array('login')); |
651
|
|
|
$parameters=array('dol_authmode'=>$dol_authmode, 'dol_loginmesg'=>$_SESSION["dol_loginmesg"]); |
652
|
|
|
$reshook=$hookmanager->executeHooks('afterLoginFailed',$parameters,$user,$action); // Note that $action and $object may have been modified by some hooks |
653
|
|
|
if ($reshook < 0) $error++; |
654
|
|
|
|
655
|
|
|
$paramsurl=array(); |
656
|
|
|
if (GETPOST('textbrowser','int')) $paramsurl[]='textbrowser='.GETPOST('textbrowser','int'); |
657
|
|
|
if (GETPOST('nojs','int')) $paramsurl[]='nojs='.GETPOST('nojs','int'); |
658
|
|
|
if (GETPOST('lang','aZ09')) $paramsurl[]='lang='.GETPOST('lang','aZ09'); |
659
|
|
|
header('Location: '.DOL_URL_ROOT.'/index.php'.(count($paramsurl)?'?'.implode('&',$paramsurl):'')); |
660
|
|
|
exit; |
661
|
|
|
} |
662
|
|
|
} |
663
|
|
|
else |
664
|
|
|
{ |
665
|
|
|
// We are already into an authenticated session |
666
|
|
|
$login=$_SESSION["dol_login"]; |
667
|
|
|
$entity=$_SESSION["dol_entity"]; |
668
|
|
|
dol_syslog("- This is an already logged session. _SESSION['dol_login']=".$login." _SESSION['dol_entity']=".$entity, LOG_DEBUG); |
669
|
|
|
|
670
|
|
|
$resultFetchUser=$user->fetch('', $login, '', 1, ($entity > 0 ? $entity : -1)); |
671
|
|
|
if ($resultFetchUser <= 0) |
672
|
|
|
{ |
673
|
|
|
// Account has been removed after login |
674
|
|
|
dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=".$login, LOG_WARNING); |
675
|
|
|
session_destroy(); |
676
|
|
|
session_name($sessionname); |
677
|
|
|
session_set_cookie_params(0, '/', null, false, true); // Add tag httponly on session cookie |
678
|
|
|
session_start(); // Fixing the bug of register_globals here is useless since session is empty |
679
|
|
|
|
680
|
|
|
if ($resultFetchUser == 0) |
681
|
|
|
{ |
682
|
|
|
// Load translation files required by page |
683
|
|
|
$langs->loadLangs(array('main', 'errors')); |
684
|
|
|
|
685
|
|
|
$_SESSION["dol_loginmesg"]=$langs->trans("ErrorCantLoadUserFromDolibarrDatabase",$login); |
686
|
|
|
|
687
|
|
|
$user->trigger_mesg='ErrorCantLoadUserFromDolibarrDatabase - login='.$login; |
688
|
|
|
} |
689
|
|
|
if ($resultFetchUser < 0) |
690
|
|
|
{ |
691
|
|
|
$_SESSION["dol_loginmesg"]=$user->error; |
692
|
|
|
|
693
|
|
|
$user->trigger_mesg=$user->error; |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
// Call triggers for the "security events" log |
697
|
|
|
include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; |
698
|
|
|
$interface=new Interfaces($db); |
699
|
|
|
$result=$interface->run_triggers('USER_LOGIN_FAILED',$user,$user,$langs,$conf); |
700
|
|
|
if ($result < 0) { |
701
|
|
|
$error++; |
702
|
|
|
} |
703
|
|
|
// End call triggers |
704
|
|
|
|
705
|
|
|
// Hooks on failed login |
706
|
|
|
$action=''; |
707
|
|
|
$hookmanager->initHooks(array('login')); |
708
|
|
|
$parameters=array('dol_authmode'=>$dol_authmode, 'dol_loginmesg'=>$_SESSION["dol_loginmesg"]); |
709
|
|
|
$reshook=$hookmanager->executeHooks('afterLoginFailed',$parameters,$user,$action); // Note that $action and $object may have been modified by some hooks |
710
|
|
|
if ($reshook < 0) $error++; |
711
|
|
|
|
712
|
|
|
$paramsurl=array(); |
713
|
|
|
if (GETPOST('textbrowser','int')) $paramsurl[]='textbrowser='.GETPOST('textbrowser','int'); |
714
|
|
|
if (GETPOST('nojs','int')) $paramsurl[]='nojs='.GETPOST('nojs','int'); |
715
|
|
|
if (GETPOST('lang','aZ09')) $paramsurl[]='lang='.GETPOST('lang','aZ09'); |
716
|
|
|
header('Location: '.DOL_URL_ROOT.'/index.php'.(count($paramsurl)?'?'.implode('&',$paramsurl):'')); |
717
|
|
|
exit; |
718
|
|
|
} |
719
|
|
|
else |
720
|
|
|
{ |
721
|
|
|
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context |
722
|
|
|
$hookmanager->initHooks(array('main')); |
723
|
|
|
|
724
|
|
|
// Code for search criteria persistence. |
725
|
|
|
if (! empty($_GET['save_lastsearch_values'])) // We must use $_GET here |
726
|
|
|
{ |
727
|
|
|
$relativepathstring = preg_replace('/\?.*$/','',$_SERVER["HTTP_REFERER"]); |
728
|
|
|
$relativepathstring = preg_replace('/^https?:\/\/[^\/]*/','',$relativepathstring); // Get full path except host server |
729
|
|
|
// Clean $relativepathstring |
730
|
|
|
if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'),'/').'/', '', $relativepathstring); |
731
|
|
|
$relativepathstring = preg_replace('/^\//', '', $relativepathstring); |
732
|
|
|
$relativepathstring = preg_replace('/^custom\//', '', $relativepathstring); |
733
|
|
|
//var_dump($relativepathstring); |
734
|
|
|
|
735
|
|
|
// We click on a link that leave a page we have to save search criteria, contextpage, limit and page. We save them from tmp to no tmp |
736
|
|
|
if (! empty($_SESSION['lastsearch_values_tmp_'.$relativepathstring])) |
737
|
|
|
{ |
738
|
|
|
$_SESSION['lastsearch_values_'.$relativepathstring]=$_SESSION['lastsearch_values_tmp_'.$relativepathstring]; |
739
|
|
|
unset($_SESSION['lastsearch_values_tmp_'.$relativepathstring]); |
740
|
|
|
} |
741
|
|
|
if (! empty($_SESSION['lastsearch_contextpage_tmp_'.$relativepathstring])) |
742
|
|
|
{ |
743
|
|
|
$_SESSION['lastsearch_contextpage_'.$relativepathstring]=$_SESSION['lastsearch_contextpage_tmp_'.$relativepathstring]; |
744
|
|
|
unset($_SESSION['lastsearch_contextpage_tmp_'.$relativepathstring]); |
745
|
|
|
} |
746
|
|
|
if (! empty($_SESSION['lastsearch_page_tmp_'.$relativepathstring]) && $_SESSION['lastsearch_page_tmp_'.$relativepathstring] > 1) |
747
|
|
|
{ |
748
|
|
|
$_SESSION['lastsearch_page_'.$relativepathstring]=$_SESSION['lastsearch_page_tmp_'.$relativepathstring]; |
749
|
|
|
unset($_SESSION['lastsearch_page_tmp_'.$relativepathstring]); |
750
|
|
|
} |
751
|
|
|
if (! empty($_SESSION['lastsearch_limit_tmp_'.$relativepathstring]) && $_SESSION['lastsearch_limit_tmp_'.$relativepathstring] != $conf->liste_limit) |
752
|
|
|
{ |
753
|
|
|
$_SESSION['lastsearch_limit_'.$relativepathstring]=$_SESSION['lastsearch_limit_tmp_'.$relativepathstring]; |
754
|
|
|
unset($_SESSION['lastsearch_limit_tmp_'.$relativepathstring]); |
755
|
|
|
} |
756
|
|
|
} |
757
|
|
|
|
758
|
|
|
$action = ''; |
759
|
|
|
$reshook = $hookmanager->executeHooks('updateSession', array(), $user, $action); |
760
|
|
|
if ($reshook < 0) { |
761
|
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); |
762
|
|
|
} |
763
|
|
|
} |
764
|
|
|
} |
765
|
|
|
|
766
|
|
|
// Is it a new session that has started ? |
767
|
|
|
// If we are here, this means authentication was successfull. |
768
|
|
|
if (! isset($_SESSION["dol_login"])) |
769
|
|
|
{ |
770
|
|
|
// New session for this login has started. |
771
|
|
|
$error=0; |
772
|
|
|
|
773
|
|
|
// Store value into session (values always stored) |
774
|
|
|
$_SESSION["dol_login"]=$user->login; |
775
|
|
|
$_SESSION["dol_authmode"]=isset($dol_authmode)?$dol_authmode:''; |
776
|
|
|
$_SESSION["dol_tz"]=isset($dol_tz)?$dol_tz:''; |
777
|
|
|
$_SESSION["dol_tz_string"]=isset($dol_tz_string)?$dol_tz_string:''; |
778
|
|
|
$_SESSION["dol_dst"]=isset($dol_dst)?$dol_dst:''; |
779
|
|
|
$_SESSION["dol_dst_observed"]=isset($dol_dst_observed)?$dol_dst_observed:''; |
780
|
|
|
$_SESSION["dol_dst_first"]=isset($dol_dst_first)?$dol_dst_first:''; |
781
|
|
|
$_SESSION["dol_dst_second"]=isset($dol_dst_second)?$dol_dst_second:''; |
782
|
|
|
$_SESSION["dol_screenwidth"]=isset($dol_screenwidth)?$dol_screenwidth:''; |
783
|
|
|
$_SESSION["dol_screenheight"]=isset($dol_screenheight)?$dol_screenheight:''; |
784
|
|
|
$_SESSION["dol_company"]=$conf->global->MAIN_INFO_SOCIETE_NOM; |
785
|
|
|
$_SESSION["dol_entity"]=$conf->entity; |
786
|
|
|
// Store value into session (values stored only if defined) |
787
|
|
|
if (! empty($dol_hide_topmenu)) $_SESSION['dol_hide_topmenu']=$dol_hide_topmenu; |
788
|
|
|
if (! empty($dol_hide_leftmenu)) $_SESSION['dol_hide_leftmenu']=$dol_hide_leftmenu; |
789
|
|
|
if (! empty($dol_optimize_smallscreen)) $_SESSION['dol_optimize_smallscreen']=$dol_optimize_smallscreen; |
790
|
|
|
if (! empty($dol_no_mouse_hover)) $_SESSION['dol_no_mouse_hover']=$dol_no_mouse_hover; |
791
|
|
|
if (! empty($dol_use_jmobile)) $_SESSION['dol_use_jmobile']=$dol_use_jmobile; |
792
|
|
|
|
793
|
|
|
dol_syslog("This is a new started user session. _SESSION['dol_login']=".$_SESSION["dol_login"]." Session id=".session_id()); |
794
|
|
|
|
795
|
|
|
$db->begin(); |
796
|
|
|
|
797
|
|
|
$user->update_last_login_date(); |
798
|
|
|
|
799
|
|
|
$loginfo = 'TZ='.$_SESSION["dol_tz"].';TZString='.$_SESSION["dol_tz_string"].';Screen='.$_SESSION["dol_screenwidth"].'x'.$_SESSION["dol_screenheight"]; |
800
|
|
|
|
801
|
|
|
// Call triggers for the "security events" log |
802
|
|
|
$user->trigger_mesg = $loginfo; |
803
|
|
|
// Call triggers |
804
|
|
|
include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; |
805
|
|
|
$interface=new Interfaces($db); |
806
|
|
|
$result=$interface->run_triggers('USER_LOGIN',$user,$user,$langs,$conf); |
807
|
|
|
if ($result < 0) { |
808
|
|
|
$error++; |
809
|
|
|
} |
810
|
|
|
// End call triggers |
811
|
|
|
|
812
|
|
|
// Hooks on successfull login |
813
|
|
|
$action=''; |
814
|
|
|
$hookmanager->initHooks(array('login')); |
815
|
|
|
$parameters=array('dol_authmode'=>$dol_authmode, 'dol_loginfo'=>$loginfo); |
816
|
|
|
$reshook=$hookmanager->executeHooks('afterLogin',$parameters,$user,$action); // Note that $action and $object may have been modified by some hooks |
817
|
|
|
if ($reshook < 0) $error++; |
818
|
|
|
|
819
|
|
|
if ($error) |
820
|
|
|
{ |
821
|
|
|
$db->rollback(); |
822
|
|
|
session_destroy(); |
823
|
|
|
dol_print_error($db,'Error in some triggers USER_LOGIN or in some hooks afterLogin'); |
824
|
|
|
exit; |
825
|
|
|
} |
826
|
|
|
else |
827
|
|
|
{ |
828
|
|
|
$db->commit(); |
829
|
|
|
} |
830
|
|
|
|
831
|
|
|
// Change landing page if defined. |
832
|
|
|
$landingpage=(empty($user->conf->MAIN_LANDING_PAGE)?(empty($conf->global->MAIN_LANDING_PAGE)?'':$conf->global->MAIN_LANDING_PAGE):$user->conf->MAIN_LANDING_PAGE); |
833
|
|
|
if (! empty($landingpage)) // Example: /index.php |
834
|
|
|
{ |
835
|
|
|
$newpath=dol_buildpath($landingpage, 1); |
836
|
|
|
if ($_SERVER["PHP_SELF"] != $newpath) // not already on landing page (avoid infinite loop) |
837
|
|
|
{ |
838
|
|
|
header('Location: '.$newpath); |
839
|
|
|
exit; |
840
|
|
|
} |
841
|
|
|
} |
842
|
|
|
} |
843
|
|
|
|
844
|
|
|
|
845
|
|
|
// If user admin, we force the rights-based modules |
846
|
|
|
if ($user->admin) |
847
|
|
|
{ |
848
|
|
|
$user->rights->user->user->lire=1; |
849
|
|
|
$user->rights->user->user->creer=1; |
850
|
|
|
$user->rights->user->user->password=1; |
851
|
|
|
$user->rights->user->user->supprimer=1; |
852
|
|
|
$user->rights->user->self->creer=1; |
853
|
|
|
$user->rights->user->self->password=1; |
854
|
|
|
} |
855
|
|
|
|
856
|
|
|
/* |
857
|
|
|
* Overwrite some configs globals (try to avoid this and have code to use instead $user->conf->xxx) |
858
|
|
|
*/ |
859
|
|
|
|
860
|
|
|
// Set liste_limit |
861
|
|
|
if (isset($user->conf->MAIN_SIZE_LISTE_LIMIT)) $conf->liste_limit = $user->conf->MAIN_SIZE_LISTE_LIMIT; // Can be 0 |
862
|
|
|
if (isset($user->conf->PRODUIT_LIMIT_SIZE)) $conf->product->limit_size = $user->conf->PRODUIT_LIMIT_SIZE; // Can be 0 |
863
|
|
|
|
864
|
|
|
// Replace conf->css by personalized value if theme not forced |
865
|
|
|
if (empty($conf->global->MAIN_FORCETHEME) && ! empty($user->conf->MAIN_THEME)) |
866
|
|
|
{ |
867
|
|
|
$conf->theme=$user->conf->MAIN_THEME; |
868
|
|
|
$conf->css = "/theme/".$conf->theme."/style.css.php"; |
869
|
|
|
} |
870
|
|
|
} |
871
|
|
|
|
872
|
|
|
// Case forcing style from url |
873
|
|
|
if (GETPOST('theme','alpha')) |
874
|
|
|
{ |
875
|
|
|
$conf->theme=GETPOST('theme','alpha',1); |
876
|
|
|
$conf->css = "/theme/".$conf->theme."/style.css.php"; |
877
|
|
|
} |
878
|
|
|
|
879
|
|
|
|
880
|
|
|
// Set javascript option |
881
|
|
|
if (! GETPOST('nojs','int')) // If javascript was not disabled on URL |
882
|
|
|
{ |
883
|
|
|
if (! empty($user->conf->MAIN_DISABLE_JAVASCRIPT)) |
884
|
|
|
{ |
885
|
|
|
$conf->use_javascript_ajax=! $user->conf->MAIN_DISABLE_JAVASCRIPT; |
886
|
|
|
} |
887
|
|
|
} |
888
|
|
|
else $conf->use_javascript_ajax=0; |
889
|
|
|
// Set MAIN_OPTIMIZEFORTEXTBROWSER |
890
|
|
|
if (GETPOST('textbrowser','int') || (! empty($conf->browser->name) && $conf->browser->name == 'lynxlinks') || ! empty($user->conf->MAIN_OPTIMIZEFORTEXTBROWSER)) // If we must enable text browser |
891
|
|
|
{ |
892
|
|
|
$conf->global->MAIN_OPTIMIZEFORTEXTBROWSER=1; |
893
|
|
|
} |
894
|
|
|
elseif (! empty($user->conf->MAIN_OPTIMIZEFORTEXTBROWSER)) |
895
|
|
|
{ |
896
|
|
|
$conf->global->MAIN_OPTIMIZEFORTEXTBROWSER=$user->conf->MAIN_OPTIMIZEFORTEXTBROWSER; |
897
|
|
|
} |
898
|
|
|
|
899
|
|
|
// Set terminal output option according to conf->browser. |
900
|
|
|
if (GETPOST('dol_hide_leftmenu','int') || ! empty($_SESSION['dol_hide_leftmenu'])) $conf->dol_hide_leftmenu=1; |
901
|
|
|
if (GETPOST('dol_hide_topmenu','int') || ! empty($_SESSION['dol_hide_topmenu'])) $conf->dol_hide_topmenu=1; |
902
|
|
|
if (GETPOST('dol_optimize_smallscreen','int') || ! empty($_SESSION['dol_optimize_smallscreen'])) $conf->dol_optimize_smallscreen=1; |
903
|
|
|
if (GETPOST('dol_no_mouse_hover','int') || ! empty($_SESSION['dol_no_mouse_hover'])) $conf->dol_no_mouse_hover=1; |
904
|
|
|
if (GETPOST('dol_use_jmobile','int') || ! empty($_SESSION['dol_use_jmobile'])) $conf->dol_use_jmobile=1; |
905
|
|
|
if (! empty($conf->browser->layout) && $conf->browser->layout != 'classic') $conf->dol_no_mouse_hover=1; |
906
|
|
|
if ((! empty($conf->browser->layout) && $conf->browser->layout == 'phone') |
907
|
|
|
|| (! empty($_SESSION['dol_screenwidth']) && $_SESSION['dol_screenwidth'] < 400) |
908
|
|
|
|| (! empty($_SESSION['dol_screenheight']) && $_SESSION['dol_screenheight'] < 400) |
909
|
|
|
) |
910
|
|
|
{ |
911
|
|
|
$conf->dol_optimize_smallscreen=1; |
912
|
|
|
} |
913
|
|
|
// If we force to use jmobile, then we reenable javascript |
914
|
|
|
if (! empty($conf->dol_use_jmobile)) $conf->use_javascript_ajax=1; |
915
|
|
|
// Replace themes bugged with jmobile with eldy |
916
|
|
|
if (! empty($conf->dol_use_jmobile) && in_array($conf->theme,array('bureau2crea','cameleo','amarok'))) |
917
|
|
|
{ |
918
|
|
|
$conf->theme='eldy'; |
919
|
|
|
$conf->css = "/theme/".$conf->theme."/style.css.php"; |
920
|
|
|
} |
921
|
|
|
|
922
|
|
|
if (! defined('NOREQUIRETRAN')) |
923
|
|
|
{ |
924
|
|
|
if (! GETPOST('lang','aZ09')) // If language was not forced on URL |
925
|
|
|
{ |
926
|
|
|
// If user has chosen its own language |
927
|
|
|
if (! empty($user->conf->MAIN_LANG_DEFAULT)) |
928
|
|
|
{ |
929
|
|
|
// If different than current language |
930
|
|
|
//print ">>>".$langs->getDefaultLang()."-".$user->conf->MAIN_LANG_DEFAULT; |
931
|
|
|
if ($langs->getDefaultLang() != $user->conf->MAIN_LANG_DEFAULT) |
932
|
|
|
{ |
933
|
|
|
$langs->setDefaultLang($user->conf->MAIN_LANG_DEFAULT); |
934
|
|
|
} |
935
|
|
|
} |
936
|
|
|
} |
937
|
|
|
} |
938
|
|
|
|
939
|
|
|
if (! defined('NOLOGIN')) |
940
|
|
|
{ |
941
|
|
|
// If the login is not recovered, it is identified with an account that does not exist. |
942
|
|
|
// Hacking attempt? |
943
|
|
|
if (! $user->login) accessforbidden(); |
944
|
|
|
|
945
|
|
|
// Check if user is active |
946
|
|
|
if ($user->statut < 1) |
947
|
|
|
{ |
948
|
|
|
// If not active, we refuse the user |
949
|
|
|
$langs->load("other"); |
950
|
|
|
dol_syslog("Authentification ko as login is disabled"); |
951
|
|
|
accessforbidden($langs->trans("ErrorLoginDisabled")); |
952
|
|
|
exit; |
953
|
|
|
} |
954
|
|
|
|
955
|
|
|
// Load permissions |
956
|
|
|
$user->getrights(); |
957
|
|
|
} |
958
|
|
|
|
959
|
|
|
|
960
|
|
|
dol_syslog("--- Access to ".$_SERVER["PHP_SELF"].' - action='.GETPOST('action','az09').', massaction='.GETPOST('massaction','az09')); |
961
|
|
|
//Another call for easy debugg |
962
|
|
|
//dol_syslog("Access to ".$_SERVER["PHP_SELF"].' GET='.join(',',array_keys($_GET)).'->'.join(',',$_GET).' POST:'.join(',',array_keys($_POST)).'->'.join(',',$_POST)); |
963
|
|
|
|
964
|
|
|
// Load main languages files |
965
|
|
|
if (! defined('NOREQUIRETRAN')) |
966
|
|
|
{ |
967
|
|
|
// Load translation files required by page |
968
|
|
|
$langs->loadLangs(array('main', 'dict')); |
969
|
|
|
} |
970
|
|
|
|
971
|
|
|
// Define some constants used for style of arrays |
972
|
|
|
$bc=array(0=>'class="impair"',1=>'class="pair"'); |
973
|
|
|
$bcdd=array(0=>'class="drag drop oddeven"',1=>'class="drag drop oddeven"'); |
974
|
|
|
$bcnd=array(0=>'class="nodrag nodrop nohover"',1=>'class="nodrag nodrop nohoverpair"'); // Used for tr to add new lines |
975
|
|
|
$bctag=array(0=>'class="impair tagtr"',1=>'class="pair tagtr"'); |
976
|
|
|
|
977
|
|
|
// Define messages variables |
978
|
|
|
$mesg=''; $warning=''; $error=0; |
979
|
|
|
// deprecated, see setEventMessages() and dol_htmloutput_events() |
980
|
|
|
$mesgs=array(); $warnings=array(); $errors=array(); |
981
|
|
|
|
982
|
|
|
// Constants used to defined number of lines in textarea |
983
|
|
|
if (empty($conf->browser->firefox)) |
984
|
|
|
{ |
985
|
|
|
define('ROWS_1',1); |
986
|
|
|
define('ROWS_2',2); |
987
|
|
|
define('ROWS_3',3); |
988
|
|
|
define('ROWS_4',4); |
989
|
|
|
define('ROWS_5',5); |
990
|
|
|
define('ROWS_6',6); |
991
|
|
|
define('ROWS_7',7); |
992
|
|
|
define('ROWS_8',8); |
993
|
|
|
define('ROWS_9',9); |
994
|
|
|
} |
995
|
|
|
else |
996
|
|
|
{ |
997
|
|
|
define('ROWS_1',0); |
998
|
|
|
define('ROWS_2',1); |
999
|
|
|
define('ROWS_3',2); |
1000
|
|
|
define('ROWS_4',3); |
1001
|
|
|
define('ROWS_5',4); |
1002
|
|
|
define('ROWS_6',5); |
1003
|
|
|
define('ROWS_7',6); |
1004
|
|
|
define('ROWS_8',7); |
1005
|
|
|
define('ROWS_9',8); |
1006
|
|
|
} |
1007
|
|
|
|
1008
|
|
|
$heightforframes=50; |
1009
|
|
|
|
1010
|
|
|
// Init menu manager |
1011
|
|
|
if (! defined('NOREQUIREMENU')) |
1012
|
|
|
{ |
1013
|
|
|
if (empty($user->societe_id)) // If internal user or not defined |
1014
|
|
|
{ |
1015
|
|
|
$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); |
1016
|
|
|
} |
1017
|
|
|
else // If external user |
1018
|
|
|
{ |
1019
|
|
|
$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); |
1020
|
|
|
} |
1021
|
|
|
|
1022
|
|
|
// Load the menu manager (only if not already done) |
1023
|
|
|
$file_menu=$conf->standard_menu; |
1024
|
|
|
if (GETPOST('menu','alpha')) $file_menu=GETPOST('menu','alpha'); // example: menu=eldy_menu.php |
1025
|
|
|
if (! class_exists('MenuManager')) |
1026
|
|
|
{ |
1027
|
|
|
$menufound=0; |
1028
|
|
|
$dirmenus=array_merge(array("/core/menus/"),(array) $conf->modules_parts['menus']); |
1029
|
|
|
foreach($dirmenus as $dirmenu) |
1030
|
|
|
{ |
1031
|
|
|
$menufound=dol_include_once($dirmenu."standard/".$file_menu); |
1032
|
|
|
if (class_exists('MenuManager')) break; |
1033
|
|
|
} |
1034
|
|
|
if (! class_exists('MenuManager')) // If failed to include, we try with standard eldy_menu.php |
1035
|
|
|
{ |
1036
|
|
|
dol_syslog("You define a menu manager '".$file_menu."' that can not be loaded.", LOG_WARNING); |
1037
|
|
|
$file_menu='eldy_menu.php'; |
1038
|
|
|
include_once DOL_DOCUMENT_ROOT."/core/menus/standard/".$file_menu; |
1039
|
|
|
} |
1040
|
|
|
} |
1041
|
|
|
$menumanager = new MenuManager($db, empty($user->societe_id)?0:1); |
1042
|
|
|
$menumanager->loadMenu(); |
1043
|
|
|
} |
1044
|
|
|
|
1045
|
|
|
|
1046
|
|
|
|
1047
|
|
|
// Functions |
1048
|
|
|
|
1049
|
|
|
if (! function_exists("llxHeader")) |
1050
|
|
|
{ |
1051
|
|
|
/** |
1052
|
|
|
* Show HTML header HTML + BODY + Top menu + left menu + DIV |
1053
|
|
|
* |
1054
|
|
|
* @param string $head Optionnal head lines |
1055
|
|
|
* @param string $title HTML title |
1056
|
|
|
* @param string $help_url Url links to help page |
1057
|
|
|
* Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage |
1058
|
|
|
* For other external page: http://server/url |
1059
|
|
|
* @param string $target Target to use on links |
1060
|
|
|
* @param int $disablejs More content into html header |
1061
|
|
|
* @param int $disablehead More content into html header |
1062
|
|
|
* @param array $arrayofjs Array of complementary js files |
1063
|
|
|
* @param array $arrayofcss Array of complementary css files |
1064
|
|
|
* @param string $morequerystring Query string to add to the link "print" to get same parameters (use only if autodetect fails) |
1065
|
|
|
* @param string $morecssonbody More CSS on body tag. |
1066
|
|
|
* @param string $replacemainareaby Replace call to main_area() by a print of this string |
1067
|
|
|
* @return void |
1068
|
|
|
*/ |
1069
|
|
|
function llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='') |
1070
|
|
|
{ |
1071
|
|
|
global $conf; |
1072
|
|
|
|
1073
|
|
|
// html header |
1074
|
|
|
top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss); |
1075
|
|
|
|
1076
|
|
|
print '<body id="mainbody"'.($morecssonbody?' class="'.$morecssonbody.'"':'').'>' . "\n"; |
1077
|
|
|
|
1078
|
|
|
// top menu and left menu area |
1079
|
|
|
if (empty($conf->dol_hide_topmenu) || GETPOST('dol_invisible_topmenu','int')) |
1080
|
|
|
{ |
1081
|
|
|
top_menu($head, $title, $target, $disablejs, $disablehead, $arrayofjs, $arrayofcss, $morequerystring, $help_url); |
1082
|
|
|
} |
1083
|
|
|
|
1084
|
|
|
if (empty($conf->dol_hide_leftmenu)) |
1085
|
|
|
{ |
1086
|
|
|
left_menu('', $help_url, '', '', 1, $title, 1); // $menumanager is retreived with a global $menumanager inside this function |
1087
|
|
|
} |
1088
|
|
|
|
1089
|
|
|
// main area |
1090
|
|
|
if ($replacemainareaby) |
1091
|
|
|
{ |
1092
|
|
|
print $replacemainareaby; |
1093
|
|
|
return; |
1094
|
|
|
} |
1095
|
|
|
main_area($title); |
1096
|
|
|
} |
1097
|
|
|
} |
1098
|
|
|
|
1099
|
|
|
|
1100
|
|
|
/** |
1101
|
|
|
* Show HTTP header |
1102
|
|
|
* |
1103
|
|
|
* @param string $contenttype Content type. For example, 'text/html' |
1104
|
|
|
* @param int $forcenocache Force disabling of cache for the page |
1105
|
|
|
* @return void |
1106
|
|
|
*/ |
1107
|
|
|
function top_httphead($contenttype='text/html', $forcenocache=0) |
1108
|
|
|
{ |
1109
|
|
|
global $db, $conf, $hookmanager; |
1110
|
|
|
|
1111
|
|
|
if ($contenttype == 'text/html' ) header("Content-Type: text/html; charset=".$conf->file->character_set_client); |
1112
|
|
|
else header("Content-Type: ".$contenttype); |
1113
|
|
|
// Security options |
1114
|
|
|
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) |
1115
|
|
|
header("X-Frame-Options: SAMEORIGIN"); // Frames allowed only if on same domain (stop some XSS attacks) |
1116
|
|
|
//header("X-XSS-Protection: 1"); // XSS protection of some browsers (note: use of Content-Security-Policy is more efficient). Disabled as deprecated. |
1117
|
|
|
if (! defined('FORCECSP')) |
1118
|
|
|
{ |
1119
|
|
|
//if (! isset($conf->global->MAIN_HTTP_CONTENT_SECURITY_POLICY)) |
1120
|
|
|
//{ |
1121
|
|
|
// // A default security policy that keep usage of js external component like ckeditor, stripe, google, working |
1122
|
|
|
// $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';"; |
1123
|
|
|
//} |
1124
|
|
|
//else $contentsecuritypolicy = $conf->global->MAIN_HTTP_CONTENT_SECURITY_POLICY; |
1125
|
|
|
$contentsecuritypolicy = $conf->global->MAIN_HTTP_CONTENT_SECURITY_POLICY; |
1126
|
|
|
|
1127
|
|
|
if (! is_object($hookmanager)) $hookmanager = new HookManager($db); |
1128
|
|
|
$hookmanager->initHooks("main"); |
1129
|
|
|
|
1130
|
|
|
$parameters=array('contentsecuritypolicy'=>$contentsecuritypolicy); |
1131
|
|
|
$result=$hookmanager->executeHooks('setContentSecurityPolicy',$parameters); // Note that $action and $object may have been modified by some hooks |
1132
|
|
|
if ($result > 0) $contentsecuritypolicy = $hookmanager->resPrint; // Replace CSP |
1133
|
|
|
else $contentsecuritypolicy .= $hookmanager->resPrint; // Concat CSP |
1134
|
|
|
|
1135
|
|
|
if (! empty($contentsecuritypolicy)) |
1136
|
|
|
{ |
1137
|
|
|
// For example, to restrict 'script', 'object', 'frames' or 'img' to some domains: |
1138
|
|
|
// 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 |
1139
|
|
|
// For example, to restrict everything to one domain, except 'object', ...: |
1140
|
|
|
// default-src https://cdn.example.net; object-src 'none' |
1141
|
|
|
// For example, to restrict everything to itself except img that can be on other servers: |
1142
|
|
|
// default-src 'self'; img-src *; |
1143
|
|
|
// Pre-existing site that uses too much inline code to fix but wants to ensure resources are loaded only over https and disable plugins: |
1144
|
|
|
// default-src http: https: 'unsafe-eval' 'unsafe-inline'; object-src 'none' |
1145
|
|
|
header("Content-Security-Policy: ".$contentsecuritypolicy); |
1146
|
|
|
} |
1147
|
|
|
} |
1148
|
|
|
elseif (constant('FORCECSP')) |
1149
|
|
|
{ |
1150
|
|
|
header("Content-Security-Policy: ".constant('FORCECSP')); |
1151
|
|
|
} |
1152
|
|
|
if ($forcenocache) |
1153
|
|
|
{ |
1154
|
|
|
header("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"); |
1155
|
|
|
} |
1156
|
|
|
} |
1157
|
|
|
|
1158
|
|
|
/** |
1159
|
|
|
* Ouput html header of a page. |
1160
|
|
|
* This code is also duplicated into security2.lib.php::dol_loginfunction |
1161
|
|
|
* |
1162
|
|
|
* @param string $head Optionnal head lines |
1163
|
|
|
* @param string $title HTML title |
1164
|
|
|
* @param int $disablejs Disable js output |
1165
|
|
|
* @param int $disablehead Disable head output |
1166
|
|
|
* @param array $arrayofjs Array of complementary js files |
1167
|
|
|
* @param array $arrayofcss Array of complementary css files |
1168
|
|
|
* @param int $disablejmobile Disable jmobile (No more used) |
1169
|
|
|
* @param int $disablenofollow Disable no follow tag |
1170
|
|
|
* @return void |
1171
|
|
|
*/ |
1172
|
|
|
function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $disablejmobile=0, $disablenofollow=0) |
1173
|
|
|
{ |
1174
|
|
|
global $db, $conf, $langs, $user, $hookmanager; |
1175
|
|
|
|
1176
|
|
|
top_httphead(); |
1177
|
|
|
|
1178
|
|
|
if (empty($conf->css)) $conf->css = '/theme/eldy/style.css.php'; // If not defined, eldy by default |
1179
|
|
|
|
1180
|
|
|
print '<!doctype html>'."\n"; |
1181
|
|
|
|
1182
|
|
|
if (! empty($conf->global->MAIN_USE_CACHE_MANIFEST)) print '<html lang="'.substr($langs->defaultlang,0,2).'" manifest="'.DOL_URL_ROOT.'/cache.manifest">'."\n"; |
1183
|
|
|
else print '<html lang="'.substr($langs->defaultlang,0,2).'">'."\n"; |
1184
|
|
|
//print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">'."\n"; |
1185
|
|
|
if (empty($disablehead)) |
1186
|
|
|
{ |
1187
|
|
|
$ext='layout='.$conf->browser->layout.'&version='.urlencode(DOL_VERSION); |
1188
|
|
|
|
1189
|
|
|
print "<head>\n"; |
1190
|
|
|
|
1191
|
|
|
if (GETPOST('dol_basehref','alpha')) print '<base href="'.dol_escape_htmltag(GETPOST('dol_basehref','alpha')).'">'."\n"; |
1192
|
|
|
|
1193
|
|
|
// Displays meta |
1194
|
|
|
print '<meta charset="UTF-8">'."\n"; |
1195
|
|
|
print '<meta name="robots" content="noindex'.($disablenofollow?'':',nofollow').'">'."\n"; // Do not index |
1196
|
|
|
print '<meta name="viewport" content="width=device-width, initial-scale=1.0">'."\n"; // Scale for mobile device |
1197
|
|
|
print '<meta name="author" content="Dolibarr Development Team">'."\n"; |
1198
|
|
|
|
1199
|
|
|
// Favicon |
1200
|
|
|
$favicon=dol_buildpath('/theme/'.$conf->theme.'/img/favicon.ico',1); |
1201
|
|
|
if (! empty($conf->global->MAIN_FAVICON_URL)) $favicon=$conf->global->MAIN_FAVICON_URL; |
1202
|
|
|
if (empty($conf->dol_use_jmobile)) print '<link rel="shortcut icon" type="image/x-icon" href="'.$favicon.'"/>'."\n"; // Not required into an Android webview |
1203
|
|
|
//if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) print '<link rel="top" title="'.$langs->trans("Home").'" href="'.(DOL_URL_ROOT?DOL_URL_ROOT:'/').'">'."\n"; |
1204
|
|
|
//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"; |
1205
|
|
|
//if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) print '<link rel="author" title="Dolibarr Development Team" href="https://www.dolibarr.org">'."\n"; |
1206
|
|
|
|
1207
|
|
|
// Auto refresh page |
1208
|
|
|
if (GETPOST('autorefresh','int') > 0) print '<meta http-equiv="refresh" content="'.GETPOST('autorefresh','int').'">'; |
1209
|
|
|
|
1210
|
|
|
// Displays title |
1211
|
|
|
$appli=constant('DOL_APPLICATION_TITLE'); |
1212
|
|
|
if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $appli=$conf->global->MAIN_APPLICATION_TITLE; |
1213
|
|
|
|
1214
|
|
|
print '<title>'; |
1215
|
|
|
$titletoshow=''; |
1216
|
|
|
if ($title && ! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/noapp/',$conf->global->MAIN_HTML_TITLE)) $titletoshow = dol_htmlentities($title); |
1217
|
|
|
else if ($title) $titletoshow = dol_htmlentities($appli.' - '.$title); |
1218
|
|
|
else $titletoshow = dol_htmlentities($appli); |
1219
|
|
|
|
1220
|
|
|
if (! is_object($hookmanager)) $hookmanager = new HookManager($db); |
1221
|
|
|
$hookmanager->initHooks("main"); |
1222
|
|
|
$parameters=array('title'=>$titletoshow); |
1223
|
|
|
$result=$hookmanager->executeHooks('setHtmlTitle',$parameters); // Note that $action and $object may have been modified by some hooks |
1224
|
|
|
if ($result > 0) $titletoshow = $hookmanager->resPrint; // Replace Title to show |
1225
|
|
|
else $titletoshow .= $hookmanager->resPrint; // Concat to Title to show |
1226
|
|
|
|
1227
|
|
|
print $titletoshow; |
1228
|
|
|
print '</title>'; |
1229
|
|
|
|
1230
|
|
|
print "\n"; |
1231
|
|
|
|
1232
|
|
|
if (GETPOST('version','int')) $ext='version='.GETPOST('version','int'); // usefull to force no cache on css/js |
1233
|
|
|
if (GETPOST('testmenuhider','int') || ! empty($conf->global->MAIN_TESTMENUHIDER)) $ext.='&testmenuhider='.(GETPOST('testmenuhider','int')?GETPOST('testmenuhider','int'):$conf->global->MAIN_TESTMENUHIDER); |
1234
|
|
|
|
1235
|
|
|
$themeparam='?lang='.$langs->defaultlang.'&theme='.$conf->theme.(GETPOST('optioncss','aZ09')?'&optioncss='.GETPOST('optioncss','aZ09',1):'').'&userid='.$user->id.'&entity='.$conf->entity; |
1236
|
|
|
$themeparam.=($ext?'&'.$ext:''); |
1237
|
|
|
if (! empty($_SESSION['dol_resetcache'])) $themeparam.='&dol_resetcache='.$_SESSION['dol_resetcache']; |
1238
|
|
|
if (GETPOST('dol_hide_topmenu','int')) { $themeparam.='&dol_hide_topmenu='.GETPOST('dol_hide_topmenu','int'); } |
1239
|
|
|
if (GETPOST('dol_hide_leftmenu','int')) { $themeparam.='&dol_hide_leftmenu='.GETPOST('dol_hide_leftmenu','int'); } |
1240
|
|
|
if (GETPOST('dol_optimize_smallscreen','int')) { $themeparam.='&dol_optimize_smallscreen='.GETPOST('dol_optimize_smallscreen','int'); } |
1241
|
|
|
if (GETPOST('dol_no_mouse_hover','int')) { $themeparam.='&dol_no_mouse_hover='.GETPOST('dol_no_mouse_hover','int'); } |
1242
|
|
|
if (GETPOST('dol_use_jmobile','int')) { $themeparam.='&dol_use_jmobile='.GETPOST('dol_use_jmobile','int'); $conf->dol_use_jmobile=GETPOST('dol_use_jmobile','int'); } |
1243
|
|
|
|
1244
|
|
|
if (! defined('DISABLE_JQUERY') && ! $disablejs && $conf->use_javascript_ajax) |
1245
|
|
|
{ |
1246
|
|
|
print '<!-- Includes CSS for JQuery (Ajax library) -->'."\n"; |
1247
|
|
|
$jquerytheme = 'base'; |
1248
|
|
|
if (!empty($conf->global->MAIN_USE_JQUERY_THEME)) $jquerytheme = $conf->global->MAIN_USE_JQUERY_THEME; |
1249
|
|
|
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 |
1250
|
|
|
else print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/css/'.$jquerytheme.'/jquery-ui.css'.($ext?'?'.$ext:'').'">'."\n"; // JQuery |
1251
|
|
|
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 |
1252
|
|
|
if (! defined('DISABLE_SELECT2') && (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT'))) // jQuery plugin "mutiselect", "multiple-select", "select2"... |
1253
|
|
|
{ |
1254
|
|
|
$tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?constant('REQUIRE_JQUERY_MULTISELECT'):$conf->global->MAIN_USE_JQUERY_MULTISELECT; |
1255
|
|
|
print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/'.$tmpplugin.'/dist/css/'.$tmpplugin.'.css'.($ext?'?'.$ext:'').'">'."\n"; |
1256
|
|
|
} |
1257
|
|
|
} |
1258
|
|
|
|
1259
|
|
|
if (! defined('DISABLE_FONT_AWSOME')) |
1260
|
|
|
{ |
1261
|
|
|
print '<!-- Includes CSS for font awesome -->'."\n"; |
1262
|
|
|
print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/theme/common/fontawesome/css/font-awesome.min.css'.($ext?'?'.$ext:'').'">'."\n"; |
1263
|
|
|
} |
1264
|
|
|
|
1265
|
|
|
print '<!-- Includes CSS for Dolibarr theme -->'."\n"; |
1266
|
|
|
// Output style sheets (optioncss='print' or ''). Note: $conf->css looks like '/theme/eldy/style.css.php' |
1267
|
|
|
$themepath=dol_buildpath($conf->css,1); |
1268
|
|
|
$themesubdir=''; |
1269
|
|
|
if (! empty($conf->modules_parts['theme'])) // This slow down |
1270
|
|
|
{ |
1271
|
|
|
foreach($conf->modules_parts['theme'] as $reldir) |
1272
|
|
|
{ |
1273
|
|
|
if (file_exists(dol_buildpath($reldir.$conf->css, 0))) |
1274
|
|
|
{ |
1275
|
|
|
$themepath=dol_buildpath($reldir.$conf->css, 1); |
1276
|
|
|
$themesubdir=$reldir; |
1277
|
|
|
break; |
1278
|
|
|
} |
1279
|
|
|
} |
1280
|
|
|
} |
1281
|
|
|
|
1282
|
|
|
//print 'themepath='.$themepath.' themeparam='.$themeparam;exit; |
1283
|
|
|
print '<link rel="stylesheet" type="text/css" href="'.$themepath.$themeparam.'">'."\n"; |
1284
|
|
|
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"; |
1285
|
|
|
|
1286
|
|
|
// CSS forced by modules (relative url starting with /) |
1287
|
|
|
if (! empty($conf->modules_parts['css'])) |
1288
|
|
|
{ |
1289
|
|
|
$arraycss=(array) $conf->modules_parts['css']; |
1290
|
|
|
foreach($arraycss as $modcss => $filescss) |
1291
|
|
|
{ |
1292
|
|
|
$filescss=(array) $filescss; // To be sure filecss is an array |
1293
|
|
|
foreach($filescss as $cssfile) |
1294
|
|
|
{ |
1295
|
|
|
if (empty($cssfile)) dol_syslog("Warning: module ".$modcss." declared a css path file into its descriptor that is empty.", LOG_WARNING); |
1296
|
|
|
// cssfile is a relative path |
1297
|
|
|
print '<!-- Includes CSS added by module '.$modcss. ' -->'."\n".'<link rel="stylesheet" type="text/css" href="'.dol_buildpath($cssfile,1); |
1298
|
|
|
// 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. |
1299
|
|
|
if (!preg_match('/\.css$/i',$cssfile)) print $themeparam; |
1300
|
|
|
print '">'."\n"; |
1301
|
|
|
} |
1302
|
|
|
} |
1303
|
|
|
} |
1304
|
|
|
// CSS forced by page in top_htmlhead call (relative url starting with /) |
1305
|
|
|
if (is_array($arrayofcss)) |
1306
|
|
|
{ |
1307
|
|
|
foreach($arrayofcss as $cssfile) |
1308
|
|
|
{ |
1309
|
|
|
print '<!-- Includes CSS added by page -->'."\n".'<link rel="stylesheet" type="text/css" title="default" href="'.dol_buildpath($cssfile,1); |
1310
|
|
|
// 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. |
1311
|
|
|
if (!preg_match('/\.css$/i',$cssfile)) print $themeparam; |
1312
|
|
|
print '">'."\n"; |
1313
|
|
|
} |
1314
|
|
|
} |
1315
|
|
|
|
1316
|
|
|
// Output standard javascript links |
1317
|
|
|
if (! defined('DISABLE_JQUERY') && ! $disablejs && ! empty($conf->use_javascript_ajax)) |
1318
|
|
|
{ |
1319
|
|
|
// JQuery. Must be before other includes |
1320
|
|
|
print '<!-- Includes JS for JQuery -->'."\n"; |
1321
|
|
|
if (defined('JS_JQUERY') && constant('JS_JQUERY')) print '<script type="text/javascript" src="'.JS_JQUERY.'jquery.min.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1322
|
|
|
else print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/js/jquery.min.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1323
|
|
|
if (! empty($conf->global->MAIN_FEATURES_LEVEL) && ! defined('JS_JQUERY_MIGRATE_DISABLED')) |
1324
|
|
|
{ |
1325
|
|
|
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"; |
|
|
|
|
1326
|
|
|
else print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/js/jquery-migrate.min.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1327
|
|
|
} |
1328
|
|
|
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"; |
1329
|
|
|
else print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/js/jquery-ui.min.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1330
|
|
|
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"; |
1331
|
|
|
// jQuery jnotify |
1332
|
|
|
if (empty($conf->global->MAIN_DISABLE_JQUERY_JNOTIFY) && ! defined('DISABLE_JQUERY_JNOTIFY')) |
1333
|
|
|
{ |
1334
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jnotify/jquery.jnotify.min.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1335
|
|
|
} |
1336
|
|
|
// Flot |
1337
|
|
|
if (empty($conf->global->MAIN_DISABLE_JQUERY_FLOT) && ! defined('DISABLE_JQUERY_FLOT')) |
1338
|
|
|
{ |
1339
|
|
|
if (constant('JS_JQUERY_FLOT')) |
1340
|
|
|
{ |
1341
|
|
|
print '<script type="text/javascript" src="'.JS_JQUERY_FLOT.'jquery.flot.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1342
|
|
|
print '<script type="text/javascript" src="'.JS_JQUERY_FLOT.'jquery.flot.pie.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1343
|
|
|
print '<script type="text/javascript" src="'.JS_JQUERY_FLOT.'jquery.flot.stack.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1344
|
|
|
} |
1345
|
|
|
else |
1346
|
|
|
{ |
1347
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/flot/jquery.flot.min.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1348
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/flot/jquery.flot.pie.min.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1349
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/flot/jquery.flot.stack.min.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1350
|
|
|
} |
1351
|
|
|
} |
1352
|
|
|
// jQuery jeditable |
1353
|
|
|
if (! empty($conf->global->MAIN_USE_JQUERY_JEDITABLE) && ! defined('DISABLE_JQUERY_JEDITABLE')) |
1354
|
|
|
{ |
1355
|
|
|
print '<!-- JS to manage editInPlace feature -->'."\n"; |
1356
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1357
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.ui-datepicker.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1358
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.ui-autocomplete.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1359
|
|
|
print '<script type="text/javascript">'."\n"; |
1360
|
|
|
print 'var urlSaveInPlace = \''.DOL_URL_ROOT.'/core/ajax/saveinplace.php\';'."\n"; |
1361
|
|
|
print 'var urlLoadInPlace = \''.DOL_URL_ROOT.'/core/ajax/loadinplace.php\';'."\n"; |
1362
|
|
|
print 'var tooltipInPlace = \''.$langs->transnoentities('ClickToEdit').'\';'."\n"; // Added in title attribute of span |
1363
|
|
|
print 'var placeholderInPlace = \' \';'."\n"; // If we put another string than $langs->trans("ClickToEdit") here, nothing is shown. If we put empty string, there is error, Why ? |
1364
|
|
|
print 'var cancelInPlace = \''.$langs->trans('Cancel').'\';'."\n"; |
1365
|
|
|
print 'var submitInPlace = \''.$langs->trans('Ok').'\';'."\n"; |
1366
|
|
|
print 'var indicatorInPlace = \'<img src="'.DOL_URL_ROOT."/theme/".$conf->theme."/img/working.gif".'">\';'."\n"; |
1367
|
|
|
print 'var withInPlace = 300;'; // width in pixel for default string edit |
1368
|
|
|
print '</script>'."\n"; |
1369
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/editinplace.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1370
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.ckeditor.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1371
|
|
|
} |
1372
|
|
|
// jQuery Timepicker |
1373
|
|
|
if (! empty($conf->global->MAIN_USE_JQUERY_TIMEPICKER) || defined('REQUIRE_JQUERY_TIMEPICKER')) |
1374
|
|
|
{ |
1375
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/timepicker/jquery-ui-timepicker-addon.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1376
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/timepicker.js.php?lang='.$langs->defaultlang.($ext?'&'.$ext:'').'"></script>'."\n"; |
1377
|
|
|
} |
1378
|
|
|
if (! defined('DISABLE_SELECT2') && (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT'))) // jQuery plugin "mutiselect", "multiple-select", "select2", ... |
1379
|
|
|
{ |
1380
|
|
|
$tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?constant('REQUIRE_JQUERY_MULTISELECT'):$conf->global->MAIN_USE_JQUERY_MULTISELECT; |
1381
|
|
|
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 |
1382
|
|
|
} |
1383
|
|
|
if (! defined('DISABLE_MULTISELECT')) // jQuery plugin "mutiselect" to select with checkboxes |
1384
|
|
|
{ |
1385
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/multiselect/jquery.multi-select.js'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1386
|
|
|
} |
1387
|
|
|
} |
1388
|
|
|
|
1389
|
|
|
if (! $disablejs && ! empty($conf->use_javascript_ajax)) |
1390
|
|
|
{ |
1391
|
|
|
// CKEditor |
1392
|
|
|
if (! empty($conf->fckeditor->enabled) && (empty($conf->global->FCKEDITOR_EDITORNAME) || $conf->global->FCKEDITOR_EDITORNAME == 'ckeditor') && ! defined('DISABLE_CKEDITOR')) |
1393
|
|
|
{ |
1394
|
|
|
print '<!-- Includes JS for CKEditor -->'."\n"; |
1395
|
|
|
$pathckeditor = DOL_URL_ROOT . '/includes/ckeditor/ckeditor/'; |
1396
|
|
|
$jsckeditor='ckeditor.js'; |
1397
|
|
|
if (constant('JS_CKEDITOR')) // To use external ckeditor 4 js lib |
1398
|
|
|
{ |
1399
|
|
|
$pathckeditor=constant('JS_CKEDITOR'); |
1400
|
|
|
} |
1401
|
|
|
print '<script type="text/javascript">'; |
1402
|
|
|
print 'var CKEDITOR_BASEPATH = \''.$pathckeditor.'\';'."\n"; |
1403
|
|
|
print 'var ckeditorConfig = \''.dol_buildpath($themesubdir.'/theme/'.$conf->theme.'/ckeditor/config.js'.($ext?'?'.$ext:''),1).'\';'."\n"; // $themesubdir='' in standard usage |
1404
|
|
|
print 'var ckeditorFilebrowserBrowseUrl = \''.DOL_URL_ROOT.'/core/filemanagerdol/browser/default/browser.php?Connector='.DOL_URL_ROOT.'/core/filemanagerdol/connectors/php/connector.php\';'."\n"; |
1405
|
|
|
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"; |
1406
|
|
|
print '</script>'."\n"; |
1407
|
|
|
print '<script type="text/javascript" src="'.$pathckeditor.$jsckeditor.($ext?'?'.$ext:'').'"></script>'."\n"; |
1408
|
|
|
} |
1409
|
|
|
|
1410
|
|
|
// Browser notifications |
1411
|
|
|
if (! defined('DISABLE_BROWSER_NOTIF')) |
1412
|
|
|
{ |
1413
|
|
|
$enablebrowsernotif=false; |
1414
|
|
|
if (! empty($conf->agenda->enabled) && ! empty($conf->global->AGENDA_REMINDER_BROWSER)) $enablebrowsernotif=true; |
1415
|
|
|
if ($conf->browser->layout == 'phone') $enablebrowsernotif=false; |
1416
|
|
|
if ($enablebrowsernotif) |
1417
|
|
|
{ |
1418
|
|
|
print '<!-- Includes JS of Dolibarr (brwoser layout = '.$conf->browser->layout.')-->'."\n"; |
1419
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/lib_notification.js.php'.($ext?'?'.$ext:'').'"></script>'."\n"; |
1420
|
|
|
} |
1421
|
|
|
} |
1422
|
|
|
|
1423
|
|
|
// Global js function |
1424
|
|
|
print '<!-- Includes JS of Dolibarr -->'."\n"; |
1425
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/lib_head.js.php?lang='.$langs->defaultlang.($ext?'&'.$ext:'').'"></script>'."\n"; |
1426
|
|
|
|
1427
|
|
|
// JS forced by modules (relative url starting with /) |
1428
|
|
|
if (! empty($conf->modules_parts['js'])) // $conf->modules_parts['js'] is array('module'=>array('file1','file2')) |
1429
|
|
|
{ |
1430
|
|
|
$arrayjs=(array) $conf->modules_parts['js']; |
1431
|
|
|
foreach($arrayjs as $modjs => $filesjs) |
1432
|
|
|
{ |
1433
|
|
|
$filesjs=(array) $filesjs; // To be sure filejs is an array |
1434
|
|
|
foreach($filesjs as $jsfile) |
1435
|
|
|
{ |
1436
|
|
|
// jsfile is a relative path |
1437
|
|
|
print '<!-- Include JS added by module '.$modjs. '-->'."\n".'<script type="text/javascript" src="'.dol_buildpath($jsfile,1).'"></script>'."\n"; |
1438
|
|
|
} |
1439
|
|
|
} |
1440
|
|
|
} |
1441
|
|
|
// JS forced by page in top_htmlhead (relative url starting with /) |
1442
|
|
|
if (is_array($arrayofjs)) |
1443
|
|
|
{ |
1444
|
|
|
print '<!-- Includes JS added by page -->'."\n"; |
1445
|
|
|
foreach($arrayofjs as $jsfile) |
1446
|
|
|
{ |
1447
|
|
|
if (preg_match('/^http/i',$jsfile)) |
1448
|
|
|
{ |
1449
|
|
|
print '<script type="text/javascript" src="'.$jsfile.'"></script>'."\n"; |
1450
|
|
|
} |
1451
|
|
|
else |
1452
|
|
|
{ |
1453
|
|
|
print '<script type="text/javascript" src="'.dol_buildpath($jsfile,1).'"></script>'."\n"; |
1454
|
|
|
} |
1455
|
|
|
} |
1456
|
|
|
} |
1457
|
|
|
} |
1458
|
|
|
|
1459
|
|
|
if (! empty($head)) print $head."\n"; |
1460
|
|
|
if (! empty($conf->global->MAIN_HTML_HEADER)) print $conf->global->MAIN_HTML_HEADER."\n"; |
1461
|
|
|
|
1462
|
|
|
print "</head>\n\n"; |
1463
|
|
|
} |
1464
|
|
|
|
1465
|
|
|
$conf->headerdone=1; // To tell header was output |
1466
|
|
|
} |
1467
|
|
|
|
1468
|
|
|
|
1469
|
|
|
/** |
1470
|
|
|
* Show an HTML header + a BODY + The top menu bar |
1471
|
|
|
* |
1472
|
|
|
* @param string $head Lines in the HEAD |
1473
|
|
|
* @param string $title Title of web page |
1474
|
|
|
* @param string $target Target to use in menu links (Example: '' or '_top') |
1475
|
|
|
* @param int $disablejs Do not output links to js (Ex: qd fonction utilisee par sous formulaire Ajax) |
1476
|
|
|
* @param int $disablehead Do not output head section |
1477
|
|
|
* @param array $arrayofjs Array of js files to add in header |
1478
|
|
|
* @param array $arrayofcss Array of css files to add in header |
1479
|
|
|
* @param string $morequerystring Query string to add to the link "print" to get same parameters (use only if autodetect fails) |
1480
|
|
|
* @param string $helppagename Name of wiki page for help ('' by default). |
1481
|
|
|
* Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage |
1482
|
|
|
* For other external page: http://server/url |
1483
|
|
|
* @return void |
1484
|
|
|
*/ |
1485
|
|
|
function top_menu($head, $title='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $helppagename='') |
1486
|
|
|
{ |
1487
|
|
|
global $user, $conf, $langs, $db; |
1488
|
|
|
global $dolibarr_main_authentication, $dolibarr_main_demo; |
1489
|
|
|
global $hookmanager,$menumanager; |
1490
|
|
|
|
1491
|
|
|
$searchform=''; |
1492
|
|
|
$bookmarks=''; |
1493
|
|
|
|
1494
|
|
|
// Instantiate hooks of thirdparty module |
1495
|
|
|
$hookmanager->initHooks(array('toprightmenu')); |
1496
|
|
|
|
1497
|
|
|
$toprightmenu=''; |
1498
|
|
|
|
1499
|
|
|
// For backward compatibility with old modules |
1500
|
|
|
if (empty($conf->headerdone)) |
1501
|
|
|
{ |
1502
|
|
|
top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss); |
1503
|
|
|
print '<body id="mainbody">'; |
1504
|
|
|
} |
1505
|
|
|
|
1506
|
|
|
/* |
1507
|
|
|
* Top menu |
1508
|
|
|
*/ |
1509
|
|
|
if ((empty($conf->dol_hide_topmenu) || GETPOST('dol_invisible_topmenu','int')) && (! defined('NOREQUIREMENU') || ! constant('NOREQUIREMENU'))) |
1510
|
|
|
{ |
1511
|
|
|
print "\n".'<!-- Start top horizontal -->'."\n"; |
1512
|
|
|
|
1513
|
|
|
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. |
1514
|
|
|
|
1515
|
|
|
// Show menu entries |
1516
|
|
|
print '<div id="tmenu_tooltip'.(empty($conf->global->MAIN_MENU_INVERT)?'':'invert').'" class="tmenu">'."\n"; |
1517
|
|
|
$menumanager->atarget=$target; |
1518
|
|
|
$menumanager->showmenu('top', array('searchform'=>$searchform, 'bookmarks'=>$bookmarks)); // This contains a \n |
1519
|
|
|
print "</div>\n"; |
1520
|
|
|
|
1521
|
|
|
// Define link to login card |
1522
|
|
|
$appli=constant('DOL_APPLICATION_TITLE'); |
1523
|
|
|
if (! empty($conf->global->MAIN_APPLICATION_TITLE)) |
1524
|
|
|
{ |
1525
|
|
|
$appli=$conf->global->MAIN_APPLICATION_TITLE; |
1526
|
|
|
if (preg_match('/\d\.\d/', $appli)) |
1527
|
|
|
{ |
1528
|
|
|
if (! preg_match('/'.preg_quote(DOL_VERSION).'/', $appli)) $appli.=" (".DOL_VERSION.")"; // If new title contains a version that is different than core |
1529
|
|
|
} |
1530
|
|
|
else $appli.=" ".DOL_VERSION; |
1531
|
|
|
} |
1532
|
|
|
else $appli.=" ".DOL_VERSION; |
1533
|
|
|
|
1534
|
|
|
if (! empty($conf->global->MAIN_FEATURES_LEVEL)) $appli.="<br>".$langs->trans("LevelOfFeature").': '.$conf->global->MAIN_FEATURES_LEVEL; |
1535
|
|
|
|
1536
|
|
|
$logouttext=''; |
1537
|
|
|
if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) |
1538
|
|
|
{ |
1539
|
|
|
//$logouthtmltext=$appli.'<br>'; |
1540
|
|
|
if ($_SESSION["dol_authmode"] != 'forceuser' && $_SESSION["dol_authmode"] != 'http') |
1541
|
|
|
{ |
1542
|
|
|
$logouthtmltext.=$langs->trans("Logout").'<br>'; |
|
|
|
|
1543
|
|
|
|
1544
|
|
|
$logouttext .='<a accesskey="l" href="'.DOL_URL_ROOT.'/user/logout.php">'; |
1545
|
|
|
//$logouttext .= img_picto($langs->trans('Logout').":".$langs->trans('Logout'), 'logout_top.png', 'class="login"', 0, 0, 1); |
1546
|
|
|
$logouttext .='<span class="fa fa-sign-out atoplogin"></span>'; |
1547
|
|
|
$logouttext .='</a>'; |
1548
|
|
|
} |
1549
|
|
|
else |
1550
|
|
|
{ |
1551
|
|
|
$logouthtmltext.=$langs->trans("NoLogoutProcessWithAuthMode",$_SESSION["dol_authmode"]); |
1552
|
|
|
$logouttext .= img_picto($langs->trans('Logout').":".$langs->trans('Logout'), 'logout_top.png', 'class="login"', 0, 0, 1); |
1553
|
|
|
} |
1554
|
|
|
} |
1555
|
|
|
|
1556
|
|
|
print '<div class="login_block">'."\n"; |
1557
|
|
|
|
1558
|
|
|
// Add login user link |
1559
|
|
|
$toprightmenu.='<div class="login_block_user">'; |
1560
|
|
|
|
1561
|
|
|
// Login name with photo and tooltip |
1562
|
|
|
$mode=-1; |
1563
|
|
|
$toprightmenu.='<div class="inline-block nowrap"><div class="inline-block login_block_elem login_block_elem_name" style="padding: 0px;">'; |
1564
|
|
|
$toprightmenu.=$user->getNomUrl($mode, '', 1, 0, 11, 0, ($user->firstname ? 'firstname' : -1),'atoplogin'); |
1565
|
|
|
$toprightmenu.='</div></div>'; |
1566
|
|
|
|
1567
|
|
|
$toprightmenu.='</div>'."\n"; |
1568
|
|
|
|
1569
|
|
|
$toprightmenu.='<div class="login_block_other">'; |
1570
|
|
|
|
1571
|
|
|
// Execute hook printTopRightMenu (hooks should output string like '<div class="login"><a href="">mylink</a></div>') |
1572
|
|
|
$parameters=array(); |
1573
|
|
|
$result=$hookmanager->executeHooks('printTopRightMenu',$parameters); // Note that $action and $object may have been modified by some hooks |
1574
|
|
|
if (is_numeric($result)) |
1575
|
|
|
{ |
1576
|
|
|
if ($result == 0) |
1577
|
|
|
$toprightmenu.=$hookmanager->resPrint; // add |
1578
|
|
|
else |
1579
|
|
|
$toprightmenu=$hookmanager->resPrint; // replace |
1580
|
|
|
} |
1581
|
|
|
else |
1582
|
|
|
{ |
1583
|
|
|
$toprightmenu.=$result; // For backward compatibility |
1584
|
|
|
} |
1585
|
|
|
|
1586
|
|
|
// Link to module builder |
1587
|
|
|
if (! empty($conf->modulebuilder->enabled)) |
1588
|
|
|
{ |
1589
|
|
|
$text ='<a href="'.DOL_URL_ROOT.'/modulebuilder/index.php?mainmenu=home&leftmenu=admintools" target="_modulebuilder">'; |
1590
|
|
|
//$text.= img_picto(":".$langs->trans("ModuleBuilder"), 'printer_top.png', 'class="printer"'); |
1591
|
|
|
$text.='<span class="fa fa-bug atoplogin"></span>'; |
1592
|
|
|
$text.='</a>'; |
1593
|
|
|
$toprightmenu.=@Form::textwithtooltip('',$langs->trans("ModuleBuilder"),2,1,$text,'login_block_elem',2); |
1594
|
|
|
} |
1595
|
|
|
|
1596
|
|
|
// Link to print main content area |
1597
|
|
|
if (empty($conf->global->MAIN_PRINT_DISABLELINK) && empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $conf->browser->layout != 'phone') |
1598
|
|
|
{ |
1599
|
|
|
$qs=dol_escape_htmltag($_SERVER["QUERY_STRING"]); |
1600
|
|
|
|
1601
|
|
|
if (is_array($_POST)) |
1602
|
|
|
{ |
1603
|
|
|
foreach($_POST as $key=>$value) { |
1604
|
|
|
if ($key!=='action' && $key!=='password' && !is_array($value)) $qs.='&'.$key.'='.urlencode($value); |
1605
|
|
|
} |
1606
|
|
|
} |
1607
|
|
|
$qs.=(($qs && $morequerystring)?'&':'').$morequerystring; |
1608
|
|
|
$text ='<a href="'.dol_escape_htmltag($_SERVER["PHP_SELF"]).'?'.$qs.($qs?'&':'').'optioncss=print" target="_blank">'; |
1609
|
|
|
//$text.= img_picto(":".$langs->trans("PrintContentArea"), 'printer_top.png', 'class="printer"'); |
1610
|
|
|
$text.='<span class="fa fa-print atoplogin"></span>'; |
1611
|
|
|
$text.='</a>'; |
1612
|
|
|
$toprightmenu.=@Form::textwithtooltip('',$langs->trans("PrintContentArea"),2,1,$text,'login_block_elem',2); |
1613
|
|
|
} |
1614
|
|
|
|
1615
|
|
|
// Link to Dolibarr wiki pages |
1616
|
|
|
if (empty($conf->global->MAIN_HELP_DISABLELINK) && empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) |
1617
|
|
|
{ |
1618
|
|
|
$langs->load("help"); |
1619
|
|
|
|
1620
|
|
|
$helpbaseurl=''; |
1621
|
|
|
$helppage=''; |
1622
|
|
|
$mode=''; |
1623
|
|
|
|
1624
|
|
|
if (empty($helppagename)) $helppagename='EN:User_documentation|FR:Documentation_utilisateur|ES:Documentación_usuarios'; |
1625
|
|
|
|
1626
|
|
|
// Get helpbaseurl, helppage and mode from helppagename and langs |
1627
|
|
|
$arrayres=getHelpParamFor($helppagename,$langs); |
1628
|
|
|
$helpbaseurl=$arrayres['helpbaseurl']; |
1629
|
|
|
$helppage=$arrayres['helppage']; |
1630
|
|
|
$mode=$arrayres['mode']; |
1631
|
|
|
|
1632
|
|
|
// Link to help pages |
1633
|
|
|
if ($helpbaseurl && $helppage) |
1634
|
|
|
{ |
1635
|
|
|
$text=''; |
1636
|
|
|
if(!empty($conf->global->MAIN_SHOWDATABASENAMEINHELPPAGESLINK)) { |
1637
|
|
|
$langs->load('admin'); |
1638
|
|
|
$appli .= '<br>' . $langs->trans("Database") . ': ' . $db->database_name; |
1639
|
|
|
} |
1640
|
|
|
$title=$appli.'<br>'; |
1641
|
|
|
$title.=$langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage'); |
1642
|
|
|
if ($mode == 'wiki') $title.=' - '.$langs->trans("PageWiki").' "'.dol_escape_htmltag(strtr($helppage,'_',' ')).'"'; |
1643
|
|
|
$text.='<a class="help" target="_blank" rel="noopener" href="'; |
1644
|
|
|
if ($mode == 'wiki') $text.=sprintf($helpbaseurl,urlencode(html_entity_decode($helppage))); |
1645
|
|
|
else $text.=sprintf($helpbaseurl,$helppage); |
1646
|
|
|
$text.='">'; |
1647
|
|
|
//$text.=img_picto('', 'helpdoc_top').' '; |
1648
|
|
|
$text.='<span class="fa fa-question-circle atoplogin"></span>'; |
1649
|
|
|
//$toprightmenu.=$langs->trans($mode == 'wiki' ? 'OnlineHelp': 'Help'); |
1650
|
|
|
//if ($mode == 'wiki') $text.=' ('.dol_trunc(strtr($helppage,'_',' '),8).')'; |
1651
|
|
|
$text.='</a>'; |
1652
|
|
|
//$toprightmenu.='</div>'."\n"; |
1653
|
|
|
$toprightmenu.=@Form::textwithtooltip('',$title,2,1,$text,'login_block_elem',2); |
1654
|
|
|
} |
1655
|
|
|
} |
1656
|
|
|
|
1657
|
|
|
// Logout link |
1658
|
|
|
$toprightmenu.=@Form::textwithtooltip('',$logouthtmltext,2,1,$logouttext,'login_block_elem',2); |
1659
|
|
|
|
1660
|
|
|
$toprightmenu.='</div>'; |
1661
|
|
|
|
1662
|
|
|
print $toprightmenu; |
1663
|
|
|
|
1664
|
|
|
print "</div>\n"; // end div class="login_block" |
1665
|
|
|
|
1666
|
|
|
print '</div></div>'; |
1667
|
|
|
|
1668
|
|
|
print '<div style="clear: both;"></div>'; |
1669
|
|
|
print "<!-- End top horizontal menu -->\n\n"; |
1670
|
|
|
} |
1671
|
|
|
|
1672
|
|
|
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:'').'">'; |
|
|
|
|
1673
|
|
|
} |
1674
|
|
|
|
1675
|
|
|
|
1676
|
|
|
/** |
1677
|
|
|
* Show left menu bar |
1678
|
|
|
* |
1679
|
|
|
* @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 ''. |
1680
|
|
|
* @param string $helppagename Name of wiki page for help ('' by default). |
1681
|
|
|
* Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage |
1682
|
|
|
* For other external page: http://server/url |
1683
|
|
|
* @param string $notused Deprecated. Used in past to add content into left menu. Hooks can be used now. |
1684
|
|
|
* @param array $menu_array_after Table of menu entries to show after entries of menu handler |
1685
|
|
|
* @param int $leftmenuwithoutmainarea Must be set to 1. 0 by default for backward compatibility with old modules. |
1686
|
|
|
* @param string $title Title of web page |
1687
|
|
|
* @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) |
1688
|
|
|
* @return void |
1689
|
|
|
*/ |
1690
|
|
|
function left_menu($menu_array_before, $helppagename='', $notused='', $menu_array_after='', $leftmenuwithoutmainarea=0, $title='', $acceptdelayedhtml=0) |
1691
|
|
|
{ |
1692
|
|
|
global $user, $conf, $langs, $db, $form; |
1693
|
|
|
global $hookmanager, $menumanager; |
1694
|
|
|
|
1695
|
|
|
$searchform=''; |
1696
|
|
|
$bookmarks=''; |
1697
|
|
|
|
1698
|
|
|
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); |
1699
|
|
|
|
1700
|
|
|
if (empty($conf->dol_hide_leftmenu) && (! defined('NOREQUIREMENU') || ! constant('NOREQUIREMENU'))) |
1701
|
|
|
{ |
1702
|
|
|
// Instantiate hooks of thirdparty module |
1703
|
|
|
$hookmanager->initHooks(array('searchform','leftblock')); |
1704
|
|
|
|
1705
|
|
|
print "\n".'<!-- Begin side-nav id-left -->'."\n".'<div class="side-nav"><div id="id-left">'."\n"; |
1706
|
|
|
|
1707
|
|
|
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 ? |
1708
|
|
|
|
1709
|
|
|
print "\n"; |
1710
|
|
|
|
1711
|
|
|
if (! is_object($form)) $form=new Form($db); |
1712
|
|
|
$selected=-1; |
1713
|
|
|
$usedbyinclude=1; |
1714
|
|
|
include_once DOL_DOCUMENT_ROOT.'/core/ajax/selectsearchbox.php'; // This set $arrayresult |
1715
|
|
|
|
1716
|
|
|
if ($conf->use_javascript_ajax && empty($conf->global->MAIN_USE_OLD_SEARCH_FORM)) |
1717
|
|
|
{ |
1718
|
|
|
//$searchform.=$form->selectArrayAjax('searchselectcombo', DOL_URL_ROOT.'/core/ajax/selectsearchbox.php', $selected, '', '', 0, 1, 'vmenusearchselectcombo', 1, $langs->trans("Search"), 1); |
1719
|
|
|
$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); |
|
|
|
|
1720
|
|
|
} |
1721
|
|
|
else |
1722
|
|
|
{ |
1723
|
|
|
foreach($arrayresult as $key => $val) |
1724
|
|
|
{ |
1725
|
|
|
//$searchform.=printSearchForm($val['url'], $val['url'], $val['label'], 'maxwidth100', 'sall', $val['shortcut'], 'searchleft', img_picto('',$val['img'])); |
1726
|
|
|
$searchform.=printSearchForm($val['url'], $val['url'], $val['label'], 'maxwidth125', 'sall', $val['shortcut'], 'searchleft', img_picto('', $val['img'], '', false, 1, 1)); |
1727
|
|
|
} |
1728
|
|
|
} |
1729
|
|
|
|
1730
|
|
|
// Execute hook printSearchForm |
1731
|
|
|
$parameters=array('searchform'=>$searchform); |
1732
|
|
|
$reshook=$hookmanager->executeHooks('printSearchForm',$parameters); // Note that $action and $object may have been modified by some hooks |
1733
|
|
|
if (empty($reshook)) |
1734
|
|
|
{ |
1735
|
|
|
$searchform.=$hookmanager->resPrint; |
1736
|
|
|
} |
1737
|
|
|
else $searchform=$hookmanager->resPrint; |
1738
|
|
|
|
1739
|
|
|
// Force special value for $searchform |
1740
|
|
|
if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) || empty($conf->use_javascript_ajax)) |
1741
|
|
|
{ |
1742
|
|
|
$urltosearch=DOL_URL_ROOT.'/core/search_page.php?showtitlebefore=1'; |
1743
|
|
|
$searchform='<div class="blockvmenuimpair blockvmenusearchphone"><div id="divsearchforms1"><a href="'.$urltosearch.'" alt="'.dol_escape_htmltag($langs->trans("ShowSearchFields")).'">'.$langs->trans("Search").'...</a></div></div>'; |
1744
|
|
|
} |
1745
|
|
|
elseif ($conf->use_javascript_ajax && ! empty($conf->global->MAIN_USE_OLD_SEARCH_FORM)) |
1746
|
|
|
{ |
1747
|
|
|
$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>'; |
1748
|
|
|
$searchform.='<script type="text/javascript"> |
1749
|
|
|
jQuery(document).ready(function () { |
1750
|
|
|
jQuery("#divsearchforms1").click(function(){ |
1751
|
|
|
jQuery("#divsearchforms2").toggle(); |
1752
|
|
|
}); |
1753
|
|
|
}); |
1754
|
|
|
</script>' . "\n"; |
1755
|
|
|
$searchform.='</div>'; |
1756
|
|
|
} |
1757
|
|
|
|
1758
|
|
|
// Define $bookmarks |
1759
|
|
|
if (! empty($conf->bookmark->enabled) && $user->rights->bookmark->lire) |
1760
|
|
|
{ |
1761
|
|
|
include_once DOL_DOCUMENT_ROOT.'/bookmarks/bookmarks.lib.php'; |
1762
|
|
|
$langs->load("bookmarks"); |
1763
|
|
|
|
1764
|
|
|
$bookmarks=printBookmarksList($db, $langs); |
1765
|
|
|
} |
1766
|
|
|
|
1767
|
|
|
// Left column |
1768
|
|
|
print '<!-- Begin left menu -->'."\n"; |
1769
|
|
|
|
1770
|
|
|
print '<div class="vmenu"'.(empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)?'':' title="Left menu"').'>'."\n\n"; |
1771
|
|
|
|
1772
|
|
|
// Show left menu with other forms |
1773
|
|
|
$menumanager->menu_array = $menu_array_before; |
1774
|
|
|
$menumanager->menu_array_after = $menu_array_after; |
1775
|
|
|
$menumanager->showmenu('left', array('searchform'=>$searchform, 'bookmarks'=>$bookmarks)); // output menu_array and menu found in database |
1776
|
|
|
|
1777
|
|
|
// Dolibarr version + help + bug report link |
1778
|
|
|
print "\n"; |
1779
|
|
|
print "<!-- Begin Help Block-->\n"; |
1780
|
|
|
print '<div id="blockvmenuhelp" class="blockvmenuhelp">'."\n"; |
1781
|
|
|
|
1782
|
|
|
// Version |
1783
|
|
|
if (empty($conf->global->MAIN_HIDE_VERSION)) // Version is already on help picto and on login page. |
1784
|
|
|
{ |
1785
|
|
|
$doliurl='https://www.dolibarr.org'; |
1786
|
|
|
//local communities |
1787
|
|
|
if (preg_match('/fr/i',$langs->defaultlang)) $doliurl='https://www.dolibarr.fr'; |
1788
|
|
|
if (preg_match('/es/i',$langs->defaultlang)) $doliurl='https://www.dolibarr.es'; |
1789
|
|
|
if (preg_match('/de/i',$langs->defaultlang)) $doliurl='https://www.dolibarr.de'; |
1790
|
|
|
if (preg_match('/it/i',$langs->defaultlang)) $doliurl='https://www.dolibarr.it'; |
1791
|
|
|
if (preg_match('/gr/i',$langs->defaultlang)) $doliurl='https://www.dolibarr.gr'; |
1792
|
|
|
|
1793
|
|
|
$appli=constant('DOL_APPLICATION_TITLE'); |
1794
|
|
|
if (! empty($conf->global->MAIN_APPLICATION_TITLE)) |
1795
|
|
|
{ |
1796
|
|
|
$appli=$conf->global->MAIN_APPLICATION_TITLE; $doliurl=''; |
1797
|
|
|
if (preg_match('/\d\.\d/', $appli)) |
1798
|
|
|
{ |
1799
|
|
|
if (! preg_match('/'.preg_quote(DOL_VERSION).'/', $appli)) $appli.=" (".DOL_VERSION.")"; // If new title contains a version that is different than core |
1800
|
|
|
} |
1801
|
|
|
else $appli.=" ".DOL_VERSION; |
1802
|
|
|
} |
1803
|
|
|
else $appli.=" ".DOL_VERSION; |
1804
|
|
|
print '<div id="blockvmenuhelpapp" class="blockvmenuhelp">'; |
1805
|
|
|
if ($doliurl) print '<a class="help" target="_blank" rel="noopener" href="'.$doliurl.'">'; |
1806
|
|
|
else print '<span class="help">'; |
1807
|
|
|
print $appli; |
1808
|
|
|
if ($doliurl) print '</a>'; |
1809
|
|
|
else print '</span>'; |
1810
|
|
|
print '</div>'."\n"; |
1811
|
|
|
} |
1812
|
|
|
|
1813
|
|
|
// Link to bugtrack |
1814
|
|
|
if (! empty($conf->global->MAIN_BUGTRACK_ENABLELINK)) |
1815
|
|
|
{ |
1816
|
|
|
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; |
1817
|
|
|
|
1818
|
|
|
$bugbaseurl = 'https://github.com/Dolibarr/dolibarr/issues/new'; |
1819
|
|
|
$bugbaseurl.= '?title='; |
1820
|
|
|
$bugbaseurl.= urlencode("Bug: "); |
1821
|
|
|
$bugbaseurl.= '&body='; |
1822
|
|
|
$bugbaseurl.= urlencode("# Bug\n"); |
1823
|
|
|
$bugbaseurl.= urlencode("\n"); |
1824
|
|
|
$bugbaseurl.= urlencode("## Environment\n"); |
1825
|
|
|
$bugbaseurl.= urlencode("- **Version**: " . DOL_VERSION . "\n"); |
1826
|
|
|
$bugbaseurl.= urlencode("- **OS**: " . php_uname('s') . "\n"); |
1827
|
|
|
$bugbaseurl.= urlencode("- **Web server**: " . $_SERVER["SERVER_SOFTWARE"] . "\n"); |
1828
|
|
|
$bugbaseurl.= urlencode("- **PHP**: " . php_sapi_name() . ' ' . phpversion() . "\n"); |
1829
|
|
|
$bugbaseurl.= urlencode("- **Database**: " . $db::LABEL . ' ' . $db->getVersion() . "\n"); |
1830
|
|
|
$bugbaseurl.= urlencode("- **URL**: " . $_SERVER["REQUEST_URI"] . "\n"); |
1831
|
|
|
$bugbaseurl.= urlencode("\n"); |
1832
|
|
|
$bugbaseurl.= urlencode("## Report\n"); |
1833
|
|
|
print '<div id="blockvmenuhelpbugreport" class="blockvmenuhelp">'; |
1834
|
|
|
print '<a class="help" target="_blank" rel="noopener" href="'.$bugbaseurl.'">'.$langs->trans("FindBug").'</a>'; |
1835
|
|
|
print '</div>'; |
1836
|
|
|
} |
1837
|
|
|
|
1838
|
|
|
print "</div>\n"; |
1839
|
|
|
print "<!-- End Help Block-->\n"; |
1840
|
|
|
print "\n"; |
1841
|
|
|
|
1842
|
|
|
print "</div>\n"; |
1843
|
|
|
print "<!-- End left menu -->\n"; |
1844
|
|
|
print "\n"; |
1845
|
|
|
|
1846
|
|
|
// Execute hook printLeftBlock |
1847
|
|
|
$parameters=array(); |
1848
|
|
|
$reshook=$hookmanager->executeHooks('printLeftBlock',$parameters); // Note that $action and $object may have been modified by some hooks |
1849
|
|
|
print $hookmanager->resPrint; |
1850
|
|
|
|
1851
|
|
|
print '</div></div> <!-- End side-nav id-left -->'; // End div id="side-nav" div id="id-left" |
1852
|
|
|
} |
1853
|
|
|
|
1854
|
|
|
print "\n"; |
1855
|
|
|
print '<!-- Begin right area -->'."\n"; |
1856
|
|
|
|
1857
|
|
|
if (empty($leftmenuwithoutmainarea)) main_area($title); |
1858
|
|
|
} |
1859
|
|
|
|
1860
|
|
|
|
1861
|
|
|
/** |
1862
|
|
|
* Begin main area |
1863
|
|
|
* |
1864
|
|
|
* @param string $title Title |
1865
|
|
|
* @return void |
1866
|
|
|
*/ |
1867
|
|
|
function main_area($title='') |
1868
|
|
|
{ |
1869
|
|
|
global $conf, $langs; |
1870
|
|
|
|
1871
|
|
|
if (empty($conf->dol_hide_leftmenu)) print '<div id="id-right">'; |
1872
|
|
|
|
1873
|
|
|
print "\n"; |
1874
|
|
|
|
1875
|
|
|
print '<!-- Begin div class="fiche" -->'."\n".'<div class="fiche">'."\n"; |
1876
|
|
|
|
1877
|
|
|
if (! empty($conf->global->MAIN_ONLY_LOGIN_ALLOWED)) print info_admin($langs->trans("WarningYouAreInMaintenanceMode",$conf->global->MAIN_ONLY_LOGIN_ALLOWED)); |
1878
|
|
|
} |
1879
|
|
|
|
1880
|
|
|
|
1881
|
|
|
/** |
1882
|
|
|
* Return helpbaseurl, helppage and mode |
1883
|
|
|
* |
1884
|
|
|
* @param string $helppagename Page name ('EN:xxx,ES:eee,FR:fff...' or 'http://localpage') |
1885
|
|
|
* @param Translate $langs Language |
1886
|
|
|
* @return array Array of help urls |
1887
|
|
|
*/ |
1888
|
|
|
function getHelpParamFor($helppagename,$langs) |
1889
|
|
|
{ |
1890
|
|
|
$helpbaseurl=''; |
1891
|
|
|
$helppage=''; |
1892
|
|
|
$mode=''; |
1893
|
|
|
|
1894
|
|
|
if (preg_match('/^http/i',$helppagename)) |
1895
|
|
|
{ |
1896
|
|
|
// If complete URL |
1897
|
|
|
$helpbaseurl='%s'; |
1898
|
|
|
$helppage=$helppagename; |
1899
|
|
|
$mode='local'; |
1900
|
|
|
} |
1901
|
|
|
else |
1902
|
|
|
{ |
1903
|
|
|
// If WIKI URL |
1904
|
|
|
if (preg_match('/^es/i',$langs->defaultlang)) |
1905
|
|
|
{ |
1906
|
|
|
$helpbaseurl='http://wiki.dolibarr.org/index.php/%s'; |
1907
|
|
|
if (preg_match('/ES:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1]; |
1908
|
|
|
} |
1909
|
|
|
if (preg_match('/^fr/i',$langs->defaultlang)) |
1910
|
|
|
{ |
1911
|
|
|
$helpbaseurl='http://wiki.dolibarr.org/index.php/%s'; |
1912
|
|
|
if (preg_match('/FR:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1]; |
1913
|
|
|
} |
1914
|
|
|
if (empty($helppage)) // If help page not already found |
1915
|
|
|
{ |
1916
|
|
|
$helpbaseurl='http://wiki.dolibarr.org/index.php/%s'; |
1917
|
|
|
if (preg_match('/EN:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1]; |
1918
|
|
|
} |
1919
|
|
|
$mode='wiki'; |
1920
|
|
|
} |
1921
|
|
|
return array('helpbaseurl'=>$helpbaseurl,'helppage'=>$helppage,'mode'=>$mode); |
1922
|
|
|
} |
1923
|
|
|
|
1924
|
|
|
|
1925
|
|
|
/** |
1926
|
|
|
* Show a search area. |
1927
|
|
|
* Used when the javascript quick search is not used. |
1928
|
|
|
* |
1929
|
|
|
* @param string $urlaction Url post |
1930
|
|
|
* @param string $urlobject Url of the link under the search box |
1931
|
|
|
* @param string $title Title search area |
1932
|
|
|
* @param string $htmlmorecss Add more css |
1933
|
|
|
* @param string $htmlinputname Field Name input form |
1934
|
|
|
* @param string $accesskey Accesskey |
1935
|
|
|
* @param string $prefhtmlinputname Complement for id to avoid multiple same id in the page |
1936
|
|
|
* @param string $img Image to use |
1937
|
|
|
* @param string $showtitlebefore Show title before input text instead of into placeholder. This can be set when output is dedicated for text browsers. |
1938
|
|
|
* @return string |
1939
|
|
|
*/ |
1940
|
|
|
function printSearchForm($urlaction, $urlobject, $title, $htmlmorecss, $htmlinputname, $accesskey='', $prefhtmlinputname='',$img='', $showtitlebefore=0) |
1941
|
|
|
{ |
1942
|
|
|
global $conf,$langs,$user; |
1943
|
|
|
|
1944
|
|
|
$ret=''; |
1945
|
|
|
$ret.='<form action="'.$urlaction.'" method="post" class="searchform">'; |
1946
|
|
|
$ret.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">'; |
1947
|
|
|
$ret.='<input type="hidden" name="mode" value="search">'; |
1948
|
|
|
$ret.='<input type="hidden" name="savelogin" value="'.dol_escape_htmltag($user->login).'">'; |
1949
|
|
|
if ($showtitlebefore) $ret.=$title.' '; |
1950
|
|
|
$ret.='<input type="text" class="flat '.$htmlmorecss.'"'; |
1951
|
|
|
$ret.=' style="text-indent: 22px; background-image: url(\''.$img.'\'); background-repeat: no-repeat; background-position: 3px;"'; |
1952
|
|
|
$ret.=($accesskey?' accesskey="'.$accesskey.'"':''); |
1953
|
|
|
$ret.=' placeholder="'.strip_tags($title).'"'; |
1954
|
|
|
$ret.=' name="'.$htmlinputname.'" id="'.$prefhtmlinputname.$htmlinputname.'" />'; |
1955
|
|
|
//$ret.='<input type="submit" class="button" style="padding-top: 4px; padding-bottom: 4px; padding-left: 6px; padding-right: 6px" value="'.$langs->trans("Go").'">'; |
1956
|
|
|
$ret.='<button type="submit" class="button" style="padding-top: 4px; padding-bottom: 4px; padding-left: 6px; padding-right: 6px">'; |
1957
|
|
|
$ret.='<span class="fa fa-search"></span>'; |
1958
|
|
|
$ret.='</button>'; |
1959
|
|
|
$ret.="</form>\n"; |
1960
|
|
|
return $ret; |
1961
|
|
|
} |
1962
|
|
|
|
1963
|
|
|
|
1964
|
|
|
if (! function_exists("llxFooter")) |
1965
|
|
|
{ |
1966
|
|
|
/** |
1967
|
|
|
* Show HTML footer |
1968
|
|
|
* Close div /DIV class=fiche + /DIV id-right + /DIV id-container + /BODY + /HTML. |
1969
|
|
|
* If global var $delayedhtmlcontent was filled, we output it just before closing the body. |
1970
|
|
|
* |
1971
|
|
|
* @param string $comment A text to add as HTML comment into HTML generated page |
1972
|
|
|
* @param string $zone 'private' (for private pages) or 'public' (for public pages) |
1973
|
|
|
* @param int $disabledoutputofmessages Clear all messages stored into session without diplaying them |
1974
|
|
|
* @return void |
1975
|
|
|
*/ |
1976
|
|
|
function llxFooter($comment='',$zone='private', $disabledoutputofmessages=0) |
1977
|
|
|
{ |
1978
|
|
|
global $conf, $langs, $user, $object; |
1979
|
|
|
global $delayedhtmlcontent; |
1980
|
|
|
global $contextpage, $page, $limit; |
1981
|
|
|
|
1982
|
|
|
$ext='layout='.$conf->browser->layout.'&version='.urlencode(DOL_VERSION); |
1983
|
|
|
|
1984
|
|
|
// Global html output events ($mesgs, $errors, $warnings) |
1985
|
|
|
dol_htmloutput_events($disabledoutputofmessages); |
1986
|
|
|
|
1987
|
|
|
// Code for search criteria persistence. |
1988
|
|
|
// $user->lastsearch_values was set by the GETPOST when form field search_xxx exists |
1989
|
|
|
if (is_object($user) && ! empty($user->lastsearch_values_tmp) && is_array($user->lastsearch_values_tmp)) |
1990
|
|
|
{ |
1991
|
|
|
// Clean and save data |
1992
|
|
|
foreach($user->lastsearch_values_tmp as $key => $val) |
1993
|
|
|
{ |
1994
|
|
|
unset($_SESSION['lastsearch_values_tmp_'.$key]); // Clean array to rebuild it just after |
1995
|
|
|
if (count($val) && empty($_POST['button_removefilter'])) // If there is search criteria to save and we did not click on 'Clear filter' button |
1996
|
|
|
{ |
1997
|
|
|
if (empty($val['sortfield'])) unset($val['sortfield']); |
1998
|
|
|
if (empty($val['sortorder'])) unset($val['sortorder']); |
1999
|
|
|
dol_syslog('Save lastsearch_values_tmp_'.$key.'='.json_encode($val, 0)." (systematic recording of last search criterias)"); |
2000
|
|
|
$_SESSION['lastsearch_values_tmp_'.$key]=json_encode($val); |
2001
|
|
|
unset($_SESSION['lastsearch_values_'.$key]); |
2002
|
|
|
} |
2003
|
|
|
} |
2004
|
|
|
} |
2005
|
|
|
|
2006
|
|
|
|
2007
|
|
|
$relativepathstring = $_SERVER["PHP_SELF"]; |
2008
|
|
|
// Clean $relativepathstring |
2009
|
|
|
if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'),'/').'/', '', $relativepathstring); |
2010
|
|
|
$relativepathstring = preg_replace('/^\//', '', $relativepathstring); |
2011
|
|
|
$relativepathstring = preg_replace('/^custom\//', '', $relativepathstring); |
2012
|
|
|
if (preg_match('/list\.php$/', $relativepathstring)) |
2013
|
|
|
{ |
2014
|
|
|
unset($_SESSION['lastsearch_contextpage_tmp_'.$relativepathstring]); |
2015
|
|
|
unset($_SESSION['lastsearch_page_tmp_'.$relativepathstring]); |
2016
|
|
|
unset($_SESSION['lastsearch_limit_tmp_'.$relativepathstring]); |
2017
|
|
|
|
2018
|
|
|
if (! empty($contextpage)) $_SESSION['lastsearch_contextpage_tmp_'.$relativepathstring]=$contextpage; |
2019
|
|
|
if (! empty($page) && $page > 1) $_SESSION['lastsearch_page_tmp_'.$relativepathstring]=$page; |
2020
|
|
|
if (! empty($limit) && $limit != $conf->limit) $_SESSION['lastsearch_limit_tmp_'.$relativepathstring]=$limit; |
2021
|
|
|
|
2022
|
|
|
unset($_SESSION['lastsearch_contextpage_'.$relativepathstring]); |
2023
|
|
|
unset($_SESSION['lastsearch_page_'.$relativepathstring]); |
2024
|
|
|
unset($_SESSION['lastsearch_limit_'.$relativepathstring]); |
2025
|
|
|
} |
2026
|
|
|
|
2027
|
|
|
// Core error message |
2028
|
|
|
if (! empty($conf->global->MAIN_CORE_ERROR)) |
2029
|
|
|
{ |
2030
|
|
|
// Ajax version |
2031
|
|
|
if ($conf->use_javascript_ajax) |
2032
|
|
|
{ |
2033
|
|
|
$title = img_warning().' '.$langs->trans('CoreErrorTitle'); |
2034
|
|
|
print ajax_dialog($title, $langs->trans('CoreErrorMessage')); |
|
|
|
|
2035
|
|
|
} |
2036
|
|
|
// html version |
2037
|
|
|
else |
2038
|
|
|
{ |
2039
|
|
|
$msg = img_warning().' '.$langs->trans('CoreErrorMessage'); |
2040
|
|
|
print '<div class="error">'.$msg.'</div>'; |
2041
|
|
|
} |
2042
|
|
|
|
2043
|
|
|
//define("MAIN_CORE_ERROR",0); // Constant was defined and we can't change value of a constant |
2044
|
|
|
} |
2045
|
|
|
|
2046
|
|
|
print "\n\n"; |
2047
|
|
|
|
2048
|
|
|
print '</div> <!-- End div class="fiche" -->'."\n"; // End div fiche |
2049
|
|
|
|
2050
|
|
|
if (empty($conf->dol_hide_leftmenu)) print '</div> <!-- End div id-right -->'."\n"; // End div id-right |
2051
|
|
|
|
2052
|
|
|
if (empty($conf->dol_hide_leftmenu) && empty($conf->dol_use_jmobile)) print '</div> <!-- End div id-container -->'."\n"; // End div container |
2053
|
|
|
|
2054
|
|
|
print "\n"; |
2055
|
|
|
if ($comment) print '<!-- '.$comment.' -->'."\n"; |
2056
|
|
|
|
2057
|
|
|
printCommonFooter($zone); |
2058
|
|
|
|
2059
|
|
|
if (! empty($delayedhtmlcontent)) print $delayedhtmlcontent; |
2060
|
|
|
|
2061
|
|
|
if (! empty($conf->use_javascript_ajax)) |
2062
|
|
|
{ |
2063
|
|
|
print "\n".'<!-- Includes JS Footer of Dolibarr -->'."\n"; |
2064
|
|
|
print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/lib_foot.js.php?lang='.$langs->defaultlang.($ext?'&'.$ext:'').'"></script>'."\n"; |
2065
|
|
|
} |
2066
|
|
|
|
2067
|
|
|
// Wrapper to add log when clicking on download or preview |
2068
|
|
|
if (! empty($conf->blockedlog->enabled) && is_object($object) && $object->id > 0 && $object->statut > 0) |
2069
|
|
|
{ |
2070
|
|
|
if (in_array($object->element, array('facture'))) // Restrict for the moment to element 'facture' |
2071
|
|
|
{ |
2072
|
|
|
print "\n<!-- JS CODE TO ENABLE log when making a download or a preview of a document -->\n"; |
2073
|
|
|
?> |
2074
|
|
|
<script type="text/javascript"> |
2075
|
|
|
jQuery(document).ready(function () { |
2076
|
|
|
$('a.documentpreview').click(function() { |
2077
|
|
|
$.post('<?php echo DOL_URL_ROOT."/blockedlog/ajax/block-add.php" ?>' |
2078
|
|
|
, { |
2079
|
|
|
id:<?php echo $object->id; ?> |
2080
|
|
|
, element:'<?php echo $object->element ?>' |
2081
|
|
|
, action:'DOC_PREVIEW' |
2082
|
|
|
} |
2083
|
|
|
); |
2084
|
|
|
}); |
2085
|
|
|
$('a.documentdownload').click(function() { |
2086
|
|
|
$.post('<?php echo DOL_URL_ROOT."/blockedlog/ajax/block-add.php" ?>' |
2087
|
|
|
, { |
2088
|
|
|
id:<?php echo $object->id; ?> |
2089
|
|
|
, element:'<?php echo $object->element ?>' |
2090
|
|
|
, action:'DOC_DOWNLOAD' |
2091
|
|
|
} |
2092
|
|
|
); |
2093
|
|
|
}); |
2094
|
|
|
}); |
2095
|
|
|
</script> |
2096
|
|
|
<?php |
2097
|
|
|
} |
2098
|
|
|
} |
2099
|
|
|
|
2100
|
|
|
// A div for the address popup |
2101
|
|
|
print "\n<!-- A div to allow dialog popup -->\n"; |
2102
|
|
|
print '<div id="dialogforpopup" style="display: none;"></div>'."\n"; |
2103
|
|
|
|
2104
|
|
|
print "</body>\n"; |
2105
|
|
|
print "</html>\n"; |
2106
|
|
|
} |
2107
|
|
|
} |
2108
|
|
|
|
If you suppress an error, we recommend checking for the error condition explicitly: