1<?php 2/* Copyright (C) 2004 Rodolphe Quiedeville <rodolphe@quiedeville.org> 3 * Copyright (C) 2004-2010 Laurent Destailleur <eldy@users.sourceforge.net> 4 * Copyright (C) 2015 Cedric GROSS <c.gross@kreiz-it.fr> 5 * Copyright (C) 2015-2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <https://www.gnu.org/licenses/>. 19 */ 20 21/** 22 * \file htdocs/install/step2.php 23 * \ingroup install 24 * \brief Create tables, primary keys, foreign keys, indexes and functions into database and then load reference data 25 */ 26 27include 'inc.php'; 28require_once $dolibarr_main_document_root.'/core/class/conf.class.php'; 29require_once $dolibarr_main_document_root.'/core/lib/admin.lib.php'; 30 31global $langs; 32 33$step = 2; 34$ok = 0; 35 36 37// Cette page peut etre longue. On augmente le delai autorise. 38// Ne fonctionne que si on est pas en safe_mode. 39$err = error_reporting(); 40error_reporting(0); // Disable all errors 41//error_reporting(E_ALL); 42@set_time_limit(1800); // Need 1800 on some very slow OS like Windows 7/64 43error_reporting($err); 44 45$action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : (empty($argv[1]) ? '' : $argv[1]); 46$setuplang = GETPOST('selectlang', 'aZ09', 3) ?GETPOST('selectlang', 'aZ09', 3) : (empty($argv[2]) ? 'auto' : $argv[2]); 47$langs->setDefaultLang($setuplang); 48 49$langs->loadLangs(array("admin", "install")); 50 51$choix = 0; 52if ($dolibarr_main_db_type == "mysqli") { 53 $choix = 1; 54} 55if ($dolibarr_main_db_type == "pgsql") { 56 $choix = 2; 57} 58if ($dolibarr_main_db_type == "mssql") { 59 $choix = 3; 60} 61if ($dolibarr_main_db_type == "sqlite") { 62 $choix = 4; 63} 64if ($dolibarr_main_db_type == "sqlite3") { 65 $choix = 5; 66} 67 68//if (empty($choix)) dol_print_error('','Database type '.$dolibarr_main_db_type.' not supported into step2.php page'); 69 70// Now we load forced values from install.forced.php file. 71$useforcedwizard = false; 72$forcedfile = "./install.forced.php"; 73if ($conffile == "/etc/dolibarr/conf.php") { 74 $forcedfile = "/etc/dolibarr/install.forced.php"; 75} 76if (@file_exists($forcedfile)) { 77 $useforcedwizard = true; 78 include_once $forcedfile; 79 // test for travis 80 if (!empty($argv[1]) && $argv[1] == "set") { 81 $action = "set"; 82 } 83} 84 85dolibarr_install_syslog("- step2: entering step2.php page"); 86 87 88/* 89 * View 90 */ 91 92pHeader($langs->trans("CreateDatabaseObjects"), "step4"); 93 94// Test if we can run a first install process 95if (!is_writable($conffile)) { 96 print $langs->trans("ConfFileIsNotWritable", $conffiletoshow); 97 pFooter(1, $setuplang, 'jscheckparam'); 98 exit; 99} 100 101if ($action == "set") { 102 print '<h3><img class="valignmiddle inline-block paddingright" src="../theme/common/octicons/build/svg/database.svg" width="20" alt="Database"> '.$langs->trans("Database").'</h3>'; 103 104 print '<table cellspacing="0" style="padding: 4px 4px 4px 0" border="0" width="100%">'; 105 $error = 0; 106 107 $db = getDoliDBInstance($conf->db->type, $conf->db->host, $conf->db->user, $conf->db->pass, $conf->db->name, $conf->db->port); 108 109 if ($db->connected) { 110 print "<tr><td>"; 111 print $langs->trans("ServerConnection")." : ".$conf->db->host.'</td><td><img src="../theme/eldy/img/tick.png" alt="Ok"></td></tr>'; 112 $ok = 1; 113 } else { 114 print "<tr><td>Failed to connect to server : ".$conf->db->host.'</td><td><img src="../theme/eldy/img/error.png" alt="Error"></td></tr>'; 115 } 116 117 if ($ok) { 118 if ($db->database_selected) { 119 dolibarr_install_syslog("step2: successful connection to database: ".$conf->db->name); 120 } else { 121 dolibarr_install_syslog("step2: failed connection to database :".$conf->db->name, LOG_ERR); 122 print "<tr><td>Failed to select database ".$conf->db->name.'</td><td><img src="../theme/eldy/img/error.png" alt="Error"></td></tr>'; 123 $ok = 0; 124 } 125 } 126 127 128 // Affiche version 129 if ($ok) { 130 $version = $db->getVersion(); 131 $versionarray = $db->getVersionArray(); 132 print '<tr><td>'.$langs->trans("DatabaseVersion").'</td>'; 133 print '<td>'.$version.'</td></tr>'; 134 //print '<td class="right">'.join('.',$versionarray).'</td></tr>'; 135 136 print '<tr><td>'.$langs->trans("DatabaseName").'</td>'; 137 print '<td>'.$db->database_name.'</td></tr>'; 138 //print '<td class="right">'.join('.',$versionarray).'</td></tr>'; 139 } 140 141 $requestnb = 0; 142 143 // To disable some code, so you can call step2 with url like 144 // http://localhost/dolibarrnew/install/step2.php?action=set&createtables=0&createkeys=0&createfunctions=0&createdata=llx_20_c_departements 145 $createtables = isset($_GET['createtables']) ?GETPOST('createtables') : 1; 146 $createkeys = isset($_GET['createkeys']) ?GETPOST('createkeys') : 1; 147 $createfunctions = isset($_GET['createfunctions']) ?GETPOST('createfunction') : 1; 148 $createdata = isset($_GET['createdata']) ?GETPOST('createdata') : 1; 149 150 151 // To say sql requests are escaped for mysql so we need to unescape them 152 $db->unescapeslashquot = true; 153 154 155 /************************************************************************************** 156 * 157 * Chargement fichiers tables/*.sql (non *.key.sql) 158 * A faire avant les fichiers *.key.sql 159 * 160 ***************************************************************************************/ 161 if ($ok && $createtables) { 162 // We always choose in mysql directory (Conversion is done by driver to translate SQL syntax) 163 $dir = "mysql/tables/"; 164 165 $ok = 0; 166 $handle = opendir($dir); 167 dolibarr_install_syslog("step2: open tables directory ".$dir." handle=".$handle); 168 $tablefound = 0; 169 $tabledata = array(); 170 if (is_resource($handle)) { 171 while (($file = readdir($handle)) !== false) { 172 if (preg_match('/\.sql$/i', $file) && preg_match('/^llx_/i', $file) && !preg_match('/\.key\.sql$/i', $file)) { 173 $tablefound++; 174 $tabledata[] = $file; 175 } 176 } 177 closedir($handle); 178 } 179 180 // Sort list of sql files on alphabetical order (load order is important) 181 sort($tabledata); 182 foreach ($tabledata as $file) { 183 $name = substr($file, 0, dol_strlen($file) - 4); 184 $buffer = ''; 185 $fp = fopen($dir.$file, "r"); 186 if ($fp) { 187 while (!feof($fp)) { 188 $buf = fgets($fp, 4096); 189 if (substr($buf, 0, 2) <> '--') { 190 $buf = preg_replace('/--(.+)*/', '', $buf); 191 $buffer .= $buf; 192 } 193 } 194 fclose($fp); 195 196 $buffer = trim($buffer); 197 if ($conf->db->type == 'mysql' || $conf->db->type == 'mysqli') { // For Mysql 5.5+, we must replace type=innodb with ENGINE=innodb 198 $buffer = preg_replace('/type=innodb/i', 'ENGINE=innodb', $buffer); 199 } else { 200 // Keyword ENGINE is MySQL-specific, so scrub it for 201 // other database types (mssql, pgsql) 202 $buffer = preg_replace('/type=innodb/i', '', $buffer); 203 $buffer = preg_replace('/ENGINE=innodb/i', '', $buffer); 204 } 205 206 // Replace the prefix tables 207 if ($dolibarr_main_db_prefix != 'llx_') { 208 $buffer = preg_replace('/llx_/i', $dolibarr_main_db_prefix, $buffer); 209 } 210 211 //print "<tr><td>Creation de la table $name/td>"; 212 $requestnb++; 213 214 dolibarr_install_syslog("step2: request: ".$buffer); 215 $resql = $db->query($buffer, 0, 'dml'); 216 if ($resql) { 217 // print "<td>OK requete ==== $buffer</td></tr>"; 218 $db->free($resql); 219 } else { 220 if ($db->errno() == 'DB_ERROR_TABLE_ALREADY_EXISTS' || 221 $db->errno() == 'DB_ERROR_TABLE_OR_KEY_ALREADY_EXISTS') { 222 //print "<td>Deja existante</td></tr>"; 223 } else { 224 print "<tr><td>".$langs->trans("CreateTableAndPrimaryKey", $name); 225 print "<br>\n".$langs->trans("Request").' '.$requestnb.' : '.$buffer.' <br>Executed query : '.$db->lastquery; 226 print "\n</td>"; 227 print '<td><span class="error">'.$langs->trans("ErrorSQL")." ".$db->errno()." ".$db->error().'</span></td></tr>'; 228 $error++; 229 } 230 } 231 } else { 232 print "<tr><td>".$langs->trans("CreateTableAndPrimaryKey", $name); 233 print "</td>"; 234 print '<td><span class="error">'.$langs->trans("Error").' Failed to open file '.$dir.$file.'</span></td></tr>'; 235 $error++; 236 dolibarr_install_syslog("step2: failed to open file ".$dir.$file, LOG_ERR); 237 } 238 } 239 240 if ($tablefound) { 241 if ($error == 0) { 242 print '<tr><td>'; 243 print $langs->trans("TablesAndPrimaryKeysCreation").'</td><td><img src="../theme/eldy/img/tick.png" alt="Ok"></td></tr>'; 244 $ok = 1; 245 } 246 } else { 247 print '<tr><td>'.$langs->trans("ErrorFailedToFindSomeFiles", $dir).'</td><td><img src="../theme/eldy/img/error.png" alt="Error"></td></tr>'; 248 dolibarr_install_syslog("step2: failed to find files to create database in directory ".$dir, LOG_ERR); 249 } 250 } 251 252 253 /*************************************************************************************** 254 * 255 * Chargement fichiers tables/*.key.sql 256 * A faire apres les fichiers *.sql 257 * 258 ***************************************************************************************/ 259 if ($ok && $createkeys) { 260 // We always choose in mysql directory (Conversion is done by driver to translate SQL syntax) 261 $dir = "mysql/tables/"; 262 263 $okkeys = 0; 264 $handle = opendir($dir); 265 dolibarr_install_syslog("step2: open keys directory ".$dir." handle=".$handle); 266 $tablefound = 0; 267 $tabledata = array(); 268 if (is_resource($handle)) { 269 while (($file = readdir($handle)) !== false) { 270 if (preg_match('/\.sql$/i', $file) && preg_match('/^llx_/i', $file) && preg_match('/\.key\.sql$/i', $file)) { 271 $tablefound++; 272 $tabledata[] = $file; 273 } 274 } 275 closedir($handle); 276 } 277 278 // Sort list of sql files on alphabetical order (load order is important) 279 sort($tabledata); 280 foreach ($tabledata as $file) { 281 $name = substr($file, 0, dol_strlen($file) - 4); 282 //print "<tr><td>Creation de la table $name</td>"; 283 $buffer = ''; 284 $fp = fopen($dir.$file, "r"); 285 if ($fp) { 286 while (!feof($fp)) { 287 $buf = fgets($fp, 4096); 288 289 // Special case of lines allowed for some version only 290 if ($choix == 1 && preg_match('/^--\sV([0-9\.]+)/i', $buf, $reg)) { 291 $versioncommande = explode('.', $reg[1]); 292 //print var_dump($versioncommande); 293 //print var_dump($versionarray); 294 if (count($versioncommande) && count($versionarray) 295 && versioncompare($versioncommande, $versionarray) <= 0) { 296 // Version qualified, delete SQL comments 297 $buf = preg_replace('/^--\sV([0-9\.]+)/i', '', $buf); 298 //print "Ligne $i qualifiee par version: ".$buf.'<br>'; 299 } 300 } 301 if ($choix == 2 && preg_match('/^--\sPOSTGRESQL\sV([0-9\.]+)/i', $buf, $reg)) { 302 $versioncommande = explode('.', $reg[1]); 303 //print var_dump($versioncommande); 304 //print var_dump($versionarray); 305 if (count($versioncommande) && count($versionarray) 306 && versioncompare($versioncommande, $versionarray) <= 0) { 307 // Version qualified, delete SQL comments 308 $buf = preg_replace('/^--\sPOSTGRESQL\sV([0-9\.]+)/i', '', $buf); 309 //print "Ligne $i qualifiee par version: ".$buf.'<br>'; 310 } 311 } 312 313 // Ajout ligne si non commentaire 314 if (!preg_match('/^--/i', $buf)) { 315 $buffer .= $buf; 316 } 317 } 318 fclose($fp); 319 320 // Si plusieurs requetes, on boucle sur chaque 321 $listesql = explode(';', $buffer); 322 foreach ($listesql as $req) { 323 $buffer = trim($req); 324 if ($buffer) { 325 // Replace the prefix tables 326 if ($dolibarr_main_db_prefix != 'llx_') { 327 $buffer = preg_replace('/llx_/i', $dolibarr_main_db_prefix, $buffer); 328 } 329 330 //print "<tr><td>Creation des cles et index de la table $name: '$buffer'</td>"; 331 $requestnb++; 332 333 dolibarr_install_syslog("step2: request: ".$buffer); 334 $resql = $db->query($buffer, 0, 'dml'); 335 if ($resql) { 336 //print "<td>OK requete ==== $buffer</td></tr>"; 337 $db->free($resql); 338 } else { 339 if ($db->errno() == 'DB_ERROR_KEY_NAME_ALREADY_EXISTS' || 340 $db->errno() == 'DB_ERROR_CANNOT_CREATE' || 341 $db->errno() == 'DB_ERROR_PRIMARY_KEY_ALREADY_EXISTS' || 342 $db->errno() == 'DB_ERROR_TABLE_OR_KEY_ALREADY_EXISTS' || 343 preg_match('/duplicate key name/i', $db->error())) { 344 //print "<td>Deja existante</td></tr>"; 345 $key_exists = 1; 346 } else { 347 print "<tr><td>".$langs->trans("CreateOtherKeysForTable", $name); 348 print "<br>\n".$langs->trans("Request").' '.$requestnb.' : '.$db->lastqueryerror(); 349 print "\n</td>"; 350 print '<td><span class="error">'.$langs->trans("ErrorSQL")." ".$db->errno()." ".$db->error().'</span></td></tr>'; 351 $error++; 352 } 353 } 354 } 355 } 356 } else { 357 print "<tr><td>".$langs->trans("CreateOtherKeysForTable", $name); 358 print "</td>"; 359 print '<td><span class="error">'.$langs->trans("Error")." Failed to open file ".$dir.$file."</span></td></tr>"; 360 $error++; 361 dolibarr_install_syslog("step2: failed to open file ".$dir.$file, LOG_ERR); 362 } 363 } 364 365 if ($tablefound && $error == 0) { 366 print '<tr><td>'; 367 print $langs->trans("OtherKeysCreation").'</td><td><img src="../theme/eldy/img/tick.png" alt="Ok"></td></tr>'; 368 $okkeys = 1; 369 } 370 } 371 372 373 /*************************************************************************************** 374 * 375 * Chargement fichier functions.sql 376 * 377 ***************************************************************************************/ 378 if ($ok && $createfunctions) { 379 // For this file, we use a directory according to database type 380 if ($choix == 1) { 381 $dir = "mysql/functions/"; 382 } elseif ($choix == 2) { 383 $dir = "pgsql/functions/"; 384 } elseif ($choix == 3) { 385 $dir = "mssql/functions/"; 386 } elseif ($choix == 4) { 387 $dir = "sqlite3/functions/"; 388 } 389 390 // Creation donnees 391 $file = "functions.sql"; 392 if (file_exists($dir.$file)) { 393 $fp = fopen($dir.$file, "r"); 394 dolibarr_install_syslog("step2: open function file ".$dir.$file." handle=".$fp); 395 if ($fp) { 396 $buffer = ''; 397 while (!feof($fp)) { 398 $buf = fgets($fp, 4096); 399 if (substr($buf, 0, 2) <> '--') { 400 $buffer .= $buf."§"; 401 } 402 } 403 fclose($fp); 404 } 405 //$buffer=preg_replace('/;\';/',";'§",$buffer); 406 407 // If several requests, we loop on each of them 408 $listesql = explode('§', $buffer); 409 foreach ($listesql as $buffer) { 410 $buffer = trim($buffer); 411 if ($buffer) { 412 // Replace the prefix in table names 413 if ($dolibarr_main_db_prefix != 'llx_') { 414 $buffer = preg_replace('/llx_/i', $dolibarr_main_db_prefix, $buffer); 415 } 416 dolibarr_install_syslog("step2: request: ".$buffer); 417 print "<!-- Insert line : ".$buffer."<br>-->\n"; 418 $resql = $db->query($buffer, 0, 'dml'); 419 if ($resql) { 420 $ok = 1; 421 $db->free($resql); 422 } else { 423 if ($db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS' 424 || $db->errno() == 'DB_ERROR_KEY_NAME_ALREADY_EXISTS') { 425 //print "Insert line : ".$buffer."<br>\n"; 426 } else { 427 $ok = 0; 428 429 print "<tr><td>".$langs->trans("FunctionsCreation"); 430 print "<br>\n".$langs->trans("Request").' '.$requestnb.' : '.$buffer; 431 print "\n</td>"; 432 print '<td><span class="error">'.$langs->trans("ErrorSQL")." ".$db->errno()." ".$db->error().'</span></td></tr>'; 433 $error++; 434 } 435 } 436 } 437 } 438 439 print "<tr><td>".$langs->trans("FunctionsCreation")."</td>"; 440 if ($ok) { 441 print '<td><img src="../theme/eldy/img/tick.png" alt="Ok"></td></tr>'; 442 } else { 443 print '<td><img src="../theme/eldy/img/error.png" alt="Error"></td></tr>'; 444 $ok = 1; 445 } 446 } 447 } 448 449 450 /*************************************************************************************** 451 * 452 * Load files data/*.sql 453 * 454 ***************************************************************************************/ 455 if ($ok && $createdata) { 456 // We always choose in mysql directory (Conversion is done by driver to translate SQL syntax) 457 $dir = "mysql/data/"; 458 459 // Insert data 460 $handle = opendir($dir); 461 dolibarr_install_syslog("step2: open directory data ".$dir." handle=".$handle); 462 $tablefound = 0; 463 $tabledata = array(); 464 if (is_resource($handle)) { 465 while (($file = readdir($handle)) !== false) { 466 if (preg_match('/\.sql$/i', $file) && preg_match('/^llx_/i', $file)) { 467 if (preg_match('/^llx_accounting_account_/', $file)) { 468 continue; // We discard data file of chart of account. Will be loaded when a chart is selected. 469 } 470 471 //print 'x'.$file.'-'.$createdata.'<br>'; 472 if (is_numeric($createdata) || preg_match('/'.preg_quote($createdata).'/i', $file)) { 473 $tablefound++; 474 $tabledata[] = $file; 475 } 476 } 477 } 478 closedir($handle); 479 } 480 481 // Sort list of data files on alphabetical order (load order is important) 482 sort($tabledata); 483 foreach ($tabledata as $file) { 484 $name = substr($file, 0, dol_strlen($file) - 4); 485 $fp = fopen($dir.$file, "r"); 486 dolibarr_install_syslog("step2: open data file ".$dir.$file." handle=".$fp); 487 if ($fp) { 488 $arrayofrequests = array(); 489 $linefound = 0; 490 $linegroup = 0; 491 $sizeofgroup = 1; // Grouping request to have 1 query for several requests does not works with mysql, so we use 1. 492 493 // Load all requests 494 while (!feof($fp)) { 495 $buffer = fgets($fp, 4096); 496 $buffer = trim($buffer); 497 if ($buffer) { 498 if (substr($buffer, 0, 2) == '--') { 499 continue; 500 } 501 502 if ($linefound && ($linefound % $sizeofgroup) == 0) { 503 $linegroup++; 504 } 505 if (empty($arrayofrequests[$linegroup])) { 506 $arrayofrequests[$linegroup] = $buffer; 507 } else { 508 $arrayofrequests[$linegroup] .= " ".$buffer; 509 } 510 511 $linefound++; 512 } 513 } 514 fclose($fp); 515 516 dolibarr_install_syslog("step2: found ".$linefound." records, defined ".count($arrayofrequests)." group(s)."); 517 518 $okallfile = 1; 519 $db->begin(); 520 521 // We loop on each requests of file 522 foreach ($arrayofrequests as $buffer) { 523 // Replace the prefix tables 524 if ($dolibarr_main_db_prefix != 'llx_') { 525 $buffer = preg_replace('/llx_/i', $dolibarr_main_db_prefix, $buffer); 526 } 527 528 //dolibarr_install_syslog("step2: request: " . $buffer); 529 $resql = $db->query($buffer, 1); 530 if ($resql) { 531 //$db->free($resql); // Not required as request we launch here does not return memory needs. 532 } else { 533 if ($db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { 534 //print "<tr><td>Insertion ligne : $buffer</td><td>"; 535 } else { 536 $ok = 0; 537 $okallfile = 0; 538 print '<span class="error">'.$langs->trans("ErrorSQL")." : ".$db->lasterrno()." - ".$db->lastqueryerror()." - ".$db->lasterror()."</span><br>"; 539 } 540 } 541 } 542 543 if ($okallfile) { 544 $db->commit(); 545 } else { 546 $db->rollback(); 547 } 548 } 549 } 550 551 print "<tr><td>".$langs->trans("ReferenceDataLoading")."</td>"; 552 if ($ok) { 553 print '<td><img src="../theme/eldy/img/tick.png" alt="Ok"></td></tr>'; 554 } else { 555 print '<td><img src="../theme/eldy/img/error.png" alt="Error"></td></tr>'; 556 $ok = 1; // Data loading are not blocking errors 557 } 558 } 559 print '</table>'; 560} else { 561 print 'Parameter action=set not defined'; 562} 563 564 565$ret = 0; 566if (!$ok && isset($argv[1])) { 567 $ret = 1; 568} 569dolibarr_install_syslog("Exit ".$ret); 570 571dolibarr_install_syslog("- step2: end"); 572 573 574$out = '<input type="checkbox" name="dolibarrpingno" id="dolibarrpingno" value="checked" checked="true"> '; 575$out .= '<label for="dolibarrpingno">'.$langs->trans("MakeAnonymousPing").'</label>'; 576 577$out .= '<!-- Add js script to manage the uncheck of option to not send the ping -->'; 578$out .= '<script type="text/javascript">'; 579$out .= 'jQuery(document).ready(function(){'; 580$out .= ' document.cookie = "DOLINSTALLNOPING_'.md5($dolibarr_main_instance_unique_id).'=0; path=/"'."\n"; 581$out .= ' jQuery("#dolibarrpingno").click(function() {'; 582$out .= ' if (! $(this).is(\':checked\')) {'; 583$out .= ' console.log("We uncheck anonymous ping");'; 584$out .= ' document.cookie = "DOLINSTALLNOPING_'.md5($dolibarr_main_instance_unique_id).'=1; path=/"'."\n"; 585$out .= ' }'; 586$out .= ' });'; 587$out .= '});'; 588$out .= '</script>'; 589 590print $out; 591 592pFooter($ok ? 0 : 1, $setuplang); 593 594if (isset($db) && is_object($db)) { 595 $db->close(); 596} 597 598// Return code if ran from command line 599if ($ret) { 600 exit($ret); 601} 602