main.inc.php 88 KB

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