PageRenderTime 66ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/admin/tools/export.php

https://bitbucket.org/speedealing/speedealing
PHP | 525 lines | 342 code | 77 blank | 106 comment | 123 complexity | bf25b97c67d2190828745d10a44d4aa6 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0, MIT
  1. <?php
  2. /* Copyright (C) 2006-2012 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /**
  19. * \file htdocs/admin/tools/export.php
  20. * \brief Page to export a database into a dump file
  21. */
  22. require '../../main.inc.php';
  23. require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
  24. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  25. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
  26. $langs->load("admin");
  27. $action=GETPOST('action','alpha');
  28. $what=GETPOST('what','alpha');
  29. $export_type=GETPOST('export_type','alpha');
  30. $file=GETPOST('filename_template','alpha');
  31. $sortfield = GETPOST('sortfield','alpha');
  32. $sortorder = GETPOST('sortorder','alpha');
  33. $page = GETPOST("page",'int');
  34. if (! $sortorder) $sortorder="DESC";
  35. if (! $sortfield) $sortfield="date";
  36. if ($page < 0) { $page = 0; }
  37. $limit = $conf->liste_limit;
  38. $offset = $limit * $page;
  39. if (! $user->admin) accessforbidden();
  40. if ($file && ! $what)
  41. {
  42. //print DOL_URL_ROOT.'/dolibarr_export.php';
  43. header("Location: ".DOL_URL_ROOT.'/admin/tools/dolibarr_export.php?msg='.urlencode($langs->trans("ErrorFieldRequired",$langs->transnoentities("ExportMethod"))));
  44. exit;
  45. }
  46. /*
  47. * Actions
  48. */
  49. if ($action == 'delete')
  50. {
  51. $file=$conf->admin->dir_output.'/backup/'.GETPOST('urlfile');
  52. $ret=dol_delete_file($file, 1);
  53. if ($ret) setEventMessage($langs->trans("FileWasRemoved", GETPOST('urlfile')));
  54. else setEventMessage($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), 'errors');
  55. $action='';
  56. }
  57. /*
  58. * View
  59. */
  60. // Increase limit of time. Works only if we are not in safe mode
  61. $ExecTimeLimit=600;
  62. if (!empty($ExecTimeLimit))
  63. {
  64. $err=error_reporting();
  65. error_reporting(0); // Disable all errors
  66. //error_reporting(E_ALL);
  67. @set_time_limit($ExecTimeLimit); // Need more than 240 on Windows 7/64
  68. error_reporting($err);
  69. }
  70. if (!empty($MemoryLimit))
  71. {
  72. @ini_set('memory_limit', $MemoryLimit);
  73. }
  74. $form=new Form($db);
  75. $formfile = new FormFile($db);
  76. llxHeader('','');
  77. print_fiche_titre($langs->trans("Backup"),'','setup');
  78. // Start with empty buffer
  79. $dump_buffer = '';
  80. $dump_buffer_len = 0;
  81. // We will send fake headers to avoid browser timeout when buffering
  82. $time_start = time();
  83. // MYSQL
  84. if ($what == 'mysql')
  85. {
  86. $cmddump=GETPOST("mysqldump"); // Do not sanitize here with 'alpha', will be sanitize later by escapeshellarg
  87. if ($cmddump)
  88. {
  89. //dolibarr_set_const($db, 'SYSTEMTOOLS_MYSQLDUMP', $cmddump,'chaine',0,'',$conf->entity);
  90. }
  91. $outputdir = $conf->admin->dir_output.'/backup';
  92. $outputfile = $outputdir.'/'.$file;
  93. // for compression format, we add extension
  94. $compression=GETPOST('compression') ? GETPOST('compression','alpha') : 'none';
  95. if ($compression == 'gz') $outputfile.='.gz';
  96. if ($compression == 'bz') $outputfile.='.bz2';
  97. $outputerror = $outputfile.'.err';
  98. dol_mkdir($conf->admin->dir_output.'/backup');
  99. // Parameteres execution
  100. $command=$cmddump;
  101. if (preg_match("/\s/",$command)) $command=escapeshellarg($command); // Use quotes on command
  102. //$param=escapeshellarg($dolibarr_main_db_name)." -h ".escapeshellarg($dolibarr_main_db_host)." -u ".escapeshellarg($dolibarr_main_db_user)." -p".escapeshellarg($dolibarr_main_db_pass);
  103. $param=$dolibarr_main_db_name." -h ".$dolibarr_main_db_host;
  104. $param.=" -u ".$dolibarr_main_db_user;
  105. if (! empty($dolibarr_main_db_port)) $param.=" -P ".$dolibarr_main_db_port;
  106. if (! GETPOST("use_transaction")) $param.=" -l --single-transaction";
  107. if (GETPOST("disable_fk")) $param.=" -K";
  108. if (GETPOST("sql_compat") && GETPOST("sql_compat") != 'NONE') $param.=" --compatible=".escapeshellarg(GETPOST("sql_compat","alpha"));
  109. if (GETPOST("drop_database")) $param.=" --add-drop-database";
  110. if (GETPOST("sql_structure"))
  111. {
  112. if (GETPOST("drop")) $param.=" --add-drop-table";
  113. }
  114. else
  115. {
  116. $param.=" -t";
  117. }
  118. if (GETPOST("disable-add-locks")) $param.=" --add-locks=FALSE";
  119. if (GETPOST("sql_data"))
  120. {
  121. $param.=" --tables";
  122. if (GETPOST("showcolumns")) $param.=" -c";
  123. if (GETPOST("extended_ins")) $param.=" -e";
  124. else $param.=" --skip-extended-insert";
  125. if (GETPOST("delayed")) $param.=" --delayed-insert";
  126. if (GETPOST("sql_ignore")) $param.=" --insert-ignore";
  127. if (GETPOST("hexforbinary")) $param.=" --hex-blob";
  128. }
  129. else
  130. {
  131. $param.=" -d"; // No row information (no data)
  132. }
  133. $param.=" --default-character-set=utf8"; // We always save output into utf8 charset
  134. $paramcrypted=$param;
  135. $paramclear=$param;
  136. if (! empty($dolibarr_main_db_pass))
  137. {
  138. $paramcrypted.=' -p"'.preg_replace('/./i','*',$dolibarr_main_db_pass).'"';
  139. $paramclear.=' -p"'.str_replace(array('"','`'),array('\"','\`'),$dolibarr_main_db_pass).'"';
  140. }
  141. print '<b>'.$langs->trans("RunCommandSummary").':</b><br>'."\n";
  142. print '<textarea rows="'.ROWS_2.'" cols="120">'.$command." ".$paramcrypted.'</textarea><br>'."\n";
  143. print '<br>';
  144. //print $paramclear;
  145. // Now run command and show result
  146. print '<b>'.$langs->trans("BackupResult").':</b> ';
  147. $errormsg='';
  148. $result=dol_mkdir($outputdir);
  149. // Debut appel methode execution
  150. $fullcommandcrypted=$command." ".$paramcrypted." 2>&1";
  151. $fullcommandclear=$command." ".$paramclear." 2>&1";
  152. if ($compression == 'none') $handle = fopen($outputfile, 'w');
  153. if ($compression == 'gz') $handle = gzopen($outputfile, 'w');
  154. if ($compression == 'bz') $handle = bzopen($outputfile, 'w');
  155. if ($handle)
  156. {
  157. $ok=0;
  158. dol_syslog("Run command ".$fullcommandcrypted);
  159. $handlein = popen($fullcommandclear, 'r');
  160. while (!feof($handlein))
  161. {
  162. $read = fgets($handlein);
  163. fwrite($handle,$read);
  164. if (preg_match('/'.preg_quote('-- Dump completed').'/i',$read)) $ok=1;
  165. elseif (preg_match('/'.preg_quote('SET SQL_NOTES=@OLD_SQL_NOTES').'/i',$read)) $ok=1;
  166. }
  167. pclose($handlein);
  168. if ($compression == 'none') fclose($handle);
  169. if ($compression == 'gz') gzclose($handle);
  170. if ($compression == 'bz') bzclose($handle);
  171. if (! empty($conf->global->MAIN_UMASK))
  172. @chmod($outputfile, octdec($conf->global->MAIN_UMASK));
  173. }
  174. else
  175. {
  176. $langs->load("errors");
  177. dol_syslog("Failed to open file ".$outputfile,LOG_ERR);
  178. $errormsg=$langs->trans("ErrorFailedToWriteInDir");
  179. }
  180. // Get errorstring
  181. if ($compression == 'none') $handle = fopen($outputfile, 'r');
  182. if ($compression == 'gz') $handle = gzopen($outputfile, 'r');
  183. if ($compression == 'bz') $handle = bzopen($outputfile, 'r');
  184. if ($handle)
  185. {
  186. // Get 2048 first chars of error message.
  187. $errormsg = fgets($handle,2048);
  188. // Close file
  189. if ($compression == 'none') fclose($handle);
  190. if ($compression == 'gz') gzclose($handle);
  191. if ($compression == 'bz') bzclose($handle);
  192. if ($ok && preg_match('/^-- MySql/i',$errormsg)) $errormsg=''; // Pas erreur
  193. else
  194. {
  195. // Renommer fichier sortie en fichier erreur
  196. //print "$outputfile -> $outputerror";
  197. @dol_delete_file($outputerror,1);
  198. @rename($outputfile,$outputerror);
  199. // Si safe_mode on et command hors du parametre exec, on a un fichier out vide donc errormsg vide
  200. if (! $errormsg)
  201. {
  202. $langs->load("errors");
  203. $errormsg=$langs->trans("ErrorFailedToRunExternalCommand");
  204. }
  205. }
  206. }
  207. // Fin execution commande
  208. }
  209. if ($what == 'mysqlnobin')
  210. {
  211. $outputdir = $conf->admin->dir_output.'/backup';
  212. $outputfile = $outputdir.'/'.$file;
  213. $outputfiletemp = $outputfile.'-TMP.sql';
  214. // for compression format, we add extension
  215. $compression=GETPOST('compression') ? GETPOST('compression','alpha') : 'none';
  216. if ($compression == 'gz') $outputfile.='.gz';
  217. if ($compression == 'bz') $outputfile.='.bz2';
  218. $outputerror = $outputfile.'.err';
  219. dol_mkdir($conf->admin->dir_output.'/backup');
  220. if ($compression == 'gz' or $compression == 'bz')
  221. {
  222. backup_tables($outputfiletemp);
  223. dol_compress_file($outputfiletemp, $outputfile, $compression);
  224. unlink($outputfiletemp);
  225. }
  226. else
  227. {
  228. backup_tables($outputfile);
  229. }
  230. }
  231. // POSTGRESQL
  232. if ($what == 'postgresql')
  233. {
  234. $cmddump=GETPOST("postgresqldump"); // Do not sanitize here with 'alpha', will be sanitize later by escapeshellarg
  235. if ($cmddump)
  236. {
  237. dolibarr_set_const($db, 'SYSTEMTOOLS_POSTGRESQLDUMP', $cmddump,'chaine',0,'',$conf->entity);
  238. }
  239. $outputdir = $conf->admin->dir_output.'/backup';
  240. $outputfile = $outputdir.'/'.$file;
  241. // for compression format, we add extension
  242. $compression=GETPOST('compression') ? GETPOST('compression','alpha') : 'none';
  243. if ($compression == 'gz') $outputfile.='.gz';
  244. if ($compression == 'bz') $outputfile.='.bz2';
  245. $outputerror = $outputfile.'.err';
  246. dol_mkdir($conf->admin->dir_output.'/backup');
  247. // Parameteres execution
  248. $command=$cmddump;
  249. if (preg_match("/\s/",$command)) $command=$command=escapeshellarg($command); // Use quotes on command
  250. //$param=escapeshellarg($dolibarr_main_db_name)." -h ".escapeshellarg($dolibarr_main_db_host)." -u ".escapeshellarg($dolibarr_main_db_user)." -p".escapeshellarg($dolibarr_main_db_pass);
  251. $param=" --no-tablespaces --inserts -h ".$dolibarr_main_db_host;
  252. $param.=" -U ".$dolibarr_main_db_user;
  253. if (! empty($dolibarr_main_db_port)) $param.=" -p ".$dolibarr_main_db_port;
  254. if (GETPOST("sql_compat") && GETPOST("sql_compat") == 'ANSI') $param.=" --disable-dollar-quoting";
  255. if (GETPOST("drop_database")) $param.=" -c -C";
  256. if (GETPOST("sql_structure"))
  257. {
  258. if (GETPOST("drop")) $param.=" --add-drop-table";
  259. if (! GETPOST("sql_data")) $param.=" -s";
  260. }
  261. if (GETPOST("sql_data"))
  262. {
  263. if (! GETPOST("sql_structure")) $param.=" -a";
  264. if (GETPOST("showcolumns")) $param.=" -c";
  265. }
  266. $param.=' -f "'.$outputfile.'"';
  267. //if ($compression == 'none')
  268. if ($compression == 'gz') $param.=' -Z 9';
  269. //if ($compression == 'bz')
  270. $paramcrypted=$param;
  271. $paramclear=$param;
  272. /*if (! empty($dolibarr_main_db_pass))
  273. {
  274. $paramcrypted.=" -W".preg_replace('/./i','*',$dolibarr_main_db_pass);
  275. $paramclear.=" -W".$dolibarr_main_db_pass;
  276. }*/
  277. $paramcrypted.=" -w ".$dolibarr_main_db_name;
  278. $paramclear.=" -w ".$dolibarr_main_db_name;
  279. print $langs->trans("RunCommandSummaryToLaunch").':<br>'."\n";
  280. print '<textarea rows="'.ROWS_3.'" cols="120">'.$command." ".$paramcrypted.'</textarea><br>'."\n";
  281. print '<br>';
  282. // Now show to ask to run command
  283. print $langs->trans("YouMustRunCommandFromCommandLineAfterLoginToUser",$dolibarr_main_db_user,$dolibarr_main_db_user);
  284. print '<br>';
  285. print '<br>';
  286. $what='';
  287. }
  288. // Si on a demande une generation
  289. if ($what)
  290. {
  291. if ($errormsg)
  292. {
  293. print '<div class="error">'.$langs->trans("Error")." : ".$errormsg.'</div>';
  294. // print '<a href="'.DOL_URL_ROOT.$relativepatherr.'">'.$langs->trans("DownloadErrorFile").'</a><br>';
  295. print '<br>';
  296. print '<br>';
  297. }
  298. else
  299. {
  300. print '<div class="ok">';
  301. print $langs->trans("BackupFileSuccessfullyCreated").'.<br>';
  302. print $langs->trans("YouCanDownloadBackupFile");
  303. print '</div>';
  304. print '<br>';
  305. }
  306. }
  307. $filearray=dol_dir_list($conf->admin->dir_output.'/backup','files',0,'','',$sortfield,(strtolower($sortorder)=='asc'?SORT_ASC:SORT_DESC),1);
  308. $result=$formfile->list_of_documents($filearray,null,'systemtools','',1,'backup/',1,0,($langs->trans("NoBackupFileAvailable").'<br>'.$langs->trans("ToBuildBackupFileClickHere",DOL_URL_ROOT.'/admin/tools/dolibarr_export.php')),0,$langs->trans("PreviousDumpFiles"));
  309. print '<br>';
  310. $time_end = time();
  311. print dol_fiche_end();
  312. llxFooter();
  313. $db->close();
  314. // MYSQL NO BINARIES (only php)
  315. /** Backup the db OR just a table without mysqldump binary (does not require any exec permission)
  316. * Author: David Walsh (http://davidwalsh.name/backup-mysql-database-php)
  317. * Updated and enhanced by Stephen Larroque (lrq3000) and by the many commentators from the blog
  318. * Note about foreign keys constraints: for Dolibarr, since there are a lot of constraints and when imported the tables will be inserted in the dumped order, not in constraints order, then we ABSOLUTELY need to use SET FOREIGN_KEY_CHECKS=0; when importing the sql dump.
  319. * Note2: db2SQL by Howard Yeend can be an alternative, by using SHOW FIELDS FROM and SHOW KEYS FROM we could generate a more precise dump (eg: by getting the type of the field and then precisely outputting the right formatting - in quotes, numeric or null - instead of trying to guess like we are doing now).
  320. *
  321. * @param string $outputfile Output file name
  322. * @param string $tables Table name or '*' for all
  323. * @return int <0 if KO, >0 if OK
  324. */
  325. function backup_tables($outputfile, $tables='*')
  326. {
  327. global $db, $langs;
  328. global $errormsg;
  329. // Set to UTF-8
  330. $db->query('SET NAMES utf8');
  331. $db->query('SET CHARACTER SET utf8');
  332. //get all of the tables
  333. if ($tables == '*')
  334. {
  335. $tables = array();
  336. $result = $db->query('SHOW FULL TABLES WHERE Table_type = \'BASE TABLE\'');
  337. while($row = $db->fetch_row($result))
  338. {
  339. $tables[] = $row[0];
  340. }
  341. }
  342. else
  343. {
  344. $tables = is_array($tables) ? $tables : explode(',',$tables);
  345. }
  346. //cycle through
  347. $handle = fopen($outputfile, 'w+');
  348. if (fwrite($handle, '') === FALSE)
  349. {
  350. $langs->load("errors");
  351. dol_syslog("Failed to open file ".$outputfile,LOG_ERR);
  352. $errormsg=$langs->trans("ErrorFailedToWriteInDir");
  353. return -1;
  354. }
  355. // Print headers and global mysql config vars
  356. $sqlhead = '';
  357. $sqlhead .= "-- ".getStaticMember($db, 'label')." dump via php
  358. --
  359. -- Host: ".$db->db->host_info." Database: ".$db->database_name."
  360. -- ------------------------------------------------------
  361. -- Server version ".$db->db->server_info."
  362. /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
  363. /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
  364. /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
  365. /*!40101 SET NAMES utf8 */;
  366. ";
  367. if (GETPOST("nobin_disable_fk")) $sqlhead .= "SET FOREIGN_KEY_CHECKS=0;\n";
  368. $sqlhead .= "SET SQL_MODE=\"NO_AUTO_VALUE_ON_ZERO\";\n";
  369. if (GETPOST("nobin_use_transaction")) $sqlhead .= "SET AUTOCOMMIT=0;\nSTART TRANSACTION;\n";
  370. fwrite($handle, $sqlhead);
  371. $ignore = '';
  372. if (GETPOST("nobin_sql_ignore")) $ignore = 'IGNORE ';
  373. $delayed = '';
  374. if (GETPOST("nobin_delayed")) $delayed = 'DELAYED ';
  375. // Process each table and print their definition + their datas
  376. foreach($tables as $table)
  377. {
  378. // Saving the table structure
  379. fwrite($handle, "\n--\n-- Table structure for table `".$table."`\n--\n");
  380. if (GETPOST("nobin_drop")) fwrite($handle,"DROP TABLE IF EXISTS `".$table."`;\n"); // Dropping table if exists prior to re create it
  381. //fwrite($handle,"/*!40101 SET @saved_cs_client = @@character_set_client */;\n");
  382. //fwrite($handle,"/*!40101 SET character_set_client = utf8 */;\n");
  383. $resqldrop=$db->query('SHOW CREATE TABLE '.$table);
  384. $row2 = $db->fetch_row($resqldrop);
  385. fwrite($handle,$row2[1].";\n");
  386. //fwrite($handle,"/*!40101 SET character_set_client = @saved_cs_client */;\n\n");
  387. // Dumping the data (locking the table and disabling the keys check while doing the process)
  388. fwrite($handle, "\n--\n-- Dumping data for table `".$table."`\n--\n");
  389. if (!GETPOST("nobin_nolocks")) fwrite($handle, "LOCK TABLES `".$table."` WRITE;\n"); // Lock the table before inserting data (when the data will be imported back)
  390. if (GETPOST("nobin_disable_fk")) fwrite($handle, "ALTER TABLE `".$table."` DISABLE KEYS;\n");
  391. $sql='SELECT * FROM '.$table;
  392. $result = $db->query($sql);
  393. $num_fields = $db->num_rows($result);
  394. while($row = $db->fetch_row($result)) {
  395. // For each row of data we print a line of INSERT
  396. fwrite($handle,'INSERT '.$delayed.$ignore.'INTO `'.$table.'` VALUES (');
  397. $columns = count($row);
  398. for($j=0; $j<$columns; $j++) {
  399. // Processing each columns of the row to ensure that we correctly save the value (eg: add quotes for string - in fact we add quotes for everything, it's easier)
  400. if ($row[$j] == null and !is_string($row[$j])) {
  401. // IMPORTANT: if the field is NULL we set it NULL
  402. $row[$j] = 'NULL';
  403. } elseif(is_string($row[$j]) and $row[$j] == '') {
  404. // if it's an empty string, we set it as an empty string
  405. $row[$j] = "''";
  406. } elseif(is_numeric($row[$j]) and !strcmp($row[$j], $row[$j]+0) ) { // test if it's a numeric type and the numeric version ($nb+0) == string version (eg: if we have 01, it's probably not a number but rather a string, else it would not have any leading 0)
  407. // if it's a number, we return it as-is
  408. $row[$j] = $row[$j];
  409. } else { // else for all other cases we escape the value and put quotes around
  410. $row[$j] = addslashes($row[$j]);
  411. $row[$j] = preg_replace("#\n#", "\\n", $row[$j]);
  412. $row[$j] = "'".$row[$j]."'";
  413. }
  414. }
  415. fwrite($handle,implode(',', $row).");\n");
  416. }
  417. if (GETPOST("nobin_disable_fk")) fwrite($handle, "ALTER TABLE `".$table."` ENABLE KEYS;\n"); // Enabling back the keys/index checking
  418. if (!GETPOST("nobin_nolocks")) fwrite($handle, "UNLOCK TABLES;\n"); // Unlocking the table
  419. fwrite($handle,"\n\n\n");
  420. }
  421. /* Backup Procedure structure*/
  422. /*
  423. $result = $db->query('SHOW PROCEDURE STATUS');
  424. if ($db->num_rows($result) > 0)
  425. {
  426. while ($row = $db->fetch_row($result)) { $procedures[] = $row[1]; }
  427. foreach($procedures as $proc)
  428. {
  429. fwrite($handle,"DELIMITER $$\n\n");
  430. fwrite($handle,"DROP PROCEDURE IF EXISTS '$name'.'$proc'$$\n");
  431. $resqlcreateproc=$db->query("SHOW CREATE PROCEDURE '$proc'");
  432. $row2 = $db->fetch_row($resqlcreateproc);
  433. fwrite($handle,"\n".$row2[2]."$$\n\n");
  434. fwrite($handle,"DELIMITER ;\n\n");
  435. }
  436. }
  437. */
  438. /* Backup Procedure structure*/
  439. // Write the footer (restore the previous database settings)
  440. $sqlfooter="\n\n";
  441. if (GETPOST("nobin_use_transaction")) $sqlfooter .= "COMMIT;\n";
  442. if (GETPOST("nobin_disable_fk")) $sqlfooter .= "SET FOREIGN_KEY_CHECKS=1;\n";
  443. $sqlfooter.="\n\n-- Dump completed on ".date('Y-m-d G-i-s');
  444. fwrite($handle, $sqlfooter);
  445. fclose($handle);
  446. return 1;
  447. }
  448. ?>