main.inc.php 93 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969
  1. <?php
  2. /* Copyright (C) 2002-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2003 Xavier Dutoit <doli@sydesy.com>
  4. * Copyright (C) 2004-2015 Laurent Destailleur <eldy@users.sourceforge.net>
  5. * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
  6. * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
  7. * Copyright (C) 2005-2015 Regis Houssin <regis.houssin@capnetworks.com>
  8. * Copyright (C) 2011-2014 Philippe Grand <philippe.grand@atoo-net.com>
  9. * Copyright (C) 2008 Matteli
  10. * Copyright (C) 2011-2013 Juanjo Menent <jmenent@2byte.es>
  11. * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
  12. * Copyright (C) 2014-2015 Marcos García <marcosgdf@gmail.com>
  13. * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
  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. * \file htdocs/main.inc.php
  30. * \ingroup core
  31. * \brief File that defines environment for Dolibarr pages only (variables not required by scripts)
  32. */
  33. //@ini_set('memory_limit', '64M'); // This may be useless if memory is hard limited by your PHP
  34. // For optional tuning. Enabled if environment variable MAIN_SHOW_TUNING_INFO is defined.
  35. $micro_start_time=0;
  36. if (! empty($_SERVER['MAIN_SHOW_TUNING_INFO']))
  37. {
  38. list($usec, $sec) = explode(" ", microtime());
  39. $micro_start_time=((float) $usec + (float) $sec);
  40. // Add Xdebug code coverage
  41. //define('XDEBUGCOVERAGE',1);
  42. if (defined('XDEBUGCOVERAGE')) {
  43. xdebug_start_code_coverage();
  44. }
  45. }
  46. // Removed magic_quotes
  47. if (function_exists('get_magic_quotes_gpc')) // magic_quotes_* removed in PHP6
  48. {
  49. if (get_magic_quotes_gpc())
  50. {
  51. // Forcing parameter setting magic_quotes_gpc and cleaning parameters
  52. // (Otherwise he would have for each position, condition
  53. // Reading stripslashes variable according to state get_magic_quotes_gpc).
  54. // Off mode recommended (just do $db->escape for insert / update).
  55. function stripslashes_deep($value)
  56. {
  57. return (is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value));
  58. }
  59. $_GET = array_map('stripslashes_deep', $_GET);
  60. $_POST = array_map('stripslashes_deep', $_POST);
  61. $_FILES = array_map('stripslashes_deep', $_FILES);
  62. //$_COOKIE = array_map('stripslashes_deep', $_COOKIE); // Useless because a cookie should never be outputed on screen nor used into sql
  63. @set_magic_quotes_runtime(0);
  64. }
  65. }
  66. /**
  67. * Security: SQL Injection and XSS Injection (scripts) protection (Filters on GET, POST, PHP_SELF).
  68. *
  69. * @param string $val Value
  70. * @param string $type 1=GET, 0=POST, 2=PHP_SELF
  71. * @return int >0 if there is an injection
  72. */
  73. function test_sql_and_script_inject($val, $type)
  74. {
  75. $sql_inj = 0;
  76. // For SQL Injection (only GET and POST are used to be included into bad escaped SQL requests)
  77. if ($type != 2)
  78. {
  79. $sql_inj += preg_match('/delete\s+from/i', $val);
  80. $sql_inj += preg_match('/create\s+table/i', $val);
  81. $sql_inj += preg_match('/update.+set.+=/i', $val);
  82. $sql_inj += preg_match('/insert\s+into/i', $val);
  83. $sql_inj += preg_match('/select.+from/i', $val);
  84. $sql_inj += preg_match('/union.+select/i', $val);
  85. $sql_inj += preg_match('/into\s+(outfile|dumpfile)/i', $val);
  86. $sql_inj += preg_match('/(\.\.%2f)+/i', $val);
  87. $sql_inj += preg_match('/onerror=/i', $val);
  88. }
  89. // For XSS Injection done by adding javascript with script
  90. // This is all cases a browser consider text is javascript:
  91. // When it found '<script', 'javascript:', '<style', 'onload\s=' on body tag, '="&' on a tag size with old browsers
  92. // All examples on page: http://ha.ckers.org/xss.html#XSScalc
  93. $sql_inj += preg_match('/<script/i', $val);
  94. if (! defined('NOSTYLECHECK')) $sql_inj += preg_match('/<style/i', $val);
  95. $sql_inj += preg_match('/base[\s]+href/si', $val);
  96. $sql_inj += preg_match('/<.*onmouse/si', $val); // onmouseover can be set on img or any html tag like <img title='>' onmouseover=alert(1)>
  97. if ($type == 1)
  98. {
  99. $sql_inj += preg_match('/javascript:/i', $val);
  100. $sql_inj += preg_match('/vbscript:/i', $val);
  101. }
  102. // For XSS Injection done by adding javascript closing html tags like with onmousemove, etc... (closing a src or href tag with not cleaned param)
  103. if ($type == 1) $sql_inj += preg_match('/"/i', $val); // We refused " in GET parameters value
  104. if ($type == 2) $sql_inj += preg_match('/[;"]/', $val); // PHP_SELF is a file system path. It can contains spaces.
  105. return $sql_inj;
  106. }
  107. /**
  108. * Return true if security check on parameters are OK, false otherwise.
  109. *
  110. * @param string $var Variable name
  111. * @param string $type 1=GET, 0=POST, 2=PHP_SELF
  112. * @return boolean||null true if there is an injection. Stop code if injection found.
  113. */
  114. function analyseVarsForSqlAndScriptsInjection(&$var, $type)
  115. {
  116. if (is_array($var))
  117. {
  118. foreach ($var as $key => $value)
  119. {
  120. if (analyseVarsForSqlAndScriptsInjection($value,$type))
  121. {
  122. $var[$key] = $value;
  123. }
  124. else
  125. {
  126. 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"]).')';
  127. exit;
  128. }
  129. }
  130. return true;
  131. }
  132. else
  133. {
  134. return (test_sql_and_script_inject($var,$type) <= 0);
  135. }
  136. }
  137. // Check consistency of NOREQUIREXXX DEFINES
  138. if ((defined('NOREQUIREDB') || defined('NOREQUIRETRAN')) && ! defined('NOREQUIREMENU')) dol_print_error('','If define NOREQUIREDB or NOREQUIRETRAN are set, you must also set NOREQUIREMENU or not use them');
  139. // Sanity check on URL
  140. if (! empty($_SERVER["PHP_SELF"]))
  141. {
  142. $morevaltochecklikepost=array($_SERVER["PHP_SELF"]);
  143. analyseVarsForSqlAndScriptsInjection($morevaltochecklikepost,2);
  144. }
  145. // Sanity check on GET parameters
  146. if (! defined('NOSCANGETFORINJECTION') && ! empty($_SERVER["QUERY_STRING"]))
  147. {
  148. $morevaltochecklikeget=array($_SERVER["QUERY_STRING"]);
  149. analyseVarsForSqlAndScriptsInjection($morevaltochecklikeget,1);
  150. }
  151. // Sanity check on POST
  152. if (! defined('NOSCANPOSTFORINJECTION'))
  153. {
  154. analyseVarsForSqlAndScriptsInjection($_POST,0);
  155. }
  156. // This is to make Dolibarr working with Plesk
  157. if (! empty($_SERVER['DOCUMENT_ROOT']) && substr($_SERVER['DOCUMENT_ROOT'], -6) !== 'htdocs')
  158. {
  159. set_include_path($_SERVER['DOCUMENT_ROOT'] . '/htdocs');
  160. }
  161. // Include the conf.php and functions.lib.php
  162. require_once 'filefunc.inc.php';
  163. // If there is a POST parameter to tell to save automatically some POST parameters into a cookies, we do it
  164. if (! empty($_POST["DOL_AUTOSET_COOKIE"]))
  165. {
  166. $tmpautoset=explode(':',$_POST["DOL_AUTOSET_COOKIE"],2);
  167. $tmplist=explode(',',$tmpautoset[1]);
  168. $cookiearrayvalue='';
  169. foreach ($tmplist as $tmpkey)
  170. {
  171. $postkey=$tmpautoset[0].'_'.$tmpkey;
  172. //var_dump('tmpkey='.$tmpkey.' postkey='.$postkey.' value='.$_POST[$postkey]);
  173. if (! empty($_POST[$postkey])) $cookiearrayvalue[$tmpkey]=$_POST[$postkey];
  174. }
  175. $cookiename=$tmpautoset[0];
  176. $cookievalue=json_encode($cookiearrayvalue);
  177. //var_dump('setcookie cookiename='.$cookiename.' cookievalue='.$cookievalue);
  178. setcookie($cookiename, empty($cookievalue)?'':$cookievalue, empty($cookievalue)?0:(time()+(86400*354)), '/'); // keep cookie 1 year
  179. if (empty($cookievalue)) unset($_COOKIE[$cookiename]);
  180. }
  181. // Init session. Name of session is specific to Dolibarr instance.
  182. $prefix=dol_getprefix();
  183. $sessionname='DOLSESSID_'.$prefix;
  184. $sessiontimeout='DOLSESSTIMEOUT_'.$prefix;
  185. if (! empty($_COOKIE[$sessiontimeout])) ini_set('session.gc_maxlifetime',$_COOKIE[$sessiontimeout]);
  186. session_name($sessionname);
  187. session_start();
  188. if (ini_get('register_globals')) // To solve bug in using $_SESSION
  189. {
  190. foreach ($_SESSION as $key=>$value)
  191. {
  192. if (isset($GLOBALS[$key])) unset($GLOBALS[$key]);
  193. }
  194. }
  195. // Init the 5 global objects
  196. // This include will set: $conf, $db, $langs, $user, $mysoc objects
  197. require_once 'master.inc.php';
  198. // Activate end of page function
  199. register_shutdown_function('dol_shutdown');
  200. // Detection browser
  201. if (isset($_SERVER["HTTP_USER_AGENT"]))
  202. {
  203. $tmp=getBrowserInfo($_SERVER["HTTP_USER_AGENT"]);
  204. $conf->browser->name=$tmp['browsername'];
  205. $conf->browser->os=$tmp['browseros'];
  206. $conf->browser->version=$tmp['browserversion'];
  207. $conf->browser->layout=$tmp['layout']; // 'classic', 'phone', 'tablet'
  208. $conf->browser->phone=$tmp['phone']; // deprecated, use layout
  209. $conf->browser->tablet=$tmp['tablet']; // deprecated, use layout
  210. //var_dump($conf->browser);
  211. }
  212. // Force HTTPS if required ($conf->file->main_force_https is 0/1 or https dolibarr root url)
  213. // $_SERVER["HTTPS"] is 'on' when link is https, otherwise $_SERVER["HTTPS"] is empty or 'off'
  214. if (! empty($conf->file->main_force_https) && (empty($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] != 'on'))
  215. {
  216. $newurl='';
  217. if (is_numeric($conf->file->main_force_https))
  218. {
  219. if ($conf->file->main_force_https == '1' && ! empty($_SERVER["SCRIPT_URI"])) // If SCRIPT_URI supported by server
  220. {
  221. if (preg_match('/^http:/i',$_SERVER["SCRIPT_URI"]) && ! preg_match('/^https:/i',$_SERVER["SCRIPT_URI"])) // If link is http
  222. {
  223. $newurl=preg_replace('/^http:/i','https:',$_SERVER["SCRIPT_URI"]);
  224. }
  225. }
  226. else // Check HTTPS environment variable (Apache/mod_ssl only)
  227. {
  228. $newurl=preg_replace('/^http:/i','https:',DOL_MAIN_URL_ROOT).$_SERVER["REQUEST_URI"];
  229. }
  230. }
  231. else
  232. {
  233. // Check HTTPS environment variable (Apache/mod_ssl only)
  234. $newurl=$conf->file->main_force_https.$_SERVER["REQUEST_URI"];
  235. }
  236. // Start redirect
  237. if ($newurl)
  238. {
  239. dol_syslog("main.inc: dolibarr_main_force_https is on, we make a redirect to ".$newurl);
  240. header("Location: ".$newurl);
  241. exit;
  242. }
  243. else
  244. {
  245. 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);
  246. }
  247. }
  248. // Loading of additional presentation includes
  249. if (! defined('NOREQUIREHTML')) require_once DOL_DOCUMENT_ROOT .'/core/class/html.form.class.php'; // Need 660ko memory (800ko in 2.2)
  250. if (! defined('NOREQUIREAJAX') && $conf->use_javascript_ajax) require_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; // Need 22ko memory
  251. // If install or upgrade process not done or not completely finished, we call the install page.
  252. if (! empty($conf->global->MAIN_NOT_INSTALLED) || ! empty($conf->global->MAIN_NOT_UPGRADED))
  253. {
  254. dol_syslog("main.inc: A previous install or upgrade was not complete. Redirect to install page.", LOG_WARNING);
  255. header("Location: ".DOL_URL_ROOT."/install/index.php");
  256. exit;
  257. }
  258. // If an upgrade process is required, we call the install page.
  259. if ((! empty($conf->global->MAIN_VERSION_LAST_UPGRADE) && ($conf->global->MAIN_VERSION_LAST_UPGRADE != DOL_VERSION))
  260. || (empty($conf->global->MAIN_VERSION_LAST_UPGRADE) && ! empty($conf->global->MAIN_VERSION_LAST_INSTALL) && ($conf->global->MAIN_VERSION_LAST_INSTALL != DOL_VERSION)))
  261. {
  262. $versiontocompare=empty($conf->global->MAIN_VERSION_LAST_UPGRADE)?$conf->global->MAIN_VERSION_LAST_INSTALL:$conf->global->MAIN_VERSION_LAST_UPGRADE;
  263. require_once DOL_DOCUMENT_ROOT .'/core/lib/admin.lib.php';
  264. $dolibarrversionlastupgrade=preg_split('/[.-]/',$versiontocompare);
  265. $dolibarrversionprogram=preg_split('/[.-]/',DOL_VERSION);
  266. $rescomp=versioncompare($dolibarrversionprogram,$dolibarrversionlastupgrade);
  267. if ($rescomp > 0) // Programs have a version higher than database. We did not add "&& $rescomp < 3" because we want upgrade process for build upgrades
  268. {
  269. dol_syslog("main.inc: database version ".$versiontocompare." is lower than programs version ".DOL_VERSION.". Redirect to install page.", LOG_WARNING);
  270. header("Location: ".DOL_URL_ROOT."/install/index.php");
  271. exit;
  272. }
  273. }
  274. // Creation of a token against CSRF vulnerabilities
  275. if (! defined('NOTOKENRENEWAL'))
  276. {
  277. $token = dol_hash(uniqid(mt_rand(),TRUE)); // Generates a hash of a random number
  278. // roulement des jetons car cree a chaque appel
  279. if (isset($_SESSION['newtoken'])) $_SESSION['token'] = $_SESSION['newtoken'];
  280. $_SESSION['newtoken'] = $token;
  281. }
  282. if (! empty($conf->global->MAIN_SECURITY_CSRF)) // Check validity of token, only if option enabled (this option breaks some features sometimes)
  283. {
  284. if (isset($_POST['token']) && isset($_SESSION['token']))
  285. {
  286. if (($_POST['token'] != $_SESSION['token']))
  287. {
  288. dol_syslog("Invalid token in ".$_SERVER['HTTP_REFERER'].", action=".GETPOST('action').", _POST['token']=".GETPOST('token').", _SESSION['token']=".$_SESSION['token'],LOG_WARNING);
  289. //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.
  290. unset($_POST);
  291. }
  292. }
  293. }
  294. // Disable modules (this must be after session_start and after conf has been loaded)
  295. if (GETPOST('disablemodules')) $_SESSION["disablemodules"]=GETPOST('disablemodules');
  296. if (! empty($_SESSION["disablemodules"]))
  297. {
  298. $disabled_modules=explode(',',$_SESSION["disablemodules"]);
  299. foreach($disabled_modules as $module)
  300. {
  301. if ($module)
  302. {
  303. if (empty($conf->$module)) $conf->$module=new stdClass();
  304. $conf->$module->enabled=false;
  305. }
  306. }
  307. }
  308. /*
  309. * Phase authentication / login
  310. */
  311. $login='';
  312. if (! defined('NOLOGIN'))
  313. {
  314. // $authmode lists the different means of identification to be tested in order of preference.
  315. // Example: 'http', 'dolibarr', 'ldap', 'http,forceuser'
  316. // Authentication mode
  317. if (empty($dolibarr_main_authentication)) $dolibarr_main_authentication='http,dolibarr';
  318. // Authentication mode: forceuser
  319. if ($dolibarr_main_authentication == 'forceuser' && empty($dolibarr_auto_user)) $dolibarr_auto_user='auto';
  320. // Set authmode
  321. $authmode=explode(',',$dolibarr_main_authentication);
  322. // No authentication mode
  323. if (! count($authmode))
  324. {
  325. $langs->load('main');
  326. dol_print_error('',$langs->trans("ErrorConfigParameterNotDefined",'dolibarr_main_authentication'));
  327. exit;
  328. }
  329. // If login request was already post, we retrieve login from the session
  330. // Call module if not realized that his request.
  331. // At the end of this phase, the variable $login is defined.
  332. $resultFetchUser='';
  333. $test=true;
  334. if (! isset($_SESSION["dol_login"]))
  335. {
  336. // It is not already authenticated and it requests the login / password
  337. include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
  338. $dol_dst_observed=GETPOST("dst_observed",'int',3);
  339. $dol_dst_first=GETPOST("dst_first",'int',3);
  340. $dol_dst_second=GETPOST("dst_second",'int',3);
  341. $dol_screenwidth=GETPOST("screenwidth",'int',3);
  342. $dol_screenheight=GETPOST("screenheight",'int',3);
  343. $dol_hide_topmenu=GETPOST('dol_hide_topmenu','int',3);
  344. $dol_hide_leftmenu=GETPOST('dol_hide_leftmenu','int',3);
  345. $dol_optimize_smallscreen=GETPOST('dol_optimize_smallscreen','int',3);
  346. $dol_no_mouse_hover=GETPOST('dol_no_mouse_hover','int',3);
  347. $dol_use_jmobile=GETPOST('dol_use_jmobile','int',3);
  348. //dol_syslog("POST key=".join(array_keys($_POST),',').' value='.join($_POST,','));
  349. // If in demo mode, we check we go to home page through the public/demo/index.php page
  350. if (! empty($dolibarr_main_demo) && $_SERVER['PHP_SELF'] == DOL_URL_ROOT.'/index.php') // We ask index page
  351. {
  352. if (empty($_SERVER['HTTP_REFERER']) || ! preg_match('/public/',$_SERVER['HTTP_REFERER']))
  353. {
  354. dol_syslog("Call index page from another url than demo page");
  355. $url='';
  356. $url.=($url?'&':'').($dol_hide_topmenu?'dol_hide_topmenu='.$dol_hide_topmenu:'');
  357. $url.=($url?'&':'').($dol_hide_leftmenu?'dol_hide_leftmenu='.$dol_hide_leftmenu:'');
  358. $url.=($url?'&':'').($dol_optimize_smallscreen?'dol_optimize_smallscreen='.$dol_optimize_smallscreen:'');
  359. $url.=($url?'&':'').($dol_no_mouse_hover?'dol_no_mouse_hover='.$dol_no_mouse_hover:'');
  360. $url.=($url?'&':'').($dol_use_jmobile?'dol_use_jmobile='.$dol_use_jmobile:'');
  361. $url=DOL_URL_ROOT.'/public/demo/index.php'.($url?'?'.$url:'');
  362. header("Location: ".$url);
  363. exit;
  364. }
  365. }
  366. // Verification security graphic code
  367. if (GETPOST("username","alpha",2) && ! empty($conf->global->MAIN_SECURITY_ENABLECAPTCHA))
  368. {
  369. $sessionkey = 'dol_antispam_value';
  370. $ok=(array_key_exists($sessionkey, $_SESSION) === TRUE && (strtolower($_SESSION[$sessionkey]) == strtolower($_POST['code'])));
  371. // Check code
  372. if (! $ok)
  373. {
  374. dol_syslog('Bad value for code, connexion refused');
  375. $langs->load('main');
  376. $langs->load('errors');
  377. $_SESSION["dol_loginmesg"]=$langs->trans("ErrorBadValueForCode");
  378. $test=false;
  379. // TODO @deprecated Remove this. Hook must be used, not this trigger.
  380. $user->trigger_mesg='ErrorBadValueForCode - login='.GETPOST("username","alpha",2);
  381. // Call of triggers
  382. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  383. $interface=new Interfaces($db);
  384. $result=$interface->run_triggers('USER_LOGIN_FAILED',$user,$user,$langs,$conf);
  385. if ($result < 0) {
  386. $error++;
  387. }
  388. // End Call of triggers
  389. // Hooks on failed login
  390. $action='';
  391. $hookmanager->initHooks(array('login'));
  392. $parameters=array('dol_authmode'=>$dol_authmode, 'dol_loginmesg'=>$_SESSION["dol_loginmesg"]);
  393. $reshook=$hookmanager->executeHooks('afterLoginFailed',$parameters,$user,$action); // Note that $action and $object may have been modified by some hooks
  394. if ($reshook < 0) $error++;
  395. // Note: exit is done later
  396. }
  397. }
  398. $usertotest = (! empty($_COOKIE['login_dolibarr']) ? $_COOKIE['login_dolibarr'] : GETPOST("username","alpha",2));
  399. $passwordtotest = (! empty($_COOKIE['password_dolibarr']) ? $_COOKIE['password_dolibarr'] : GETPOST('password'));
  400. $entitytotest = (GETPOST('entity','int') ? GETPOST('entity','int') : (!empty($conf->entity) ? $conf->entity : 1));
  401. // Validation of login/pass/entity
  402. // If ok, the variable login will be returned
  403. // If error, we will put error message in session under the name dol_loginmesg
  404. $goontestloop=false;
  405. if (isset($_SERVER["REMOTE_USER"]) && in_array('http',$authmode)) $goontestloop=true;
  406. if ($dolibarr_main_authentication == 'forceuser' && ! empty($dolibarr_auto_user)) $goontestloop=true;
  407. if (GETPOST("username","alpha",2) || ! empty($_COOKIE['login_dolibarr']) || GETPOST('openid_mode','alpha',1)) $goontestloop=true;
  408. if (! is_object($langs)) // This can occurs when calling page with NOREQUIRETRAN defined, however we need langs for error messages.
  409. {
  410. include_once DOL_DOCUMENT_ROOT.'/core/class/translate.class.php';
  411. $langs=new Translate("",$conf);
  412. $langcode=(GETPOST('lang')?GETPOST('lang','alpha',1):(empty($conf->global->MAIN_LANG_DEFAULT)?'auto':$conf->global->MAIN_LANG_DEFAULT));
  413. $langs->setDefaultLang($langcode);
  414. }
  415. if ($test && $goontestloop)
  416. {
  417. $login = checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode);
  418. if ($login)
  419. {
  420. $dol_authmode=$conf->authmode; // This properties is defined only when logged, to say what mode was successfully used
  421. $dol_tz=$_POST["tz"];
  422. $dol_tz_string=$_POST["tz_string"];
  423. $dol_tz_string=preg_replace('/\s*\(.+\)$/','',$dol_tz_string);
  424. $dol_tz_string=preg_replace('/,/','/',$dol_tz_string);
  425. $dol_tz_string=preg_replace('/\s/','_',$dol_tz_string);
  426. $dol_dst=0;
  427. if (isset($_POST["dst_first"]) && isset($_POST["dst_second"]))
  428. {
  429. include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
  430. $datenow=dol_now();
  431. $datefirst=dol_stringtotime($_POST["dst_first"]);
  432. $datesecond=dol_stringtotime($_POST["dst_second"]);
  433. if ($datenow >= $datefirst && $datenow < $datesecond) $dol_dst=1;
  434. }
  435. //print $datefirst.'-'.$datesecond.'-'.$datenow.'-'.$dol_tz.'-'.$dol_tzstring.'-'.$dol_dst; exit;
  436. }
  437. if (! $login)
  438. {
  439. dol_syslog('Bad password, connexion refused',LOG_DEBUG);
  440. $langs->load('main');
  441. $langs->load('errors');
  442. // Bad password. No authmode has found a good password.
  443. // We set a generic message if not defined inside function checkLoginPassEntity or subfunctions
  444. if (empty($_SESSION["dol_loginmesg"])) $_SESSION["dol_loginmesg"]=$langs->trans("ErrorBadLoginPassword");
  445. // TODO @deprecated Remove this. Hook must be used, not this trigger.
  446. $user->trigger_mesg=$langs->trans("ErrorBadLoginPassword").' - login='.GETPOST("username","alpha",2);
  447. // Call of triggers
  448. include_once DOL_DOCUMENT_ROOT.'/core/class/interfaces.class.php';
  449. $interface=new Interfaces($db);
  450. $result=$interface->run_triggers('USER_LOGIN_FAILED',$user,$user,$langs,$conf,GETPOST("username","alpha",2));
  451. if ($result < 0) {
  452. $error++;
  453. }
  454. // End Call of triggers
  455. // Hooks on failed login
  456. $action='';
  457. $hookmanager->initHooks(array('login'));
  458. $parameters=array('dol_authmode'=>$dol_authmode, 'dol_loginmesg'=>$_SESSION["dol_loginmesg"]);
  459. $reshook=$hookmanager->executeHooks('afterLoginFailed',$parameters,$user,$action); // Note that $action and $object may have been modified by some hooks
  460. if ($reshook < 0) $error++;
  461. // Note: exit is done in next chapter
  462. }
  463. }
  464. // End test login / passwords
  465. 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.
  466. {
  467. // We show login page
  468. dol_syslog("--- Access to ".$_SERVER["PHP_SELF"]." showing the login form and exit");
  469. dol_loginfunction($langs,$conf,(! empty($mysoc)?$mysoc:''));
  470. exit;
  471. }
  472. $resultFetchUser=$user->fetch('', $login, '', 1, ($entitytotest ? $entitytotest : -1));
  473. if ($resultFetchUser <= 0)
  474. {
  475. dol_syslog('User not found, connexion refused');
  476. session_destroy();
  477. session_name($sessionname);
  478. session_start(); // Fixing the bug of register_globals here is useless since session is empty
  479. if ($resultFetchUser == 0)
  480. {
  481. $langs->load('main');
  482. $langs->load('errors');
  483. $_SESSION["dol_loginmesg"]=$langs->trans("ErrorCantLoadUserFromDolibarrDatabase",$login);
  484. // TODO @deprecated Remove this. Hook must be used, not this trigger.
  485. $user->trigger_mesg='ErrorCantLoadUserFromDolibarrDatabase - login='.$login;
  486. }
  487. if ($resultFetchUser < 0)
  488. {
  489. $_SESSION["dol_loginmesg"]=$user->error;
  490. // TODO @deprecated Remove this. Hook must be used, not this trigger.
  491. $user->trigger_mesg=$user->error;
  492. }
  493. // Call triggers
  494. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  495. $interface=new Interfaces($db);
  496. $result=$interface->run_triggers('USER_LOGIN_FAILED',$user,$user,$langs,$conf);
  497. if ($result < 0) {
  498. $error++;
  499. }
  500. // End call triggers
  501. // Hooks on failed login
  502. $action='';
  503. $hookmanager->initHooks(array('login'));
  504. $parameters=array('dol_authmode'=>$dol_authmode, 'dol_loginmesg'=>$_SESSION["dol_loginmesg"]);
  505. $reshook=$hookmanager->executeHooks('afterLoginFailed',$parameters,$user,$action); // Note that $action and $object may have been modified by some hooks
  506. if ($reshook < 0) $error++;
  507. header('Location: '.DOL_URL_ROOT.'/index.php');
  508. exit;
  509. }
  510. }
  511. else
  512. {
  513. // We are already into an authenticated session
  514. $login=$_SESSION["dol_login"];
  515. dol_syslog("This is an already logged session. _SESSION['dol_login']=".$login, LOG_DEBUG);
  516. $resultFetchUser=$user->fetch('',$login);
  517. if ($resultFetchUser <= 0)
  518. {
  519. // Account has been removed after login
  520. dol_syslog("Can't load user even if session logged. _SESSION['dol_login']=".$login, LOG_WARNING);
  521. session_destroy();
  522. session_name($sessionname);
  523. session_start(); // Fixing the bug of register_globals here is useless since session is empty
  524. if ($resultFetchUser == 0)
  525. {
  526. $langs->load('main');
  527. $langs->load('errors');
  528. $_SESSION["dol_loginmesg"]=$langs->trans("ErrorCantLoadUserFromDolibarrDatabase",$login);
  529. // TODO @deprecated Remove this. Hook must be used, not this trigger.
  530. $user->trigger_mesg='ErrorCantLoadUserFromDolibarrDatabase - login='.$login;
  531. }
  532. if ($resultFetchUser < 0)
  533. {
  534. $_SESSION["dol_loginmesg"]=$user->error;
  535. // TODO @deprecated Remove this. Hook must be used, not this trigger.
  536. $user->trigger_mesg=$user->error;
  537. }
  538. // TODO @deprecated Remove this. Hook must be used, not this trigger.
  539. // Call triggers
  540. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  541. $interface=new Interfaces($db);
  542. $result=$interface->run_triggers('USER_LOGIN_FAILED',$user,$user,$langs,$conf);
  543. if ($result < 0) {
  544. $error++;
  545. }
  546. // End call triggers
  547. // Hooks on failed login
  548. $action='';
  549. $hookmanager->initHooks(array('login'));
  550. $parameters=array('dol_authmode'=>$dol_authmode, 'dol_loginmesg'=>$_SESSION["dol_loginmesg"]);
  551. $reshook=$hookmanager->executeHooks('afterLoginFailed',$parameters,$user,$action); // Note that $action and $object may have been modified by some hooks
  552. if ($reshook < 0) $error++;
  553. header('Location: '.DOL_URL_ROOT.'/index.php');
  554. exit;
  555. }
  556. else
  557. {
  558. // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
  559. $hookmanager->initHooks(array('main'));
  560. $action = '';
  561. $reshook = $hookmanager->executeHooks('updateSession', array(), $user, $action);
  562. if ($reshook < 0) {
  563. setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  564. }
  565. }
  566. }
  567. // Is it a new session that has started ?
  568. // If we are here, this means authentication was successfull.
  569. if (! isset($_SESSION["dol_login"]))
  570. {
  571. // New session for this login has started.
  572. $error=0;
  573. // Store value into session (values always stored)
  574. $_SESSION["dol_login"]=$user->login;
  575. $_SESSION["dol_authmode"]=isset($dol_authmode)?$dol_authmode:'';
  576. $_SESSION["dol_tz"]=isset($dol_tz)?$dol_tz:'';
  577. $_SESSION["dol_tz_string"]=isset($dol_tz_string)?$dol_tz_string:'';
  578. $_SESSION["dol_dst"]=isset($dol_dst)?$dol_dst:'';
  579. $_SESSION["dol_dst_observed"]=isset($dol_dst_observed)?$dol_dst_observed:'';
  580. $_SESSION["dol_dst_first"]=isset($dol_dst_first)?$dol_dst_first:'';
  581. $_SESSION["dol_dst_second"]=isset($dol_dst_second)?$dol_dst_second:'';
  582. $_SESSION["dol_screenwidth"]=isset($dol_screenwidth)?$dol_screenwidth:'';
  583. $_SESSION["dol_screenheight"]=isset($dol_screenheight)?$dol_screenheight:'';
  584. $_SESSION["dol_company"]=$conf->global->MAIN_INFO_SOCIETE_NOM;
  585. $_SESSION["dol_entity"]=$conf->entity;
  586. // Store value into session (values stored only if defined)
  587. if (! empty($dol_hide_topmenu)) $_SESSION['dol_hide_topmenu']=$dol_hide_topmenu;
  588. if (! empty($dol_hide_leftmenu)) $_SESSION['dol_hide_leftmenu']=$dol_hide_leftmenu;
  589. if (! empty($dol_optimize_smallscreen)) $_SESSION['dol_optimize_smallscreen']=$dol_optimize_smallscreen;
  590. if (! empty($dol_no_mouse_hover)) $_SESSION['dol_no_mouse_hover']=$dol_no_mouse_hover;
  591. if (! empty($dol_use_jmobile)) $_SESSION['dol_use_jmobile']=$dol_use_jmobile;
  592. dol_syslog("This is a new started user session. _SESSION['dol_login']=".$_SESSION["dol_login"]." Session id=".session_id());
  593. $db->begin();
  594. $user->update_last_login_date();
  595. $loginfo = 'TZ='.$_SESSION["dol_tz"].';TZString='.$_SESSION["dol_tz_string"].';Screen='.$_SESSION["dol_screenwidth"].'x'.$_SESSION["dol_screenheight"];
  596. // TODO @deprecated Remove this. Hook must be used, not this trigger.
  597. $user->trigger_mesg = $loginfo;
  598. // Call triggers
  599. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  600. $interface=new Interfaces($db);
  601. $result=$interface->run_triggers('USER_LOGIN',$user,$user,$langs,$conf);
  602. if ($result < 0) {
  603. $error++;
  604. }
  605. // End call triggers
  606. // Hooks on successfull login
  607. $action='';
  608. $hookmanager->initHooks(array('login'));
  609. $parameters=array('dol_authmode'=>$dol_authmode, 'dol_loginfo'=>$loginfo);
  610. $reshook=$hookmanager->executeHooks('afterLogin',$parameters,$user,$action); // Note that $action and $object may have been modified by some hooks
  611. if ($reshook < 0) $error++;
  612. if ($error)
  613. {
  614. $db->rollback();
  615. session_destroy();
  616. dol_print_error($db,'Error in some hooks afterLogin (or old trigger USER_LOGIN)');
  617. exit;
  618. }
  619. else
  620. {
  621. $db->commit();
  622. }
  623. // Change landing page if defined.
  624. $landingpage=(empty($user->conf->MAIN_LANDING_PAGE)?(empty($conf->global->MAIN_LANDING_PAGE)?'':$conf->global->MAIN_LANDING_PAGE):$user->conf->MAIN_LANDING_PAGE);
  625. if (! empty($landingpage)) // Example: /index.php
  626. {
  627. $newpath=dol_buildpath($landingpage, 1);
  628. if ($_SERVER["PHP_SELF"] != $newpath) // not already on landing page (avoid infinite loop)
  629. {
  630. header('Location: '.$newpath);
  631. exit;
  632. }
  633. }
  634. }
  635. // If user admin, we force the rights-based modules
  636. if ($user->admin)
  637. {
  638. $user->rights->user->user->lire=1;
  639. $user->rights->user->user->creer=1;
  640. $user->rights->user->user->password=1;
  641. $user->rights->user->user->supprimer=1;
  642. $user->rights->user->self->creer=1;
  643. $user->rights->user->self->password=1;
  644. }
  645. /*
  646. * Overwrite configs global by personal configs
  647. */
  648. // Set liste_limit
  649. if (isset($user->conf->MAIN_SIZE_LISTE_LIMIT)) $conf->liste_limit = $user->conf->MAIN_SIZE_LISTE_LIMIT; // Can be 0
  650. if (isset($user->conf->PRODUIT_LIMIT_SIZE)) $conf->product->limit_size = $user->conf->PRODUIT_LIMIT_SIZE; // Can be 0
  651. // Replace conf->css by personalized value if theme not forced
  652. if (empty($conf->global->MAIN_FORCETHEME) && ! empty($user->conf->MAIN_THEME))
  653. {
  654. $conf->theme=$user->conf->MAIN_THEME;
  655. $conf->css = "/theme/".$conf->theme."/style.css.php";
  656. }
  657. }
  658. // Case forcing style from url
  659. if (GETPOST('theme'))
  660. {
  661. $conf->theme=GETPOST('theme','alpha',1);
  662. $conf->css = "/theme/".$conf->theme."/style.css.php";
  663. }
  664. // Set javascript option
  665. if (! GETPOST('nojs')) // If javascript was not disabled on URL
  666. {
  667. if (! empty($user->conf->MAIN_DISABLE_JAVASCRIPT))
  668. {
  669. $conf->use_javascript_ajax=! $user->conf->MAIN_DISABLE_JAVASCRIPT;
  670. }
  671. }
  672. else $conf->use_javascript_ajax=0;
  673. // Set terminal output option according to conf->browser.
  674. if (GETPOST('dol_hide_leftmenu') || ! empty($_SESSION['dol_hide_leftmenu'])) $conf->dol_hide_leftmenu=1;
  675. if (GETPOST('dol_hide_topmenu') || ! empty($_SESSION['dol_hide_topmenu'])) $conf->dol_hide_topmenu=1;
  676. if (GETPOST('dol_optimize_smallscreen') || ! empty($_SESSION['dol_optimize_smallscreen'])) $conf->dol_optimize_smallscreen=1;
  677. if (GETPOST('dol_no_mouse_hover') || ! empty($_SESSION['dol_no_mouse_hover'])) $conf->dol_no_mouse_hover=1;
  678. if (GETPOST('dol_use_jmobile') || ! empty($_SESSION['dol_use_jmobile'])) $conf->dol_use_jmobile=1;
  679. if (! empty($conf->browser->layout) && $conf->browser->layout != 'classic') $conf->dol_no_mouse_hover=1;
  680. if ((! empty($conf->browser->layout) && $conf->browser->layout == 'phone')
  681. || (! empty($_SESSION['dol_screenwidth']) && $_SESSION['dol_screenwidth'] < 400)
  682. || (! empty($_SESSION['dol_screenheight']) && $_SESSION['dol_screenheight'] < 400)
  683. )
  684. {
  685. $conf->dol_optimize_smallscreen=1;
  686. }
  687. // If we force to use jmobile, then we reenable javascript
  688. if (! empty($conf->dol_use_jmobile)) $conf->use_javascript_ajax=1;
  689. // Replace themes bugged with jmobile with eldy
  690. if (! empty($conf->dol_use_jmobile) && in_array($conf->theme,array('bureau2crea','cameleo','amarok')))
  691. {
  692. $conf->theme='eldy';
  693. $conf->css = "/theme/".$conf->theme."/style.css.php";
  694. }
  695. //var_dump($conf->browser->phone);
  696. if (! defined('NOREQUIRETRAN'))
  697. {
  698. if (! GETPOST('lang')) // If language was not forced on URL
  699. {
  700. // If user has chosen its own language
  701. if (! empty($user->conf->MAIN_LANG_DEFAULT))
  702. {
  703. // If different than current language
  704. //print ">>>".$langs->getDefaultLang()."-".$user->conf->MAIN_LANG_DEFAULT;
  705. if ($langs->getDefaultLang() != $user->conf->MAIN_LANG_DEFAULT)
  706. {
  707. $langs->setDefaultLang($user->conf->MAIN_LANG_DEFAULT);
  708. }
  709. }
  710. }
  711. }
  712. if (! defined('NOLOGIN'))
  713. {
  714. // If the login is not recovered, it is identified with an account that does not exist.
  715. // Hacking attempt?
  716. if (! $user->login) accessforbidden();
  717. // Check if user is active
  718. if ($user->statut < 1)
  719. {
  720. // If not active, we refuse the user
  721. $langs->load("other");
  722. dol_syslog("Authentification ko as login is disabled");
  723. accessforbidden($langs->trans("ErrorLoginDisabled"));
  724. exit;
  725. }
  726. // Load permissions
  727. $user->getrights();
  728. }
  729. dol_syslog("--- Access to ".$_SERVER["PHP_SELF"]);
  730. //Another call for easy debugg
  731. //dol_syslog("Access to ".$_SERVER["PHP_SELF"].' GET='.join(',',array_keys($_GET)).'->'.join(',',$_GET).' POST:'.join(',',array_keys($_POST)).'->'.join(',',$_POST));
  732. // Load main languages files
  733. if (! defined('NOREQUIRETRAN'))
  734. {
  735. $langs->load("main");
  736. $langs->load("dict");
  737. }
  738. // Define some constants used for style of arrays
  739. $bc=array(0=>'class="impair"',1=>'class="pair"');
  740. $bcdd=array(0=>'class="impair drag drop"',1=>'class="pair drag drop"');
  741. $bcnd=array(0=>'class="impair nodrag nodrop nohover"',1=>'class="pair nodrag nodrop nohoverpair"'); // Used for tr to add new lines
  742. // Define messages variables
  743. $mesg=''; $warning=''; $error=0;
  744. // deprecated, see setEventMessages() and dol_htmloutput_events()
  745. $mesgs=array(); $warnings=array(); $errors=array();
  746. // Constants used to defined number of lines in textarea
  747. if (empty($conf->browser->firefox))
  748. {
  749. define('ROWS_1',1);
  750. define('ROWS_2',2);
  751. define('ROWS_3',3);
  752. define('ROWS_4',4);
  753. define('ROWS_5',5);
  754. define('ROWS_6',6);
  755. define('ROWS_7',7);
  756. define('ROWS_8',8);
  757. define('ROWS_9',9);
  758. }
  759. else
  760. {
  761. define('ROWS_1',0);
  762. define('ROWS_2',1);
  763. define('ROWS_3',2);
  764. define('ROWS_4',3);
  765. define('ROWS_5',4);
  766. define('ROWS_6',5);
  767. define('ROWS_7',6);
  768. define('ROWS_8',7);
  769. define('ROWS_9',8);
  770. }
  771. $heightforframes=52;
  772. // Init menu manager
  773. if (! defined('NOREQUIREMENU'))
  774. {
  775. if (empty($user->societe_id)) // If internal user or not defined
  776. {
  777. $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);
  778. }
  779. else // If external user
  780. {
  781. $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);
  782. }
  783. // Load the menu manager (only if not already done)
  784. $file_menu=$conf->standard_menu;
  785. if (GETPOST('menu')) $file_menu=GETPOST('menu'); // example: menu=eldy_menu.php
  786. if (! class_exists('MenuManager'))
  787. {
  788. $menufound=0;
  789. $dirmenus=array_merge(array("/core/menus/"),(array) $conf->modules_parts['menus']);
  790. foreach($dirmenus as $dirmenu)
  791. {
  792. $menufound=dol_include_once($dirmenu."standard/".$file_menu);
  793. if (class_exists('MenuManager')) break;
  794. }
  795. if (! class_exists('MenuManager')) // If failed to include, we try with standard eldy_menu.php
  796. {
  797. dol_syslog("You define a menu manager '".$file_menu."' that can not be loaded.", LOG_WARNING);
  798. $file_menu='eldy_menu.php';
  799. include_once DOL_DOCUMENT_ROOT."/core/menus/standard/".$file_menu;
  800. }
  801. }
  802. $menumanager = new MenuManager($db, empty($user->societe_id)?0:1);
  803. $menumanager->loadMenu();
  804. }
  805. // Functions
  806. if (! function_exists("llxHeader"))
  807. {
  808. /**
  809. * Show HTML header HTML + BODY + Top menu + left menu + DIV
  810. *
  811. * @param string $head Optionnal head lines
  812. * @param string $title HTML title
  813. * @param string $help_url Url links to help page
  814. * Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage
  815. * For other external page: http://server/url
  816. * @param string $target Target to use on links
  817. * @param int $disablejs More content into html header
  818. * @param int $disablehead More content into html header
  819. * @param array $arrayofjs Array of complementary js files
  820. * @param array $arrayofcss Array of complementary css files
  821. * @param string $morequerystring Query string to add to the link "print" to get same parameters (use only if autodetect fails)
  822. * @return void
  823. */
  824. function llxHeader($head = '', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='')
  825. {
  826. global $conf;
  827. // html header
  828. top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
  829. // top menu and left menu area
  830. if (empty($conf->dol_hide_topmenu))
  831. {
  832. top_menu($head, $title, $target, $disablejs, $disablehead, $arrayofjs, $arrayofcss, $morequerystring, $help_url);
  833. }
  834. if (empty($conf->dol_hide_leftmenu))
  835. {
  836. left_menu('', $help_url, '', '', 1, $title, 1);
  837. }
  838. // main area
  839. main_area($title);
  840. }
  841. }
  842. /**
  843. * Show HTTP header
  844. *
  845. * @return void
  846. */
  847. function top_httphead()
  848. {
  849. global $conf;
  850. //header("Content-type: text/html; charset=UTF-8");
  851. header("Content-type: text/html; charset=".$conf->file->character_set_client);
  852. // On the fly GZIP compression for all pages (if browser support it). Must set the bit 3 of constant to 1.
  853. if (isset($conf->global->MAIN_OPTIMIZE_SPEED) && ($conf->global->MAIN_OPTIMIZE_SPEED & 0x04)) {
  854. ob_start("ob_gzhandler");
  855. }
  856. }
  857. /**
  858. * Ouput html header of a page.
  859. * This code is also duplicated into security2.lib.php::dol_loginfunction
  860. *
  861. * @param string $head Optionnal head lines
  862. * @param string $title HTML title
  863. * @param int $disablejs More content into html header
  864. * @param int $disablehead More content into html header
  865. * @param array $arrayofjs Array of complementary js files
  866. * @param array $arrayofcss Array of complementary css files
  867. * @return void
  868. */
  869. function top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='')
  870. {
  871. global $user, $conf, $langs, $db;
  872. top_httphead();
  873. if (empty($conf->css)) $conf->css = '/theme/eldy/style.css.php'; // If not defined, eldy by default
  874. if (empty($conf->global->MAIN_ACTIVATE_HTML5)) {
  875. $doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
  876. }else {
  877. $doctype = '<!doctype html>'; // Html5 - Developement - Only available on Eldy template
  878. }
  879. print $doctype."\n";
  880. if (! empty($conf->global->MAIN_USE_CACHE_MANIFEST)) print '<html lang="'.substr($langs->defaultlang,0,2).'" manifest="'.DOL_URL_ROOT.'/cache.manifest">'."\n";
  881. else print '<html lang="'.substr($langs->defaultlang,0,2).'">'."\n";
  882. //print '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">'."\n";
  883. if (empty($disablehead))
  884. {
  885. print "<head>\n";
  886. if (GETPOST('dol_basehref')) print '<base href="'.dol_escape_htmltag(GETPOST('dol_basehref')).'">'."\n";
  887. // Displays meta
  888. print '<meta name="robots" content="noindex,nofollow">'."\n"; // Do not index
  889. print '<meta name="viewport" content="width=device-width, initial-scale=1.0">'; // Scale for mobile device
  890. print '<meta name="author" content="Dolibarr Development Team">'."\n";
  891. $favicon=dol_buildpath('/theme/'.$conf->theme.'/img/favicon.ico',1);
  892. if (! empty($conf->global->MAIN_FAVICON_URL)) $favicon=$conf->global->MAIN_FAVICON_URL;
  893. print '<link rel="shortcut icon" type="image/x-icon" href="'.$favicon.'"/>'."\n";
  894. if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) print '<link rel="top" title="'.$langs->trans("Home").'" href="'.(DOL_URL_ROOT?DOL_URL_ROOT:'/').'">'."\n";
  895. 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";
  896. if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) print '<link rel="author" title="Dolibarr Development Team" href="http://www.dolibarr.org">'."\n";
  897. // Displays title
  898. $appli=constant('DOL_APPLICATION_TITLE');
  899. if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $appli=$conf->global->MAIN_APPLICATION_TITLE;
  900. if ($title && ! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/noapp/',$conf->global->MAIN_HTML_TITLE)) print '<title>'.dol_htmlentities($title).'</title>';
  901. else if ($title) print '<title>'.dol_htmlentities($appli.' - '.$title).'</title>';
  902. else print "<title>".dol_htmlentities($appli)."</title>";
  903. print "\n";
  904. //$ext='';
  905. //if (! empty($conf->dol_use_jmobile)) $ext='version='.urlencode(DOL_VERSION);
  906. $ext='version='.urlencode(DOL_VERSION);
  907. if (GETPOST('version')) $ext='version='.GETPOST('version','int'); // usefull to force no cache on css/js
  908. if (! defined('DISABLE_JQUERY') && ! $disablejs && $conf->use_javascript_ajax)
  909. {
  910. print '<!-- Includes CSS for JQuery (Ajax library) -->'."\n";
  911. $jquerytheme = 'smoothness';
  912. if (!empty($conf->global->MAIN_USE_JQUERY_THEME)) $jquerytheme = $conf->global->MAIN_USE_JQUERY_THEME;
  913. 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
  914. else print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/css/'.$jquerytheme.'/jquery-ui.css'.($ext?'?'.$ext:'').'">'."\n"; // JQuery
  915. print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/tiptip/tipTip.css'.($ext?'?'.$ext:'').'">'."\n"; // Tooltip
  916. print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/jnotify/jquery.jnotify-alt.min.css'.($ext?'?'.$ext:'').'">'."\n"; // JNotify
  917. /*if (! empty($conf->global->MAIN_USE_JQUERY_FILEUPLOAD) || (defined('REQUIRE_JQUERY_FILEUPLOAD') && constant('REQUIRE_JQUERY_FILEUPLOAD'))) // jQuery fileupload
  918. {
  919. print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/fileupload/css/jquery.fileupload-ui.css'.($ext?'?'.$ext:'').'">'."\n";
  920. }*/
  921. if (! empty($conf->global->MAIN_USE_JQUERY_DATATABLES) || (defined('REQUIRE_JQUERY_DATATABLES') && constant('REQUIRE_JQUERY_DATATABLES'))) // jQuery datatables
  922. {
  923. //print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/css/jquery.dataTables.css'.($ext?'?'.$ext:'').'">'."\n";
  924. print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/media/css/jquery.dataTables.min.css'.($ext?'?'.$ext:'').'">'."\n";
  925. print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/extensions/ColReorder/css/dataTables.colReorder.min.css'.($ext?'?'.$ext:'').'">'."\n";
  926. print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/extensions/ColVis/css/dataTables.colVis.min.css'.($ext?'?'.$ext:'').'">'."\n";
  927. print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/extensions/TableTools/css/dataTables.tableTools.min.css'.($ext?'?'.$ext:'').'">'."\n";
  928. }
  929. if (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT')) // jQuery plugin "mutiselect", "multiple-select", "select2"...
  930. {
  931. $tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?constant('REQUIRE_JQUERY_MULTISELECT'):$conf->global->MAIN_USE_JQUERY_MULTISELECT;
  932. print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/'.$tmpplugin.'/'.$tmpplugin.'.css'.($ext?'?'.$ext:'').'">'."\n";
  933. }
  934. // jQuery Timepicker
  935. if (! empty($conf->global->MAIN_USE_JQUERY_TIMEPICKER) || defined('REQUIRE_JQUERY_TIMEPICKER'))
  936. {
  937. print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/timepicker/jquery-ui-timepicker-addon.css'.($ext?'?'.$ext:'').'">'."\n";
  938. }
  939. // jQuery jMobile
  940. if (! empty($conf->global->MAIN_USE_JQUERY_JMOBILE) || defined('REQUIRE_JQUERY_JMOBILE') || ! empty($conf->dol_use_jmobile))
  941. {
  942. print '<link rel="stylesheet" type="text/css" href="'.DOL_URL_ROOT.'/includes/jquery/plugins/mobile/jquery.mobile-latest.min.css'.($ext?'?'.$ext:'').'">'."\n";
  943. }
  944. }
  945. print '<!-- Includes CSS for Dolibarr theme -->'."\n";
  946. // Output style sheets (optioncss='print' or ''). Note: $conf->css looks like '/theme/eldy/style.css.php'
  947. //$themepath=dol_buildpath((empty($conf->global->MAIN_FORCETHEMEDIR)?'':$conf->global->MAIN_FORCETHEMEDIR).$conf->css,1);
  948. $themepath=dol_buildpath($conf->css,1);
  949. $themesubdir='';
  950. if (! empty($conf->modules_parts['theme'])) // This slow down
  951. {
  952. foreach($conf->modules_parts['theme'] as $reldir)
  953. {
  954. if (file_exists(dol_buildpath($reldir.$conf->css, 0)))
  955. {
  956. $themepath=dol_buildpath($reldir.$conf->css, 1);
  957. $themesubdir=$reldir;
  958. break;
  959. }
  960. }
  961. }
  962. $themeparam='?lang='.$langs->defaultlang.'&amp;theme='.$conf->theme.(GETPOST('optioncss')?'&amp;optioncss='.GETPOST('optioncss','alpha',1):'').'&amp;userid='.$user->id.'&amp;entity='.$conf->entity;
  963. $themeparam.=($ext?'&amp;'.$ext:'');
  964. if (! empty($_SESSION['dol_resetcache'])) $themeparam.='&amp;dol_resetcache='.$_SESSION['dol_resetcache'];
  965. if (GETPOST('dol_hide_topmenu')) { $themeparam.='&amp;dol_hide_topmenu='.GETPOST('dol_hide_topmenu','int'); }
  966. if (GETPOST('dol_hide_leftmenu')) { $themeparam.='&amp;dol_hide_leftmenu='.GETPOST('dol_hide_leftmenu','int'); }
  967. if (GETPOST('dol_optimize_smallscreen')) { $themeparam.='&amp;dol_optimize_smallscreen='.GETPOST('dol_optimize_smallscreen','int'); }
  968. if (GETPOST('dol_no_mouse_hover')) { $themeparam.='&amp;dol_no_mouse_hover='.GETPOST('dol_no_mouse_hover','int'); }
  969. if (GETPOST('dol_use_jmobile')) { $themeparam.='&amp;dol_use_jmobile='.GETPOST('dol_use_jmobile','int'); $conf->dol_use_jmobile=GETPOST('dol_use_jmobile','int'); }
  970. //print 'themepath='.$themepath.' themeparam='.$themeparam;exit;
  971. print '<link rel="stylesheet" type="text/css" href="'.$themepath.$themeparam.'">'."\n";
  972. if (! empty($conf->global->MAIN_FIX_FLASH_ON_CHROME)) print '<!-- Includes CSS that does not exists as workaround of flash bug of chrome -->'."\n".'<link rel="stylesheet" type="text/css" href="filethatdoesnotexiststosolvechromeflashbug">'."\n";
  973. // CSS forced by modules (relative url starting with /)
  974. if (! empty($conf->modules_parts['css']))
  975. {
  976. $arraycss=(array) $conf->modules_parts['css'];
  977. foreach($arraycss as $modcss => $filescss)
  978. {
  979. $filescss=(array) $filescss; // To be sure filecss is an array
  980. foreach($filescss as $cssfile)
  981. {
  982. if (empty($cssfile)) dol_syslog("Warning: module ".$modcss." declared a css path file into its descriptor that is empty.", LOG_WARNING);
  983. // cssfile is a relative path
  984. print '<!-- Includes CSS added by module '.$modcss. ' -->'."\n".'<link rel="stylesheet" type="text/css" href="'.dol_buildpath($cssfile,1);
  985. // 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.
  986. if (!preg_match('/\.css$/i',$cssfile)) print $themeparam;
  987. print '">'."\n";
  988. }
  989. }
  990. }
  991. // CSS forced by page in top_htmlhead call (relative url starting with /)
  992. if (is_array($arrayofcss))
  993. {
  994. foreach($arrayofcss as $cssfile)
  995. {
  996. print '<!-- Includes CSS added by page -->'."\n".'<link rel="stylesheet" type="text/css" title="default" href="'.dol_buildpath($cssfile,1);
  997. // 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.
  998. if (!preg_match('/\.css$/i',$cssfile)) print $themeparam;
  999. print '">'."\n";
  1000. }
  1001. }
  1002. // Output standard javascript links
  1003. if (! defined('DISABLE_JQUERY') && ! $disablejs && ! empty($conf->use_javascript_ajax))
  1004. {
  1005. // JQuery. Must be before other includes
  1006. print '<!-- Includes JS for JQuery -->'."\n";
  1007. if (constant('JS_JQUERY')) print '<script type="text/javascript" src="'.JS_JQUERY.'jquery.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1008. else print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/js/jquery.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1009. if (constant('JS_JQUERY_UI')) print '<script type="text/javascript" src="'.JS_JQUERY_UI.'jquery-ui.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1010. else print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/js/jquery-ui.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1011. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/tablednd/jquery.tablednd.0.6.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1012. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/tiptip/jquery.tipTip.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1013. // jQuery Layout
  1014. if (empty($conf->dol_use_jmobile) && ! empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT) || defined('REQUIRE_JQUERY_LAYOUT'))
  1015. {
  1016. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/layout/jquery.layout.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1017. }
  1018. // jQuery jnotify
  1019. if (empty($conf->global->MAIN_DISABLE_JQUERY_JNOTIFY) && ! defined('DISABLE_JQUERY_JNOTIFY'))
  1020. {
  1021. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jnotify/jquery.jnotify.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1022. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/jnotify.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1023. }
  1024. // jQuery blockUI
  1025. if (! empty($conf->global->MAIN_USE_JQUERY_BLOCKUI) || defined('REQUIRE_JQUERY_BLOCKUI'))
  1026. {
  1027. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/blockUI/jquery.blockUI.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1028. print '<script type="text/javascript">'."\n";
  1029. print 'var indicatorBlockUI = \''.DOL_URL_ROOT."/theme/".$conf->theme."/img/working2.gif".'\';'."\n";
  1030. print '</script>'."\n";
  1031. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/blockUI.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1032. }
  1033. // Flot
  1034. if (empty($conf->global->MAIN_DISABLE_JQUERY_FLOT))
  1035. {
  1036. if (constant('JS_JQUERY_FLOT'))
  1037. {
  1038. print '<script type="text/javascript" src="'.JS_JQUERY_FLOT.'jquery.flot.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1039. print '<script type="text/javascript" src="'.JS_JQUERY_FLOT.'jquery.flot.pie.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1040. print '<script type="text/javascript" src="'.JS_JQUERY_FLOT.'jquery.flot.stack.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1041. }
  1042. else
  1043. {
  1044. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/flot/jquery.flot.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1045. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/flot/jquery.flot.pie.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1046. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/flot/jquery.flot.stack.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1047. }
  1048. }
  1049. // jQuery jeditable
  1050. if (! empty($conf->global->MAIN_USE_JQUERY_JEDITABLE))
  1051. {
  1052. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1053. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.ui-datepicker.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1054. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.ui-autocomplete.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1055. print '<script type="text/javascript">'."\n";
  1056. print 'var urlSaveInPlace = \''.DOL_URL_ROOT.'/core/ajax/saveinplace.php\';'."\n";
  1057. print 'var urlLoadInPlace = \''.DOL_URL_ROOT.'/core/ajax/loadinplace.php\';'."\n";
  1058. print 'var tooltipInPlace = \''.$langs->transnoentities('ClickToEdit').'\';'."\n";
  1059. print 'var placeholderInPlace = \''.$langs->trans('ClickToEdit').'\';'."\n";
  1060. print 'var cancelInPlace = \''.$langs->trans('Cancel').'\';'."\n";
  1061. print 'var submitInPlace = \''.$langs->trans('Ok').'\';'."\n";
  1062. print 'var indicatorInPlace = \'<img src="'.DOL_URL_ROOT."/theme/".$conf->theme."/img/working.gif".'">\';'."\n";
  1063. print '</script>'."\n";
  1064. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/editinplace.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1065. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/jeditable/jquery.jeditable.ckeditor.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1066. }
  1067. // jQuery File Upload
  1068. /*
  1069. if (! empty($conf->global->MAIN_USE_JQUERY_FILEUPLOAD) || (defined('REQUIRE_JQUERY_FILEUPLOAD') && constant('REQUIRE_JQUERY_FILEUPLOAD')))
  1070. {
  1071. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/template/tmpl.min'.$ext.'"></script>'."\n";
  1072. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/fileupload/js/jquery.iframe-transport'.$ext.'"></script>'."\n";
  1073. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/fileupload/js/jquery.fileupload'.$ext.'"></script>'."\n";
  1074. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/fileupload/js/jquery.fileupload-fp'.$ext.'"></script>'."\n";
  1075. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/fileupload/js/jquery.fileupload-ui'.$ext.'"></script>'."\n";
  1076. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/fileupload/js/jquery.fileupload-jui'.$ext.'"></script>'."\n";
  1077. print '<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE8+ -->'."\n";
  1078. print '<!--[if gte IE 8]><script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/fileupload/js/cors/jquery.xdr-transport'.$ext.'"></script><![endif]-->'."\n";
  1079. }*/
  1080. // jQuery DataTables
  1081. if (! empty($conf->global->MAIN_USE_JQUERY_DATATABLES) || (defined('REQUIRE_JQUERY_DATATABLES') && constant('REQUIRE_JQUERY_DATATABLES')))
  1082. {
  1083. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/media/js/jquery.dataTables.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1084. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/extensions/ColReorder/js/dataTables.colReorder.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1085. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/extensions/ColVis/js/dataTables.colVis.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1086. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/datatables/extensions/TableTools/js/dataTables.tableTools.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1087. }
  1088. // jQuery Timepicker
  1089. if (! empty($conf->global->MAIN_USE_JQUERY_TIMEPICKER) || defined('REQUIRE_JQUERY_TIMEPICKER'))
  1090. {
  1091. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/timepicker/jquery-ui-timepicker-addon.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1092. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/timepicker.js.php?lang='.$langs->defaultlang.($ext?'&amp;'.$ext:'').'"></script>'."\n";
  1093. }
  1094. if (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT')) // jQuery plugin "mutiselect", "multiple-select", "select2", ...
  1095. {
  1096. $tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?constant('REQUIRE_JQUERY_MULTISELECT'):$conf->global->MAIN_USE_JQUERY_MULTISELECT;
  1097. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/'.$tmpplugin.'/'.$tmpplugin.'.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1098. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/select2_locale.js.php'.($ext?'?'.$ext:'').'"></script>'."\n";
  1099. }
  1100. // jQuery jMobile
  1101. if (! empty($conf->global->MAIN_USE_JQUERY_JMOBILE) || defined('REQUIRE_JQUERY_JMOBILE') || (! empty($conf->dol_use_jmobile) && $conf->dol_use_jmobile > 0))
  1102. {
  1103. // We must force not using ajax because cache of jquery does not load js of other pages.
  1104. // This also increase seriously speed onto mobile device where complex js code is very slow and memory very low.
  1105. // Note: dol_use_jmobile=1 use jmobile without ajax, dol_use_jmobile=2 use jmobile with ajax
  1106. if (empty($conf->dol_use_jmobile) || ($conf->dol_use_jmobile != 2 && $conf->dol_use_jmobile != 3))
  1107. {
  1108. print '<script type="text/javascript">
  1109. $(document).bind("mobileinit", function() {
  1110. ';
  1111. if ($conf->theme == 'md')
  1112. {
  1113. print '
  1114. /* Disabled decoration for some css */
  1115. $.mobile.keepNative = \'input[type="submit"]\'; /* jQuery Mobile 1.4 and higher */
  1116. $.mobile.page.prototype.options.keepNative = \'input[type="submit"]\'; /* jQuery Mobile 1.4 and lower */
  1117. ';
  1118. }
  1119. print '
  1120. $.extend( $.mobile , {
  1121. autoInitializePage : true, /* We need this to run jmobile */
  1122. /* loadingMessage : \'xxxxx\', */
  1123. touchOverflowEnabled : true,
  1124. defaultPageTransition : \'none\',
  1125. defaultDialogTransition : \'none\',
  1126. ajaxEnabled : false /* old param was ajaxFormsEnabled and ajaxLinksEnabled */
  1127. });
  1128. });
  1129. </script>';
  1130. }
  1131. if (empty($conf->dol_use_jmobile) || $conf->dol_use_jmobile != 3) print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/includes/jquery/plugins/mobile/jquery.mobile-latest.min.js'.($ext?'?'.$ext:'').'"></script>'."\n";
  1132. }
  1133. }
  1134. if (! $disablejs && ! empty($conf->use_javascript_ajax))
  1135. {
  1136. // CKEditor
  1137. if (! empty($conf->fckeditor->enabled) && (empty($conf->global->FCKEDITOR_EDITORNAME) || $conf->global->FCKEDITOR_EDITORNAME == 'ckeditor'))
  1138. {
  1139. print '<!-- Includes JS for CKEditor -->'."\n";
  1140. $pathckeditor = DOL_URL_ROOT . '/includes/ckeditor/ckeditor/';
  1141. $jsckeditor='ckeditor.js';
  1142. if (constant('JS_CKEDITOR')) // To use external ckeditor 4 js lib
  1143. {
  1144. $pathckeditor=constant('JS_CKEDITOR');
  1145. }
  1146. print '<script type="text/javascript">';
  1147. print 'var CKEDITOR_BASEPATH = \''.$pathckeditor.'\';'."\n";
  1148. print 'var ckeditorConfig = \''.dol_buildpath($themesubdir.'/theme/'.$conf->theme.'/ckeditor/config.js',1).'\';'."\n"; // $themesubdir='' in standard usage
  1149. print 'var ckeditorFilebrowserBrowseUrl = \''.DOL_URL_ROOT.'/core/filemanagerdol/browser/default/browser.php?Connector='.DOL_URL_ROOT.'/core/filemanagerdol/connectors/php/connector.php\';'."\n";
  1150. 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";
  1151. print '</script>'."\n";
  1152. print '<script type="text/javascript" src="'.$pathckeditor.$jsckeditor.($ext?'?'.$ext:'').'"></script>'."\n";
  1153. }
  1154. // Raven.js for client-side Sentry logging support
  1155. if (array_key_exists('mod_syslog_sentry', $conf->loghandlers)) {
  1156. print '<!-- Includes Raven.js for Sentry -->' . "\n";
  1157. print '<script src="' . DOL_URL_ROOT . '/includes/raven-js/dist/raven.min.js"></script>' . "\n";
  1158. print '<script src="' . DOL_URL_ROOT . '/includes/raven-js/plugins/native.js"></script>' . "\n";
  1159. if (! defined('DISABLE_JQUERY')) {
  1160. print '<script src="' . DOL_URL_ROOT . '/includes/raven-js/plugins/jquery.js"></script>' . "\n";
  1161. }
  1162. }
  1163. // Global js function
  1164. print '<!-- Includes JS of Dolibarr -->'."\n";
  1165. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/lib_head.js.php?version='.urlencode(DOL_VERSION).($ext?'&amp;'.$ext:'').'"></script>'."\n";
  1166. // Add datepicker default options
  1167. print '<script type="text/javascript" src="'.DOL_URL_ROOT.'/core/js/datepicker.js.php?lang='.$langs->defaultlang.($ext?'&amp;'.$ext:'').'"></script>'."\n";
  1168. // JS forced by modules (relative url starting with /)
  1169. if (! empty($conf->modules_parts['js'])) // $conf->modules_parts['js'] is array('module'=>array('file1','file2'))
  1170. {
  1171. $arrayjs=(array) $conf->modules_parts['js'];
  1172. foreach($arrayjs as $modjs => $filesjs)
  1173. {
  1174. $filesjs=(array) $filesjs; // To be sure filejs is an array
  1175. foreach($filesjs as $jsfile)
  1176. {
  1177. // jsfile is a relative path
  1178. print '<!-- Include JS added by module '.$modjs. '-->'."\n".'<script type="text/javascript" src="'.dol_buildpath($jsfile,1).'"></script>'."\n";
  1179. }
  1180. }
  1181. }
  1182. // JS forced by page in top_htmlhead (relative url starting with /)
  1183. if (is_array($arrayofjs))
  1184. {
  1185. print '<!-- Includes JS added by page -->'."\n";
  1186. foreach($arrayofjs as $jsfile)
  1187. {
  1188. if (preg_match('/^http/i',$jsfile))
  1189. {
  1190. print '<script type="text/javascript" src="'.$jsfile.'"></script>'."\n";
  1191. }
  1192. else
  1193. {
  1194. if (! preg_match('/^\//',$jsfile)) $jsfile='/'.$jsfile; // For backward compatibility
  1195. print '<script type="text/javascript" src="'.dol_buildpath($jsfile,1).'"></script>'."\n";
  1196. }
  1197. }
  1198. }
  1199. }
  1200. if (! empty($head)) print $head."\n";
  1201. if (! empty($conf->global->MAIN_HTML_HEADER)) print $conf->global->MAIN_HTML_HEADER."\n";
  1202. print "</head>\n\n";
  1203. }
  1204. $conf->headerdone=1; // To tell header was output
  1205. }
  1206. /**
  1207. * Show an HTML header + a BODY + The top menu bar
  1208. *
  1209. * @param string $head Lines in the HEAD
  1210. * @param string $title Title of web page
  1211. * @param string $target Target to use in menu links (Example: '' or '_top')
  1212. * @param int $disablejs Do not output links to js (Ex: qd fonction utilisee par sous formulaire Ajax)
  1213. * @param int $disablehead Do not output head section
  1214. * @param array $arrayofjs Array of js files to add in header
  1215. * @param array $arrayofcss Array of css files to add in header
  1216. * @param string $morequerystring Query string to add to the link "print" to get same parameters (use only if autodetect fails)
  1217. * @param string $helppagename Name of wiki page for help ('' by default).
  1218. * Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage
  1219. * For other external page: http://server/url
  1220. * @return void
  1221. */
  1222. function top_menu($head, $title='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $helppagename='')
  1223. {
  1224. global $user, $conf, $langs, $db;
  1225. global $dolibarr_main_authentication, $dolibarr_main_demo;
  1226. global $hookmanager,$menumanager;
  1227. // Instantiate hooks of thirdparty module
  1228. $hookmanager->initHooks(array('toprightmenu'));
  1229. $toprightmenu='';
  1230. // For backward compatibility with old modules
  1231. if (empty($conf->headerdone)) top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
  1232. print '<body id="mainbody">' . "\n";
  1233. if ($conf->use_javascript_ajax)
  1234. {
  1235. if (empty($conf->dol_use_jmobile) && ! empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT))
  1236. {
  1237. print '<script type="text/javascript">
  1238. jQuery(document).ready(function () {
  1239. jQuery("body").layout(layoutSettings);
  1240. });
  1241. var layoutSettings = {
  1242. name: "mainlayout",
  1243. defaults: {
  1244. useStateCookie: true,
  1245. size: "auto",
  1246. resizable: false,
  1247. //paneClass: "none",
  1248. //resizerClass: "resizer",
  1249. //togglerClass: "toggler",
  1250. //buttonClass: "button",
  1251. //contentSelector: ".content",
  1252. //contentIgnoreSelector: "span",
  1253. togglerTip_open: "Close This Pane",
  1254. togglerTip_closed: "Open This Pane",
  1255. resizerTip: "Resize This Pane",
  1256. fxSpeed: "fast"
  1257. },
  1258. west: {
  1259. paneClass: "leftContent",
  1260. //spacing_closed: 14,
  1261. //togglerLength_closed: 14,
  1262. //togglerAlign_closed: "auto",
  1263. //togglerLength_open: 0,
  1264. // effect defaults - overridden on some panes
  1265. //slideTrigger_open: "mouseover",
  1266. initClosed: '.(empty($conf->dol_optimize_smallscreen)?'false':'true').',
  1267. fxName: "drop",
  1268. fxSpeed: "fast",
  1269. fxSettings: { easing: "" }
  1270. },
  1271. north: {
  1272. paneClass: "none",
  1273. resizerClass: "none",
  1274. togglerClass: "none",
  1275. spacing_open: 0,
  1276. togglerLength_open: 0,
  1277. togglerLength_closed: -1,
  1278. slidable: false,
  1279. fxName: "none",
  1280. fxSpeed: "fast"
  1281. },
  1282. center: {
  1283. paneSelector: "#mainContent"
  1284. }
  1285. }
  1286. </script>' . "\n";
  1287. }
  1288. // Raven.js for client-side Sentry logging support
  1289. if (array_key_exists('mod_syslog_sentry', $conf->loghandlers) && ! empty($conf->global->SYSLOG_SENTRY_DSN))
  1290. {
  1291. // Filter out secret key
  1292. $dsn = parse_url($conf->global->SYSLOG_SENTRY_DSN);
  1293. $public_dsn = $dsn['scheme'] . '://' . $dsn['user'] .'@' . $dsn['host'] . $dsn['path'];
  1294. print '<script type="text/javascript">' . "\n";
  1295. print "Raven.config('" . $public_dsn . "').install()\n";
  1296. print "Raven.setUserContext({username: '" . $user->login . "'})\n";
  1297. print "Raven.setTagsContext({version: '" . DOL_VERSION . "'})\n";
  1298. print "</script>\n";
  1299. }
  1300. }
  1301. /*
  1302. * Top menu
  1303. */
  1304. print "\n".'<!-- Start top horizontal -->'."\n";
  1305. if (empty($conf->dol_use_jmobile) && ! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT)) print '<div class="ui-layout-north"> <!-- Begin top layout -->'."\n";
  1306. if (empty($conf->dol_hide_topmenu))
  1307. {
  1308. print '<div class="side-nav-vert"><div id="id-top">';
  1309. // Show menu entries
  1310. print '<div id="tmenu_tooltip'.(empty($conf->global->MAIN_MENU_INVERT)?'':'invert').'" class="tmenu">'."\n";
  1311. $menumanager->atarget=$target;
  1312. $menumanager->showmenu('top'); // This contains a \n
  1313. print "</div>\n";
  1314. //$form=new Form($db);
  1315. // Define link to login card
  1316. $appli=constant('DOL_APPLICATION_TITLE');
  1317. if (! empty($conf->global->MAIN_APPLICATION_TITLE))
  1318. {
  1319. $appli=$conf->global->MAIN_APPLICATION_TITLE;
  1320. if (preg_match('/\d\.\d/', $appli))
  1321. {
  1322. if (! preg_match('/'.preg_quote(DOL_VERSION).'/', $appli)) $appli.=" (".DOL_VERSION.")"; // If new title contains a version that is different than core
  1323. }
  1324. else $appli.=" ".DOL_VERSION;
  1325. }
  1326. else $appli.=" ".DOL_VERSION;
  1327. if (! empty($conf->global->MAIN_FEATURES_LEVEL)) $appli.="<br>".$langs->trans("LevelOfFeature").': '.$conf->global->MAIN_FEATURES_LEVEL;
  1328. $logouttext='';
  1329. $logouthtmltext=$appli.'<br>';
  1330. if ($_SESSION["dol_authmode"] != 'forceuser' && $_SESSION["dol_authmode"] != 'http')
  1331. {
  1332. $logouthtmltext.=$langs->trans("Logout").'<br>';
  1333. $logouttext .='<a href="'.DOL_URL_ROOT.'/user/logout.php">';
  1334. $logouttext .= img_picto($langs->trans('Logout').":".$langs->trans('Logout'), 'logout_top.png', 'class="login"', 0, 0, 1);
  1335. $logouttext .='</a>';
  1336. }
  1337. else
  1338. {
  1339. $logouthtmltext.=$langs->trans("NoLogoutProcessWithAuthMode",$_SESSION["dol_authmode"]);
  1340. $logouttext .= img_picto($langs->trans('Logout').":".$langs->trans('Logout'), 'logout_top.png', 'class="login"', 0, 0, 1);
  1341. }
  1342. print '<div class="login_block">'."\n";
  1343. // Add login user link
  1344. $toprightmenu.='<div class="login_block_user">';
  1345. // Login name with photo and tooltip
  1346. $mode=-1;
  1347. $toprightmenu.='<div class="inline-block nowrap"><div class="inline-block login_block_elem login_block_elem_name" style="padding: 0px;">';
  1348. $toprightmenu.=$user->getNomUrl($mode, '', true, 0, 11, 0, ($user->firstname ? 'firstname' : -1),'atoplogin');
  1349. $toprightmenu.='</div></div>';
  1350. $toprightmenu.='</div>';
  1351. $toprightmenu.='<div class="login_block_other">';
  1352. // Execute hook printTopRightMenu (hooks should output string like '<div class="login"><a href="">mylink</a></div>')
  1353. $parameters=array();
  1354. $result=$hookmanager->executeHooks('printTopRightMenu',$parameters); // Note that $action and $object may have been modified by some hooks
  1355. if (is_numeric($result))
  1356. {
  1357. if (empty($result)) $toprightmenu.=$hookmanager->resPrint; // add
  1358. else $toprightmenu=$hookmanager->resPrint; // replace
  1359. }
  1360. else $toprightmenu.=$result; // For backward compatibility
  1361. // Link to print main content area
  1362. if (empty($conf->global->MAIN_PRINT_DISABLELINK) && empty($conf->browser->phone))
  1363. {
  1364. $qs=$_SERVER["QUERY_STRING"];
  1365. $qs.=(($qs && $morequerystring)?'&':'').$morequerystring;
  1366. $text ='<a href="'.$_SERVER["PHP_SELF"].'?'.$qs.($qs?'&':'').'optioncss=print" target="_blank">';
  1367. $text.= img_picto(":".$langs->trans("PrintContentArea"), 'printer_top.png', 'class="printer"');
  1368. $text.='</a>';
  1369. $toprightmenu.=Form::textwithtooltip('',$langs->trans("PrintContentArea"),2,1,$text,'login_block_elem',2);
  1370. }
  1371. // Link to Dolibarr wiki pages
  1372. if (empty($conf->global->MAIN_HELP_DISABLELINK))
  1373. {
  1374. $langs->load("help");
  1375. $helpbaseurl='';
  1376. $helppage='';
  1377. $mode='';
  1378. if (empty($helppagename)) $helppagename='EN:User_documentation|FR:Documentation_utilisateur|ES:Documentación_usuarios';
  1379. // Get helpbaseurl, helppage and mode from helppagename and langs
  1380. $arrayres=getHelpParamFor($helppagename,$langs);
  1381. $helpbaseurl=$arrayres['helpbaseurl'];
  1382. $helppage=$arrayres['helppage'];
  1383. $mode=$arrayres['mode'];
  1384. // Link to help pages
  1385. if ($helpbaseurl && $helppage)
  1386. {
  1387. $text='';
  1388. $title='';
  1389. //$text.='<div id="blockvmenuhelpwiki" class="blockvmenuhelp">';
  1390. $title.=$langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage');
  1391. if ($mode == 'wiki') $title.=' - '.$langs->trans("PageWiki").' &quot;'.dol_escape_htmltag(strtr($helppage,'_',' ')).'&quot;';
  1392. $text.='<a class="help" target="_blank" href="';
  1393. if ($mode == 'wiki') $text.=sprintf($helpbaseurl,urlencode(html_entity_decode($helppage)));
  1394. else $text.=sprintf($helpbaseurl,$helppage);
  1395. $text.='">';
  1396. $text.=img_picto('', 'helpdoc_top').' ';
  1397. //$toprightmenu.=$langs->trans($mode == 'wiki' ? 'OnlineHelp': 'Help');
  1398. //if ($mode == 'wiki') $text.=' ('.dol_trunc(strtr($helppage,'_',' '),8).')';
  1399. $text.='</a>';
  1400. //$toprightmenu.='</div>'."\n";
  1401. $toprightmenu.=Form::textwithtooltip('',$title,2,1,$text,'login_block_elem',2);
  1402. }
  1403. }
  1404. // Logout link
  1405. $toprightmenu.=Form::textwithtooltip('',$logouthtmltext,2,1,$logouttext,'login_block_elem',2);
  1406. $toprightmenu.='</div>';
  1407. print $toprightmenu;
  1408. print "</div>\n";
  1409. print '</div></div>';
  1410. //unset($form);
  1411. }
  1412. if (empty($conf->dol_use_jmobile) && ! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT)) print "</div><!-- End top layout -->\n";
  1413. print '<div style="clear: both;"></div>';
  1414. print "<!-- End top horizontal menu -->\n\n";
  1415. if (empty($conf->dol_hide_leftmenu) && empty($conf->dol_use_jmobile) && empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT)) print '<div id="id-container">';
  1416. }
  1417. /**
  1418. * Show left menu bar
  1419. *
  1420. * @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 ''.
  1421. * @param string $helppagename Name of wiki page for help ('' by default).
  1422. * Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage
  1423. * For other external page: http://server/url
  1424. * @param string $notused Deprecated. Used in past to add content into left menu. Hooks can be used now.
  1425. * @param array $menu_array_after Table of menu entries to show after entries of menu handler
  1426. * @param int $leftmenuwithoutmainarea Must be set to 1. 0 by default for backward compatibility with old modules.
  1427. * @param string $title Title of web page
  1428. * @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)
  1429. * @return void
  1430. */
  1431. function left_menu($menu_array_before, $helppagename='', $notused='', $menu_array_after='', $leftmenuwithoutmainarea=0, $title='', $acceptdelayedhtml=0)
  1432. {
  1433. global $user, $conf, $langs, $db, $form;
  1434. global $hookmanager, $menumanager;
  1435. $searchform='';
  1436. $bookmarks='';
  1437. 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);
  1438. if (empty($conf->dol_hide_leftmenu))
  1439. {
  1440. // Instantiate hooks of thirdparty module
  1441. $hookmanager->initHooks(array('searchform','leftblock'));
  1442. if (empty($conf->dol_use_jmobile) && ! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT)) print "\n".'<!-- Begin left layout -->'."\n".'<div class="ui-layout-west">'."\n";
  1443. else print "\n".'<!-- Begin id-left -->'."\n".'<div class="side-nav"><div id="id-left">'."\n";
  1444. print "\n";
  1445. if ($conf->use_javascript_ajax && $conf->browser->layout != 'phone')
  1446. {
  1447. if (! is_object($form)) $form=new Form($db);
  1448. $selected=-1;
  1449. $searchform.=$form->selectArrayAjax('searchselectcombo', DOL_URL_ROOT.'/core/ajax/selectsearchbox.php', $selected, '', '', 0, 1, 'vmenusearchselectcombo', 1, $langs->trans("Search"), 1);
  1450. }
  1451. else
  1452. {
  1453. // Define $searchform
  1454. if ((( ! empty($conf->societe->enabled) && (empty($conf->global->SOCIETE_DISABLE_PROSPECTS) || empty($conf->global->SOCIETE_DISABLE_CUSTOMERS))) || ! empty($conf->fournisseur->enabled)) && $user->rights->societe->lire)
  1455. {
  1456. $langs->load("companies");
  1457. $searchform.=printSearchForm(DOL_URL_ROOT.'/societe/list.php', DOL_URL_ROOT.'/societe/list.php', $langs->trans("ThirdParties"), 'soc', 'sall', 'T', 'searchleftt', img_object('','company'));
  1458. }
  1459. if (! empty($conf->societe->enabled) && $user->rights->societe->lire)
  1460. {
  1461. $langs->load("companies");
  1462. $searchform.=printSearchForm(DOL_URL_ROOT.'/contact/list.php', DOL_URL_ROOT.'/contact/list.php', $langs->trans("Contacts"), 'contact', 'sall', 'A', 'searchleftc', img_object('','contact'));
  1463. }
  1464. if (((! empty($conf->product->enabled) && $user->rights->produit->lire) || (! empty($conf->service->enabled) && $user->rights->service->lire))
  1465. )
  1466. {
  1467. $langs->load("products");
  1468. $searchform.=printSearchForm(DOL_URL_ROOT.'/product/list.php', DOL_URL_ROOT.'/product/list.php', $langs->trans("Products")."/".$langs->trans("Services"), 'products', 'sall', 'P', 'searchleftp', img_object('','product'));
  1469. }
  1470. if (! empty($conf->projet->enabled) && $user->rights->projet->lire)
  1471. {
  1472. $langs->load("projects");
  1473. $searchform.=printSearchForm(DOL_URL_ROOT.'/projet/list.php', DOL_URL_ROOT.'/projet/list.php', $langs->trans("Projects"), 'project', 'search_all', 'Q', 'searchleftproj', img_object('','projectpub'));
  1474. }
  1475. if (! empty($conf->adherent->enabled) && $user->rights->adherent->lire)
  1476. {
  1477. $langs->load("members");
  1478. $searchform.=printSearchForm(DOL_URL_ROOT.'/adherents/list.php', DOL_URL_ROOT.'/adherents/list.php', $langs->trans("Members"), 'member', 'sall', 'M', 'searchleftm', img_object('','user'));
  1479. }
  1480. if (! empty($conf->user->enabled) && $user->rights->user->user->lire)
  1481. {
  1482. $langs->load("users");
  1483. $searchform.=printSearchForm(DOL_URL_ROOT.'/user/list.php', DOL_URL_ROOT.'/user/list.php', $langs->trans("Users"), 'user', 'sall', 'M', 'searchleftuser', img_object('','user'));
  1484. }
  1485. }
  1486. // Execute hook printSearchForm
  1487. $parameters=array('searchform'=>$searchform);
  1488. $reshook=$hookmanager->executeHooks('printSearchForm',$parameters); // Note that $action and $object may have been modified by some hooks
  1489. if (empty($reshook))
  1490. {
  1491. $searchform.=$hookmanager->resPrint;
  1492. }
  1493. else $searchform=$hookmanager->resPrint;
  1494. if ($conf->use_javascript_ajax && $conf->browser->layout == 'phone')
  1495. {
  1496. $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>';
  1497. $searchform.='<script type="text/javascript">
  1498. jQuery(document).ready(function () {
  1499. jQuery("#divsearchforms1").click(function(){
  1500. jQuery("#divsearchforms2").toggle();
  1501. });
  1502. });
  1503. </script>' . "\n";
  1504. $searchform.='</div>';
  1505. }
  1506. // Define $bookmarks
  1507. if (! empty($conf->bookmark->enabled) && $user->rights->bookmark->lire)
  1508. {
  1509. include_once (DOL_DOCUMENT_ROOT.'/bookmarks/bookmarks.lib.php');
  1510. $langs->load("bookmarks");
  1511. $bookmarks=printBookmarksList($db, $langs);
  1512. }
  1513. // Left column
  1514. print '<!-- Begin left menu -->'."\n";
  1515. print '<div class="vmenu">'."\n\n";
  1516. // Show left menu with other forms
  1517. $menumanager->menu_array = $menu_array_before;
  1518. $menumanager->menu_array_after = $menu_array_after;
  1519. $menumanager->showmenu('left', array('searchform'=>$searchform, 'bookmarks'=>$bookmarks)); // output menu_array and menu found in database
  1520. // Dolibarr version + help + bug report link
  1521. print "\n";
  1522. print "<!-- Begin Help Block-->\n";
  1523. print '<div id="blockvmenuhelp" class="blockvmenuhelp">'."\n";
  1524. // Version
  1525. $doliurl='http://www.dolibarr.org';
  1526. //local communities
  1527. if (preg_match('/fr/i',$langs->defaultlang)) $doliurl='http://www.dolibarr.fr';
  1528. if (preg_match('/es/i',$langs->defaultlang)) $doliurl='http://www.dolibarr.es';
  1529. if (preg_match('/de/i',$langs->defaultlang)) $doliurl='http://www.dolibarr.de';
  1530. if (preg_match('/it/i',$langs->defaultlang)) $doliurl='http://www.dolibarr.it';
  1531. if (preg_match('/gr/i',$langs->defaultlang)) $doliurl='http://www.dolibarr.gr';
  1532. $appli=constant('DOL_APPLICATION_TITLE');
  1533. if (! empty($conf->global->MAIN_APPLICATION_TITLE))
  1534. {
  1535. $appli=$conf->global->MAIN_APPLICATION_TITLE; $doliurl='';
  1536. if (preg_match('/\d\.\d/', $appli))
  1537. {
  1538. if (! preg_match('/'.preg_quote(DOL_VERSION).'/', $appli)) $appli.=" (".DOL_VERSION.")"; // If new title contains a version that is different than core
  1539. }
  1540. else $appli.=" ".DOL_VERSION;
  1541. }
  1542. else $appli.=" ".DOL_VERSION;
  1543. print '<div id="blockvmenuhelpapp" class="blockvmenuhelp">';
  1544. if ($doliurl) print '<a class="help" target="_blank" href="'.$doliurl.'">';
  1545. print $appli;
  1546. if ($doliurl) print '</a>';
  1547. print '</div>'."\n";
  1548. // Link to bugtrack
  1549. if (! empty($conf->global->MAIN_BUGTRACK_ENABLELINK))
  1550. {
  1551. require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
  1552. $bugbaseurl = 'https://github.com/Dolibarr/dolibarr/issues/new';
  1553. $bugbaseurl.= '?title=';
  1554. $bugbaseurl.= urlencode("Bug: ");
  1555. $bugbaseurl.= '&body=';
  1556. // FIXME: use .github/ISSUE_TEMPLATE.md to generate?
  1557. $bugbaseurl .= urlencode("# Bug\n");
  1558. $bugbaseurl .= urlencode("\n");
  1559. $bugbaseurl.= urlencode("## Environment\n");
  1560. $bugbaseurl.= urlencode("- **Version**: " . DOL_VERSION . "\n");
  1561. $bugbaseurl.= urlencode("- **OS**: " . php_uname('s') . "\n");
  1562. $bugbaseurl.= urlencode("- **Web server**: " . $_SERVER["SERVER_SOFTWARE"] . "\n");
  1563. $bugbaseurl.= urlencode("- **PHP**: " . php_sapi_name() . ' ' . phpversion() . "\n");
  1564. $bugbaseurl.= urlencode("- **Database**: " . $db::LABEL . ' ' . $db->getVersion() . "\n");
  1565. $bugbaseurl.= urlencode("- **URL**: " . $_SERVER["REQUEST_URI"] . "\n");
  1566. $bugbaseurl.= urlencode("\n");
  1567. $bugbaseurl.= urlencode("## Report\n");
  1568. print '<div id="blockvmenuhelpbugreport" class="blockvmenuhelp">';
  1569. print '<a class="help" target="_blank" href="'.$bugbaseurl.'">'.$langs->trans("FindBug").'</a>';
  1570. print '</div>';
  1571. }
  1572. print "</div>\n";
  1573. print "<!-- End Help Block-->\n";
  1574. print "\n";
  1575. print "</div>\n";
  1576. print "<!-- End left menu -->\n";
  1577. print "\n";
  1578. // Execute hook printLeftBlock
  1579. $parameters=array();
  1580. $reshook=$hookmanager->executeHooks('printLeftBlock',$parameters); // Note that $action and $object may have been modified by some hooks
  1581. print $hookmanager->resPrint;
  1582. if (empty($conf->dol_use_jmobile) && ! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT)) print '</div> <!-- End left layout -->'."\n";
  1583. else print '</div></div> <!-- end id-left -->'; // End div id="id-left"
  1584. }
  1585. print "\n";
  1586. print '<!-- Begin right area -->'."\n";
  1587. if (empty($leftmenuwithoutmainarea)) main_area($title);
  1588. }
  1589. /**
  1590. * Begin main area
  1591. *
  1592. * @param string $title Title
  1593. * @return void
  1594. */
  1595. function main_area($title='')
  1596. {
  1597. global $conf, $langs;
  1598. if (empty($conf->dol_use_jmobile) && ! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT)) print '<div id="mainContent"><div class="ui-layout-center"> <!-- begin main layout -->'."\n";
  1599. if (empty($conf->dol_hide_leftmenu)) print '<div id="id-right">';
  1600. print "\n";
  1601. if (! empty($conf->dol_use_jmobile)) print '<div data-role="page">';
  1602. print '<div class="fiche"> <!-- begin div class="fiche" -->'."\n";
  1603. if (! empty($conf->global->MAIN_ONLY_LOGIN_ALLOWED)) print info_admin($langs->trans("WarningYouAreInMaintenanceMode",$conf->global->MAIN_ONLY_LOGIN_ALLOWED));
  1604. }
  1605. /**
  1606. * Return helpbaseurl, helppage and mode
  1607. *
  1608. * @param string $helppagename Page name ('EN:xxx,ES:eee,FR:fff...' or 'http://localpage')
  1609. * @param Translate $langs Language
  1610. * @return array Array of help urls
  1611. */
  1612. function getHelpParamFor($helppagename,$langs)
  1613. {
  1614. $helpbaseurl='';
  1615. $helppage='';
  1616. $mode='';
  1617. if (preg_match('/^http/i',$helppagename))
  1618. {
  1619. // If complete URL
  1620. $helpbaseurl='%s';
  1621. $helppage=$helppagename;
  1622. $mode='local';
  1623. }
  1624. else
  1625. {
  1626. // If WIKI URL
  1627. if (preg_match('/^es/i',$langs->defaultlang))
  1628. {
  1629. $helpbaseurl='http://wiki.dolibarr.org/index.php/%s';
  1630. if (preg_match('/ES:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1];
  1631. }
  1632. if (preg_match('/^fr/i',$langs->defaultlang))
  1633. {
  1634. $helpbaseurl='http://wiki.dolibarr.org/index.php/%s';
  1635. if (preg_match('/FR:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1];
  1636. }
  1637. if (empty($helppage)) // If help page not already found
  1638. {
  1639. $helpbaseurl='http://wiki.dolibarr.org/index.php/%s';
  1640. if (preg_match('/EN:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1];
  1641. }
  1642. $mode='wiki';
  1643. }
  1644. return array('helpbaseurl'=>$helpbaseurl,'helppage'=>$helppage,'mode'=>$mode);
  1645. }
  1646. /**
  1647. * Show a search area
  1648. *
  1649. * @param string $urlaction Url post
  1650. * @param string $urlobject Url of the link under the search box
  1651. * @param string $title Title search area
  1652. * @param string $htmlmodesearch Value to set into parameter "mode_search" ('soc','contact','products','member',...)
  1653. * @param string $htmlinputname Field Name input form
  1654. * @param string $accesskey Accesskey
  1655. * @param string $prefhtmlinputname Complement for id to avoid multiple same id in the page
  1656. * @param string $img Image to use
  1657. * @return string
  1658. */
  1659. function printSearchForm($urlaction,$urlobject,$title,$htmlmodesearch,$htmlinputname,$accesskey='', $prefhtmlinputname='',$img='')
  1660. {
  1661. global $conf,$langs;
  1662. if (empty($htmlinputid)) {
  1663. $htmlinputid = $htmlinputname;
  1664. }
  1665. $ret='';
  1666. $ret.='<form action="'.$urlaction.'" method="post" class="searchform">';
  1667. $ret.='<div class="menu_titre menu_titre_search"';
  1668. if (! empty($conf->global->MAIN_HTML5_PLACEHOLDER)) $ret.=' style="display: inline-block"';
  1669. $ret.='>';
  1670. $ret.='<label for="'.$prefhtmlinputname.$htmlinputname.'">';
  1671. $ret.='<a class="vsmenu" href="'.$urlobject.'">';
  1672. if ($img && ! empty($conf->global->MAIN_HTML5_PLACEHOLDER)) $ret.=$img;
  1673. else $ret.=$img.' '.$title;
  1674. $ret.='</a>';
  1675. $ret.='</label>';
  1676. $ret.='</div>';
  1677. $ret.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  1678. $ret.='<input type="hidden" name="mode" value="search">';
  1679. $ret.='<input type="hidden" name="mode_search" value="'.$htmlmodesearch.'">';
  1680. $ret.='<input type="text" class="flat"';
  1681. $ret.=($accesskey?' accesskey="'.$accesskey.'"':'');
  1682. if (! empty($conf->global->MAIN_HTML5_PLACEHOLDER)) $ret.=' placeholder="'.strip_tags($title).'"'; // Will work only if MAIN_HTML5_PLACEHOLDER is set to 1
  1683. else $ret.=' title="'.$langs->trans("SearchOf").''.strip_tags($title).'"';
  1684. $ret.=' name="'.$htmlinputname.'" id="'.$prefhtmlinputname.$htmlinputname.'" size="10" />';
  1685. $ret.='<input type="submit" class="button" style="padding-top: 4px; padding-bottom: 4px; padding-left: 6px; padding-right: 6px" value="'.$langs->trans("Go").'">';
  1686. $ret.="</form>\n";
  1687. return $ret;
  1688. }
  1689. if (! function_exists("llxFooter"))
  1690. {
  1691. /**
  1692. * Show HTML footer
  1693. * Close div /DIV data-role=page + /DIV class=fiche + /DIV /DIV main layout + /BODY + /HTML.
  1694. * If global var $delayedhtmlcontent was filled, we output it just before closing the body.
  1695. *
  1696. * @param string $comment A text to add as HTML comment into HTML generated page
  1697. * @param string $zone 'private' (for private pages) or 'public' (for public pages)
  1698. * @return void
  1699. */
  1700. function llxFooter($comment='',$zone='private')
  1701. {
  1702. global $conf, $langs;
  1703. global $delayedhtmlcontent;
  1704. // Global html output events ($mesgs, $errors, $warnings)
  1705. dol_htmloutput_events();
  1706. // Core error message
  1707. if (defined("MAIN_CORE_ERROR") && constant("MAIN_CORE_ERROR") == 1)
  1708. {
  1709. // Ajax version
  1710. if ($conf->use_javascript_ajax)
  1711. {
  1712. $title = img_warning().' '.$langs->trans('CoreErrorTitle');
  1713. print ajax_dialog($title, $langs->trans('CoreErrorMessage'));
  1714. }
  1715. // html version
  1716. else
  1717. {
  1718. $msg = img_warning().' '.$langs->trans('CoreErrorMessage');
  1719. print '<div class="error">'.$msg.'</div>';
  1720. }
  1721. define("MAIN_CORE_ERROR",0);
  1722. }
  1723. print "\n\n";
  1724. print '</div> <!-- End div class="fiche" -->'."\n";
  1725. if (! empty($conf->dol_use_jmobile)) print '</div>'; // end data-role="page"
  1726. if (empty($conf->dol_use_jmobile) && ! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT)) print '</div></div> <!-- end main layout -->'."\n";
  1727. if (empty($conf->dol_hide_leftmenu)) print '</div> <!-- End div id-right -->'; // End div id-right
  1728. print "\n";
  1729. if ($comment) print '<!-- '.$comment.' -->'."\n";
  1730. printCommonFooter($zone);
  1731. //var_dump($langs); // Uncommment to see the property _tab_loaded to see which language file were loaded
  1732. if (empty($conf->dol_hide_leftmenu) && empty($conf->dol_use_jmobile) && empty($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT)) print '</div> <!-- End div id-container -->'."\n"; // End div container
  1733. if (! empty($delayedhtmlcontent)) print $delayedhtmlcontent;
  1734. // Wrapper to show tooltips
  1735. if ($conf->use_javascript_ajax)
  1736. {
  1737. print "\n<!-- JS CODE TO ENABLE tipTip on all object with class classfortooltip -->\n";
  1738. print '<script type="text/javascript">
  1739. jQuery(document).ready(function () {
  1740. jQuery(".classfortooltip").tipTip({maxWidth: "'.dol_size(600,'width').'px", edgeOffset: 10, delay: 50, fadeIn: 50, fadeOut: 50});
  1741. });
  1742. </script>' . "\n";
  1743. }
  1744. // A div for the address popup
  1745. print "\n<!-- A div to allow dialog popup -->\n";
  1746. print '<div id="dialogforpopup" style="display: none;"></div>'."\n";
  1747. print "</body>\n";
  1748. print "</html>\n";
  1749. }
  1750. }