check.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. <?php
  2. /* Copyright (C) 2004-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2015 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
  5. * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
  6. * Copyright (C) 2013-2014 Juanjo Menent <jmenent@2byte.es>
  7. * Copyright (C) 2014 Marcos García <marcosgdf@gmail.com>
  8. * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. /**
  24. * \file htdocs/install/check.php
  25. * \ingroup install
  26. * \brief Test if file conf can be modified and if does not exists, test if install process can create it
  27. */
  28. include_once 'inc.php';
  29. $err = 0;
  30. $allowinstall = 0;
  31. $allowupgrade = false;
  32. $checksok = 1;
  33. $setuplang=GETPOST("selectlang",'',3)?GETPOST("selectlang",'',3):$langs->getDefaultLang();
  34. $langs->setDefaultLang($setuplang);
  35. $langs->load("install");
  36. // Now we load forced value from install.forced.php file.
  37. $useforcedwizard=false;
  38. $forcedfile="./install.forced.php";
  39. if ($conffile == "/etc/dolibarr/conf.php") $forcedfile="/etc/dolibarr/install.forced.php";
  40. if (@file_exists($forcedfile)) { $useforcedwizard=true; include_once $forcedfile; }
  41. dolibarr_install_syslog("--- check: Dolibarr install/upgrade process started");
  42. /*
  43. * View
  44. */
  45. pHeader('',''); // No next step for navigation buttons. Next step is defined by clik on links.
  46. //print "<br>\n";
  47. //print $langs->trans("InstallEasy")."<br><br>\n";
  48. print '<h3>'.$langs->trans("MiscellaneousChecks").":</h3>\n";
  49. // Check browser
  50. $useragent=$_SERVER['HTTP_USER_AGENT'];
  51. if (! empty($useragent))
  52. {
  53. $tmp=getBrowserInfo($_SERVER["HTTP_USER_AGENT"]);
  54. $browserversion=$tmp['browserversion'];
  55. $browsername=$tmp['browsername'];
  56. if ($browsername == 'ie' && $browserversion < 7) print '<img src="../theme/eldy/img/warning.png" alt="Error"> '.$langs->trans("WarningBrowserTooOld")."<br>\n";
  57. }
  58. // Check PHP version
  59. $arrayphpminversionerror = array(5,3,0);
  60. $arrayphpminversionwarning = array(5,3,0);
  61. if (versioncompare(versionphparray(),$arrayphpminversionerror) < 0) // Minimum to use (error if lower)
  62. {
  63. print '<img src="../theme/eldy/img/error.png" alt="Error"> '.$langs->trans("ErrorPHPVersionTooLow",'5.2.3');
  64. $checksok=0; // 0=error, 1=warning
  65. }
  66. else if (versioncompare(versionphparray(),$arrayphpminversionwarning) < 0) // Minimum supported (warning if lower)
  67. {
  68. print '<img src="../theme/eldy/img/warning.png" alt="Error"> '.$langs->trans("ErrorPHPVersionTooLow",'5.3.0');
  69. $checksok=0; // 0=error, 1=warning
  70. }
  71. else
  72. {
  73. print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("PHPVersion")." ".versiontostring(versionphparray());
  74. }
  75. if (empty($force_install_nophpinfo)) print ' (<a href="phpinfo.php" target="_blank">'.$langs->trans("MoreInformation").'</a>)';
  76. print "<br>\n";
  77. // Check PHP support for $_POST
  78. if (! isset($_GET["testget"]) && ! isset($_POST["testpost"]))
  79. {
  80. print '<img src="../theme/eldy/img/warning.png" alt="Warning"> '.$langs->trans("PHPSupportPOSTGETKo");
  81. print ' (<a href="'.$_SERVER["PHP_SELF"].'?testget=ok">'.$langs->trans("Recheck").'</a>)';
  82. print "<br>\n";
  83. $checksok=0;
  84. }
  85. else
  86. {
  87. print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("PHPSupportPOSTGETOk")."<br>\n";
  88. }
  89. // Check if sessions enabled
  90. if (! function_exists("session_id"))
  91. {
  92. print '<img src="../theme/eldy/img/error.png" alt="Error"> '.$langs->trans("ErrorPHPDoesNotSupportSessions")."<br>\n";
  93. $checksok=0;
  94. }
  95. else
  96. {
  97. print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("PHPSupportSessions")."<br>\n";
  98. }
  99. // Check if GD supported
  100. if (! function_exists("imagecreate"))
  101. {
  102. $langs->load("errors");
  103. print '<img src="../theme/eldy/img/warning.png" alt="Error"> '.$langs->trans("ErrorPHPDoesNotSupportGD")."<br>\n";
  104. // $checksok=0; // If image ko, just warning. So check must still be 1 (otherwise no way to install)
  105. }
  106. else
  107. {
  108. print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("PHPSupportGD")."<br>\n";
  109. }
  110. // Check if UTF8 supported
  111. if (! function_exists("utf8_encode"))
  112. {
  113. $langs->load("errors");
  114. print '<img src="../theme/eldy/img/warning.png" alt="Error"> '.$langs->trans("ErrorPHPDoesNotSupportUTF8")."<br>\n";
  115. // $checksok=0; // If image ko, just warning. So check must still be 1 (otherwise no way to install)
  116. }
  117. else
  118. {
  119. print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("PHPSupportUTF8")."<br>\n";
  120. }
  121. // Check memory
  122. $memrequiredorig='64M';
  123. $memrequired=64*1024*1024;
  124. $memmaxorig=@ini_get("memory_limit");
  125. $memmax=@ini_get("memory_limit");
  126. if ($memmaxorig != '')
  127. {
  128. preg_match('/([0-9]+)([a-zA-Z]*)/i',$memmax,$reg);
  129. if ($reg[2])
  130. {
  131. if (strtoupper($reg[2]) == 'G') $memmax=$reg[1]*1024*1024*1024;
  132. if (strtoupper($reg[2]) == 'M') $memmax=$reg[1]*1024*1024;
  133. if (strtoupper($reg[2]) == 'K') $memmax=$reg[1]*1024;
  134. }
  135. if ($memmax >= $memrequired || $memmax == -1)
  136. {
  137. print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("PHPMemoryOK",$memmaxorig,$memrequiredorig)."<br>\n";
  138. }
  139. else
  140. {
  141. print '<img src="../theme/eldy/img/warning.png" alt="Warning"> '.$langs->trans("PHPMemoryTooLow",$memmaxorig,$memrequiredorig)."<br>\n";
  142. }
  143. }
  144. // If config file present and filled
  145. clearstatcache();
  146. if (is_readable($conffile) && filesize($conffile) > 8)
  147. {
  148. dolibarr_install_syslog("check: conf file '" . $conffile . "' already defined");
  149. $confexists=1;
  150. include_once $conffile;
  151. $databaseok=1;
  152. if ($databaseok)
  153. {
  154. // Already installed for all parts (config and database). We can propose upgrade.
  155. $allowupgrade=true;
  156. }
  157. else
  158. {
  159. $allowupgrade=false;
  160. }
  161. }
  162. else
  163. {
  164. // If not, we create it
  165. dolibarr_install_syslog("check: we try to create conf file '" . $conffile . "'");
  166. $confexists=0;
  167. // First we try by copying example
  168. if (@copy($conffile.".example", $conffile))
  169. {
  170. // Success
  171. dolibarr_install_syslog("check: successfully copied file " . $conffile . ".example into " . $conffile);
  172. }
  173. else
  174. {
  175. // If failed, we try to create an empty file
  176. dolibarr_install_syslog("check: failed to copy file " . $conffile . ".example into " . $conffile . ". We try to create it.", LOG_WARNING);
  177. $fp = @fopen($conffile, "w");
  178. if ($fp)
  179. {
  180. @fwrite($fp, '<?php');
  181. @fputs($fp,"\n");
  182. fclose($fp);
  183. }
  184. else dolibarr_install_syslog("check: failed to create a new file " . $conffile . " into current dir " . getcwd() . ". Please check permissions.", LOG_ERR);
  185. }
  186. // First install, we can't upgrade
  187. $allowupgrade=false;
  188. }
  189. // File is missng and can't be created
  190. if (! file_exists($conffile))
  191. {
  192. print '<img src="../theme/eldy/img/error.png" alt="Error"> '.$langs->trans("ConfFileDoesNotExistsAndCouldNotBeCreated",$conffiletoshow);
  193. print "<br><br>";
  194. print $langs->trans("YouMustCreateWithPermission",$conffiletoshow);
  195. print "<br><br>";
  196. print $langs->trans("CorrectProblemAndReloadPage",$_SERVER['PHP_SELF'].'?testget=ok');
  197. $err++;
  198. }
  199. else
  200. {
  201. // File exists but can't be modified
  202. if (!is_writable($conffile))
  203. {
  204. if ($confexists)
  205. {
  206. print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("ConfFileExists",$conffiletoshow);
  207. }
  208. else
  209. {
  210. print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("ConfFileCouldBeCreated",$conffiletoshow);
  211. }
  212. print "<br>";
  213. print '<img src="../theme/eldy/img/tick.png" alt="Warning"> '.$langs->trans("ConfFileIsNotWritable",$conffiletoshow);
  214. print "<br>\n";
  215. $allowinstall=0;
  216. }
  217. // File exists and can be modified
  218. else
  219. {
  220. if ($confexists)
  221. {
  222. print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("ConfFileExists",$conffiletoshow);
  223. }
  224. else
  225. {
  226. print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("ConfFileCouldBeCreated",$conffiletoshow);
  227. }
  228. print "<br>";
  229. print '<img src="../theme/eldy/img/tick.png" alt="Ok"> '.$langs->trans("ConfFileIsWritable",$conffiletoshow);
  230. print "<br>\n";
  231. $allowinstall=1;
  232. }
  233. print "<br>\n";
  234. // Requirements ok, we display the next step button
  235. if ($checksok)
  236. {
  237. $ok=0;
  238. // Try to create db connection
  239. if (file_exists($conffile))
  240. {
  241. include_once $conffile;
  242. if (! empty($dolibarr_main_db_type) && ! empty($dolibarr_main_document_root))
  243. {
  244. if (! file_exists($dolibarr_main_document_root."/core/lib/admin.lib.php"))
  245. {
  246. print '<font class="error">A '.$conffiletoshow.' file exists with a dolibarr_main_document_root to '.$dolibarr_main_document_root.' that seems wrong. Try to fix or remove the '.$conffiletoshow.' file.</font><br>'."\n";
  247. dol_syslog("A '" . $conffiletoshow . "' file exists with a dolibarr_main_document_root to " . $dolibarr_main_document_root . " that seems wrong. Try to fix or remove the '" . $conffiletoshow . "' file.", LOG_WARNING);
  248. }
  249. else
  250. {
  251. require_once $dolibarr_main_document_root.'/core/lib/admin.lib.php';
  252. // $conf is already instancied inside inc.php
  253. $conf->db->type = $dolibarr_main_db_type;
  254. $conf->db->host = $dolibarr_main_db_host;
  255. $conf->db->port = $dolibarr_main_db_port;
  256. $conf->db->name = $dolibarr_main_db_name;
  257. $conf->db->user = $dolibarr_main_db_user;
  258. $conf->db->pass = $dolibarr_main_db_pass;
  259. $db=getDoliDBInstance($conf->db->type,$conf->db->host,$conf->db->user,$conf->db->pass,$conf->db->name,$conf->db->port);
  260. if ($db->connected && $db->database_selected)
  261. {
  262. $ok=true;
  263. }
  264. }
  265. }
  266. }
  267. // If a database access is available, we set more variable
  268. if ($ok)
  269. {
  270. if (empty($dolibarr_main_db_encryption)) $dolibarr_main_db_encryption=0;
  271. $conf->db->dolibarr_main_db_encryption = $dolibarr_main_db_encryption;
  272. if (empty($dolibarr_main_db_cryptkey)) $dolibarr_main_db_cryptkey='';
  273. $conf->db->dolibarr_main_db_cryptkey = $dolibarr_main_db_cryptkey;
  274. $conf->setValues($db);
  275. // Current version is $conf->global->MAIN_VERSION_LAST_UPGRADE
  276. // Version to install is DOL_VERSION
  277. $dolibarrlastupgradeversionarray=preg_split('/[\.-]/',isset($conf->global->MAIN_VERSION_LAST_UPGRADE) ? $conf->global->MAIN_VERSION_LAST_UPGRADE : (isset($conf->global->MAIN_VERSION_LAST_INSTALL)?$conf->global->MAIN_VERSION_LAST_INSTALL:''));
  278. $dolibarrversiontoinstallarray=versiondolibarrarray();
  279. }
  280. // Show title
  281. if (! empty($conf->global->MAIN_VERSION_LAST_UPGRADE) || ! empty($conf->global->MAIN_VERSION_LAST_INSTALL))
  282. {
  283. print $langs->trans("VersionLastUpgrade").': <b><font class="ok">'.(empty($conf->global->MAIN_VERSION_LAST_UPGRADE)?$conf->global->MAIN_VERSION_LAST_INSTALL:$conf->global->MAIN_VERSION_LAST_UPGRADE).'</font></b><br>';
  284. print $langs->trans("VersionProgram").': <b><font class="ok">'.DOL_VERSION.'</font></b>';
  285. //print ' '.img_warning($langs->trans("RunningUpdateProcessMayBeRequired"));
  286. print '<br>';
  287. print '<br>';
  288. }
  289. else print "<br>\n";
  290. print $langs->trans("InstallEasy")." ";
  291. print $langs->trans("ChooseYourSetupMode");
  292. print '<br /><br />';
  293. $foundrecommandedchoice=0;
  294. $available_choices = array();
  295. $notavailable_choices = array();
  296. // Show first install line
  297. $choice = '<tr class="listofchoices"><td class="listofchoices nowrap" align="center"><b>'.$langs->trans("FreshInstall").'</b>';
  298. $choice .= '</td>';
  299. $choice .= '<td class="listofchoices">';
  300. $choice .= $langs->trans("FreshInstallDesc");
  301. if (empty($dolibarr_main_db_host)) // This means install process was not run
  302. {
  303. $choice .= '<br>';
  304. //print $langs->trans("InstallChoiceRecommanded",DOL_VERSION,$conf->global->MAIN_VERSION_LAST_UPGRADE);
  305. $choice .= '<div class="center"><div class="ok">'.$langs->trans("InstallChoiceSuggested").'</div></div>';
  306. // <img src="../theme/eldy/img/tick.png" alt="Ok"> ';
  307. $foundrecommandedchoice=1; // To show only once
  308. }
  309. $choice .= '</td>';
  310. $choice .= '<td class="listofchoices" align="center">';
  311. if ($allowinstall)
  312. {
  313. $choice .= '<a class="button" href="fileconf.php?selectlang='.$setuplang.'">'.$langs->trans("Start").'</a>';
  314. }
  315. else
  316. {
  317. $choice .= $langs->trans("InstallNotAllowed");
  318. }
  319. $choice .= '</td>';
  320. $choice .= '</tr>'."\n";
  321. if ($allowinstall) {
  322. $available_choices[] = $choice;
  323. } else {
  324. $notavailable_choices[] = $choice;
  325. }
  326. // Show upgrade lines
  327. $allowupgrade=true;
  328. if (empty($dolibarr_main_db_host)) // This means install process was not run
  329. {
  330. $allowupgrade=false;
  331. }
  332. if (defined("MAIN_NOT_INSTALLED")) $allowupgrade=false;
  333. if (GETPOST('allowupgrade')) $allowupgrade=true;
  334. $migrationscript=array( array('from'=>'3.0.0', 'to'=>'3.1.0'),
  335. array('from'=>'3.1.0', 'to'=>'3.2.0'),
  336. array('from'=>'3.2.0', 'to'=>'3.3.0'),
  337. array('from'=>'3.3.0', 'to'=>'3.4.0'),
  338. array('from'=>'3.4.0', 'to'=>'3.5.0'),
  339. array('from'=>'3.5.0', 'to'=>'3.6.0'),
  340. array('from'=>'3.6.0', 'to'=>'3.7.0'),
  341. array('from'=>'3.7.0', 'to'=>'3.8.0'),
  342. array('from'=>'3.8.0', 'to'=>'3.9.0'),
  343. array('from'=>'3.9.0', 'to'=>'4.0.0'),
  344. array('from'=>'4.0.0', 'to'=>'5.0.0')
  345. );
  346. $count=0;
  347. foreach ($migrationscript as $migarray)
  348. {
  349. $choice = '';
  350. $count++;
  351. $recommended_choice = false;
  352. $version=DOL_VERSION;
  353. $versionfrom=$migarray['from'];
  354. $versionto=$migarray['to'];
  355. $versionarray=preg_split('/[\.-]/',$version);
  356. $dolibarrversionfromarray=preg_split('/[\.-]/',$versionfrom);
  357. $dolibarrversiontoarray=preg_split('/[\.-]/',$versionto);
  358. // Define string newversionxxx that are used for text to show
  359. $newversionfrom=preg_replace('/(\.[0-9]+)$/i','.*',$versionfrom);
  360. $newversionto=preg_replace('/(\.[0-9]+)$/i','.*',$versionto);
  361. $newversionfrombis='';
  362. if (versioncompare($dolibarrversiontoarray,$versionarray) < -2) // From x.y.z -> x.y.z+1
  363. {
  364. $newversionfrombis=' '.$langs->trans("or").' '.$versionto;
  365. }
  366. if ($ok)
  367. {
  368. if (count($dolibarrlastupgradeversionarray) >= 2) // If a database access is available and last upgrade version is known
  369. {
  370. // Now we check if this is the first qualified choice
  371. if ($allowupgrade && empty($foundrecommandedchoice) &&
  372. (versioncompare($dolibarrversiontoarray,$dolibarrlastupgradeversionarray) > 0 || versioncompare($dolibarrversiontoarray,$versionarray) < -2)
  373. )
  374. {
  375. $foundrecommandedchoice=1; // To show only once
  376. $recommended_choice = true;
  377. }
  378. }
  379. else {
  380. // We can not recommand a choice.
  381. // A version of install may be known, but we need last upgrade.
  382. }
  383. }
  384. $choice .= '<tr class="listofchoices '.($recommended_choice ? 'choiceselected' : '').'">';
  385. $choice .= '<td class="listofchoices nowrap" align="center"><b>'.$langs->trans("Upgrade").'<br>'.$newversionfrom.$newversionfrombis.' -> '.$newversionto.'</b></td>';
  386. $choice .= '<td class="listofchoices">';
  387. $choice .= $langs->trans("UpgradeDesc");
  388. if ($recommended_choice)
  389. {
  390. $choice .= '<br>';
  391. //print $langs->trans("InstallChoiceRecommanded",DOL_VERSION,$conf->global->MAIN_VERSION_LAST_UPGRADE);
  392. $choice .= '<div class="center"><div class="ok">'.$langs->trans("InstallChoiceSuggested").'</div>';
  393. if ($count < count($migarray)) // There is other choices after
  394. {
  395. print $langs->trans("MigrateIsDoneStepByStep",DOL_VERSION);
  396. }
  397. $choice .= '</div>';
  398. }
  399. $choice .= '</td>';
  400. $choice .= '<td class="listofchoices" align="center">';
  401. if ($allowupgrade)
  402. {
  403. // If it's not last updagre script, action = upgrade_tmp, if last action = upgrade
  404. $choice .= '<a class="button runupgrade" href="upgrade.php?action=upgrade'.($count<count($migrationscript)?'_'.$versionto:'').'&amp;selectlang='.$setuplang.'&amp;versionfrom='.$versionfrom.'&amp;versionto='.$versionto.'">'.$langs->trans("Start").'</a>';
  405. }
  406. else
  407. {
  408. $choice .= $langs->trans("NotAvailable");
  409. }
  410. $choice .= '</td>';
  411. $choice .= '</tr>'."\n";
  412. if ($allowupgrade) {
  413. $available_choices[] = $choice;
  414. } else {
  415. $notavailable_choices[] = $choice;
  416. }
  417. }
  418. // If there is no choice at all, we show all of them.
  419. if (empty($available_choices))
  420. {
  421. $available_choices=$notavailable_choices;
  422. $notavailable_choices=array();
  423. }
  424. // Array of install choices
  425. print '<table width="100%" class="listofchoices">';
  426. foreach ($available_choices as $choice) {
  427. print $choice;
  428. }
  429. print '</table>';
  430. if (count($notavailable_choices)) {
  431. print '<br />';
  432. print '<div id="AShowChoices">';
  433. print '<img src="../theme/eldy/img/1downarrow.png"> <a href="#">'.$langs->trans('ShowNotAvailableOptions').'</a>';
  434. print '</div>';
  435. print '<div id="navail_choices" style="display:none">';
  436. print '<br />';
  437. print '<table width="100%" class="listofchoices">';
  438. foreach ($notavailable_choices as $choice) {
  439. print $choice;
  440. }
  441. print '</table>';
  442. print '</div>';
  443. }
  444. }
  445. }
  446. print '<script type="text/javascript">
  447. $("div#AShowChoices a").click(function() {
  448. $("div#navail_choices").toggle();
  449. if ($("div#navail_choices").css("display") == "none") {
  450. $(this).text("'.$langs->trans('ShowNotAvailableOptions').'");
  451. $(this).parent().children("img").attr("src", "../theme/eldy/img/1downarrow.png");
  452. } else {
  453. $(this).text("'.$langs->trans('HideNotAvailableOptions').'");
  454. $(this).parent().children("img").attr("src", "../theme/eldy/img/1uparrow.png");
  455. }
  456. });
  457. /*
  458. $(".runupgrade").click(function() {
  459. return confirm("'.dol_escape_js($langs->transnoentitiesnoconv("WarningUpgrade"), 0, 1).'");
  460. });
  461. */
  462. </script>';
  463. dolibarr_install_syslog("--- check: end");
  464. pFooter(1); // Never display next button