PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/admin/tools/export.php

https://github.com/zeert/dolibarr
PHP | 526 lines | 353 code | 73 blank | 100 comment | 112 complexity | ffc45c462d3f51d305dcfc4aab5e6149 MD5 | raw file
Possible License(s): LGPL-2.0
  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 2 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");
  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. $help_url='EN:Backups|FR:Sauvegardes|ES:Copias_de_seguridad';
  77. llxHeader('','',$help_url);
  78. print_fiche_titre($langs->trans("Backup"),'','setup');
  79. // Start with empty buffer
  80. $dump_buffer = '';
  81. $dump_buffer_len = 0;
  82. // We will send fake headers to avoid browser timeout when buffering
  83. $time_start = time();
  84. // MYSQL
  85. if ($what == 'mysql')
  86. {
  87. $cmddump=GETPOST("mysqldump"); // Do not sanitize here with 'alpha', will be sanitize later by escapeshellarg
  88. if ($cmddump)
  89. {
  90. dolibarr_set_const($db, 'SYSTEMTOOLS_MYSQLDUMP', $cmddump,'chaine',0,'',$conf->entity);
  91. }
  92. $outputdir = $conf->admin->dir_output.'/backup';
  93. $outputfile = $outputdir.'/'.$file;
  94. // for compression format, we add extension
  95. $compression=GETPOST('compression') ? GETPOST('compression','alpha') : 'none';
  96. if ($compression == 'gz') $outputfile.='.gz';
  97. if ($compression == 'bz') $outputfile.='.bz2';
  98. $outputerror = $outputfile.'.err';
  99. dol_mkdir($conf->admin->dir_output.'/backup');
  100. // Parameteres execution
  101. $command=$cmddump;
  102. if (preg_match("/\s/",$command)) $command=escapeshellarg($command); // Use quotes on command
  103. //$param=escapeshellarg($dolibarr_main_db_name)." -h ".escapeshellarg($dolibarr_main_db_host)." -u ".escapeshellarg($dolibarr_main_db_user)." -p".escapeshellarg($dolibarr_main_db_pass);
  104. $param=$dolibarr_main_db_name." -h ".$dolibarr_main_db_host;
  105. $param.=" -u ".$dolibarr_main_db_user;
  106. if (! empty($dolibarr_main_db_port)) $param.=" -P ".$dolibarr_main_db_port;
  107. if (! GETPOST("use_transaction")) $param.=" -l --single-transaction";
  108. if (GETPOST("disable_fk")) $param.=" -K";
  109. if (GETPOST("sql_compat") && GETPOST("sql_compat") != 'NONE') $param.=" --compatible=".escapeshellarg(GETPOST("sql_compat","alpha"));
  110. if (GETPOST("drop_database")) $param.=" --add-drop-database";
  111. if (GETPOST("sql_structure"))
  112. {
  113. if (GETPOST("drop")) $param.=" --add-drop-table";
  114. }
  115. else
  116. {
  117. $param.=" -t";
  118. }
  119. if (GETPOST("disable-add-locks")) $param.=" --add-locks=FALSE";
  120. if (GETPOST("sql_data"))
  121. {
  122. $param.=" --tables";
  123. if (GETPOST("showcolumns")) $param.=" -c";
  124. if (GETPOST("extended_ins")) $param.=" -e";
  125. else $param.=" --skip-extended-insert";
  126. if (GETPOST("delayed")) $param.=" --delayed-insert";
  127. if (GETPOST("sql_ignore")) $param.=" --insert-ignore";
  128. if (GETPOST("hexforbinary")) $param.=" --hex-blob";
  129. }
  130. else
  131. {
  132. $param.=" -d"; // No row information (no data)
  133. }
  134. $param.=" --default-character-set=utf8"; // We always save output into utf8 charset
  135. $paramcrypted=$param;
  136. $paramclear=$param;
  137. if (! empty($dolibarr_main_db_pass))
  138. {
  139. $paramcrypted.=' -p"'.preg_replace('/./i','*',$dolibarr_main_db_pass).'"';
  140. $paramclear.=' -p"'.str_replace('"','\"',$dolibarr_main_db_pass).'"';
  141. }
  142. print '<b>'.$langs->trans("RunCommandSummary").':</b><br>'."\n";
  143. print '<textarea rows="'.ROWS_2.'" cols="120">'.$command." ".$paramcrypted.'</textarea><br>'."\n";
  144. print '<br>';
  145. //print $paramclear;
  146. // Now run command and show result
  147. print '<b>'.$langs->trans("BackupResult").':</b> ';
  148. $errormsg='';
  149. $result=dol_mkdir($outputdir);
  150. // Debut appel methode execution
  151. $fullcommandcrypted=$command." ".$paramcrypted." 2>&1";
  152. $fullcommandclear=$command." ".$paramclear." 2>&1";
  153. if ($compression == 'none') $handle = fopen($outputfile, 'w');
  154. if ($compression == 'gz') $handle = gzopen($outputfile, 'w');
  155. if ($compression == 'bz') $handle = bzopen($outputfile, 'w');
  156. if ($handle)
  157. {
  158. $ok=0;
  159. dol_syslog("Run command ".$fullcommandcrypted);
  160. $handlein = popen($fullcommandclear, 'r');
  161. while (!feof($handlein))
  162. {
  163. $read = fgets($handlein);
  164. fwrite($handle,$read);
  165. if (preg_match('/'.preg_quote('-- Dump completed').'/i',$read)) $ok=1;
  166. elseif (preg_match('/'.preg_quote('SET SQL_NOTES=@OLD_SQL_NOTES').'/i',$read)) $ok=1;
  167. }
  168. pclose($handlein);
  169. if ($compression == 'none') fclose($handle);
  170. if ($compression == 'gz') gzclose($handle);
  171. if ($compression == 'bz') bzclose($handle);
  172. if (! empty($conf->global->MAIN_UMASK))
  173. @chmod($outputfile, octdec($conf->global->MAIN_UMASK));
  174. }
  175. else
  176. {
  177. $langs->load("errors");
  178. dol_syslog("Failed to open file ".$outputfile,LOG_ERR);
  179. $errormsg=$langs->trans("ErrorFailedToWriteInDir");
  180. }
  181. // Get errorstring
  182. if ($compression == 'none') $handle = fopen($outputfile, 'r');
  183. if ($compression == 'gz') $handle = gzopen($outputfile, 'r');
  184. if ($compression == 'bz') $handle = bzopen($outputfile, 'r');
  185. if ($handle)
  186. {
  187. // Get 2048 first chars of error message.
  188. $errormsg = fgets($handle,2048);
  189. // Close file
  190. if ($compression == 'none') fclose($handle);
  191. if ($compression == 'gz') gzclose($handle);
  192. if ($compression == 'bz') bzclose($handle);
  193. if ($ok && preg_match('/^-- MySql/i',$errormsg)) $errormsg=''; // Pas erreur
  194. else
  195. {
  196. // Renommer fichier sortie en fichier erreur
  197. //print "$outputfile -> $outputerror";
  198. @dol_delete_file($outputerror,1);
  199. @rename($outputfile,$outputerror);
  200. // Si safe_mode on et command hors du parametre exec, on a un fichier out vide donc errormsg vide
  201. if (! $errormsg)
  202. {
  203. $langs->load("errors");
  204. $errormsg=$langs->trans("ErrorFailedToRunExternalCommand");
  205. }
  206. }
  207. }
  208. // Fin execution commande
  209. }
  210. if ($what == 'mysqlnobin')
  211. {
  212. $outputdir = $conf->admin->dir_output.'/backup';
  213. $outputfile = $outputdir.'/'.$file;
  214. $outputfiletemp = $outputfile.'-TMP.sql';
  215. // for compression format, we add extension
  216. $compression=GETPOST('compression') ? GETPOST('compression','alpha') : 'none';
  217. if ($compression == 'gz') $outputfile.='.gz';
  218. if ($compression == 'bz') $outputfile.='.bz2';
  219. $outputerror = $outputfile.'.err';
  220. dol_mkdir($conf->admin->dir_output.'/backup');
  221. if ($compression == 'gz' or $compression == 'bz')
  222. {
  223. backup_tables($outputfiletemp);
  224. dol_compress_file($outputfiletemp, $outputfile, $compression);
  225. unlink($outputfiletemp);
  226. }
  227. else
  228. {
  229. backup_tables($outputfile);
  230. }
  231. }
  232. // POSTGRESQL
  233. if ($what == 'postgresql')
  234. {
  235. $cmddump=GETPOST("postgresqldump"); // Do not sanitize here with 'alpha', will be sanitize later by escapeshellarg
  236. if ($cmddump)
  237. {
  238. dolibarr_set_const($db, 'SYSTEMTOOLS_POSTGRESQLDUMP', $cmddump,'chaine',0,'',$conf->entity);
  239. }
  240. $outputdir = $conf->admin->dir_output.'/backup';
  241. $outputfile = $outputdir.'/'.$file;
  242. // for compression format, we add extension
  243. $compression=GETPOST('compression') ? GETPOST('compression','alpha') : 'none';
  244. if ($compression == 'gz') $outputfile.='.gz';
  245. if ($compression == 'bz') $outputfile.='.bz2';
  246. $outputerror = $outputfile.'.err';
  247. dol_mkdir($conf->admin->dir_output.'/backup');
  248. // Parameteres execution
  249. $command=$cmddump;
  250. if (preg_match("/\s/",$command)) $command=$command=escapeshellarg($command); // Use quotes on command
  251. //$param=escapeshellarg($dolibarr_main_db_name)." -h ".escapeshellarg($dolibarr_main_db_host)." -u ".escapeshellarg($dolibarr_main_db_user)." -p".escapeshellarg($dolibarr_main_db_pass);
  252. $param=" --no-tablespaces --inserts -h ".$dolibarr_main_db_host;
  253. $param.=" -U ".$dolibarr_main_db_user;
  254. if (! empty($dolibarr_main_db_port)) $param.=" -p ".$dolibarr_main_db_port;
  255. if (GETPOST("sql_compat") && GETPOST("sql_compat") == 'ANSI') $param.=" --disable-dollar-quoting";
  256. if (GETPOST("drop_database")) $param.=" -c -C";
  257. if (GETPOST("sql_structure"))
  258. {
  259. if (GETPOST("drop")) $param.=" --add-drop-table";
  260. if (! GETPOST("sql_data")) $param.=" -s";
  261. }
  262. if (GETPOST("sql_data"))
  263. {
  264. if (! GETPOST("sql_structure")) $param.=" -a";
  265. if (GETPOST("showcolumns")) $param.=" -c";
  266. }
  267. $param.=' -f "'.$outputfile.'"';
  268. //if ($compression == 'none')
  269. if ($compression == 'gz') $param.=' -Z 9';
  270. //if ($compression == 'bz')
  271. $paramcrypted=$param;
  272. $paramclear=$param;
  273. /*if (! empty($dolibarr_main_db_pass))
  274. {
  275. $paramcrypted.=" -W".preg_replace('/./i','*',$dolibarr_main_db_pass);
  276. $paramclear.=" -W".$dolibarr_main_db_pass;
  277. }*/
  278. $paramcrypted.=" -w ".$dolibarr_main_db_name;
  279. $paramclear.=" -w ".$dolibarr_main_db_name;
  280. print $langs->trans("RunCommandSummaryToLaunch").':<br>'."\n";
  281. print '<textarea rows="'.ROWS_3.'" cols="120">'.$command." ".$paramcrypted.'</textarea><br>'."\n";
  282. print '<br>';
  283. // Now show to ask to run command
  284. print $langs->trans("YouMustRunCommandFromCommandLineAfterLoginToUser",$dolibarr_main_db_user,$dolibarr_main_db_user);
  285. print '<br>';
  286. print '<br>';
  287. $what='';
  288. }
  289. // Si on a demande une generation
  290. if ($what)
  291. {
  292. if ($errormsg)
  293. {
  294. print '<div class="error">'.$langs->trans("Error")." : ".$errormsg.'</div>';
  295. // print '<a href="'.DOL_URL_ROOT.$relativepatherr.'">'.$langs->trans("DownloadErrorFile").'</a><br>';
  296. print '<br>';
  297. print '<br>';
  298. }
  299. else
  300. {
  301. print '<div class="ok">';
  302. print $langs->trans("BackupFileSuccessfullyCreated").'.<br>';
  303. print $langs->trans("YouCanDownloadBackupFile");
  304. print '</div>';
  305. print '<br>';
  306. }
  307. }
  308. $filearray=dol_dir_list($conf->admin->dir_output.'/backup','files',0,'','',$sortfield,(strtolower($sortorder)=='asc'?SORT_ASC:SORT_DESC),1);
  309. $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"));
  310. print '<br>';
  311. $time_end = time();
  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. *
  319. * @param string $outputfile Output file name
  320. * @param string $tables Table name or '*' for all
  321. * @return int <0 if KO, >0 if OK
  322. */
  323. function backup_tables($outputfile, $tables='*')
  324. {
  325. global $db, $langs;
  326. global $errormsg;
  327. // Set to UTF-8
  328. $db->query('SET NAMES utf8');
  329. $db->query('SET CHARACTER SET utf8');
  330. //get all of the tables
  331. if ($tables == '*')
  332. {
  333. $tables = array();
  334. $result = $db->query('SHOW FULL TABLES WHERE Table_type = \'BASE TABLE\'');
  335. while($row = $db->fetch_row($result))
  336. {
  337. $tables[] = $row[0];
  338. }
  339. }
  340. else
  341. {
  342. $tables = is_array($tables) ? $tables : explode(',',$tables);
  343. }
  344. //cycle through
  345. $handle = fopen($outputfile, 'w+');
  346. if (fwrite($handle, '') === FALSE)
  347. {
  348. $langs->load("errors");
  349. dol_syslog("Failed to open file ".$outputfile,LOG_ERR);
  350. $errormsg=$langs->trans("ErrorFailedToWriteInDir");
  351. return -1;
  352. }
  353. // Print headers and global mysql config vars
  354. $sqlhead = '';
  355. $sqlhead .= "-- ".getStaticMember($db, 'label')." dump via php
  356. --
  357. -- Host: ".$db->db->host_info." Database: ".$db->database_name."
  358. -- ------------------------------------------------------
  359. -- Server version ".$db->db->server_info."
  360. /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
  361. /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
  362. /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
  363. /*!40101 SET NAMES utf8 */;
  364. /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
  365. /*!40103 SET TIME_ZONE='+00:00' */;
  366. /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
  367. /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
  368. /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
  369. /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
  370. ";
  371. fwrite($handle, $sqlhead);
  372. // Process each table and print their definition + their datas
  373. foreach($tables as $table)
  374. {
  375. // Saving the table structure
  376. fwrite($handle, "--\n-- Table structure for table `".$table."`\n--\n\n");
  377. fwrite($handle,"DROP TABLE IF EXISTS `".$table."`;\n");
  378. fwrite($handle,"/*!40101 SET @saved_cs_client = @@character_set_client */;\n");
  379. fwrite($handle,"/*!40101 SET character_set_client = utf8 */;\n");
  380. $resqldrop=$db->query('SHOW CREATE TABLE '.$table);
  381. $row2 = $db->fetch_row($resqldrop);
  382. fwrite($handle,$row2[1].";\n");
  383. fwrite($handle,"/*!40101 SET character_set_client = @saved_cs_client */;\n\n");
  384. // Dumping the data (locking the table and disabling the keys check while doing the process)
  385. fwrite($handle, "--\n-- Dumping data for table `".$table."`\n--\n\n");
  386. fwrite($handle, "LOCK TABLES `".$table."` WRITE;\n");
  387. fwrite($handle, "/*!40000 ALTER TABLE `".$table."` DISABLE KEYS */;\n");
  388. $sql='SELECT * FROM '.$table;
  389. $result = $db->query($sql);
  390. $num_fields = $db->num_rows($result);
  391. while($row = $db->fetch_row($result)) {
  392. // For each row of data we print a line of INSERT
  393. fwrite($handle,'INSERT INTO `'.$table.'` VALUES (');
  394. $columns = count($row);
  395. $rowsarr = array();
  396. for($j=0; $j<$columns; $j++) {
  397. // 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)
  398. if ($row[$j] == null and !is_string($row[$j])) {
  399. // IMPORTANT: if the field is NULL we set it NULL
  400. $row[$j] = 'NULL';
  401. } elseif(is_string($row[$j]) and $row[$j] == '') {
  402. // if it's an empty string, we set it as an empty string
  403. $row[$j] = "''";
  404. } elseif(is_numeric($row[$j])) {
  405. // if it's a number, we return it as-is
  406. $row[$j] = $row[$j];
  407. } else { // else for all other cases we escape the value and put quotes around
  408. $row[$j] = addslashes($row[$j]);
  409. $row[$j] = preg_replace("#\n#", "\\n", $row[$j]);
  410. $row[$j] = "'".$row[$j]."'";
  411. }
  412. }
  413. fwrite($handle,implode(',', $row).");\n");
  414. }
  415. fwrite($handle, "/*!40000 ALTER TABLE `".$table."` ENABLE KEYS */;\n"); // Enabling back the keys/index checking
  416. fwrite($handle, "UNLOCK TABLES;\n"); // Unlocking the tables
  417. fwrite($handle,"\n\n\n");
  418. }
  419. /* Backup Procedure structure*/
  420. /*
  421. $result = $db->query('SHOW PROCEDURE STATUS');
  422. if ($db->num_rows($result) > 0)
  423. {
  424. while ($row = $db->fetch_row($result)) { $procedures[] = $row[1]; }
  425. foreach($procedures as $proc)
  426. {
  427. fwrite($handle,"DELIMITER $$\n\n");
  428. fwrite($handle,"DROP PROCEDURE IF EXISTS '$name'.'$proc'$$\n");
  429. $resqlcreateproc=$db->query("SHOW CREATE PROCEDURE '$proc'");
  430. $row2 = $db->fetch_row($resqlcreateproc);
  431. fwrite($handle,"\n".$row2[2]."$$\n\n");
  432. fwrite($handle,"DELIMITER ;\n\n");
  433. }
  434. }
  435. */
  436. /* Backup Procedure structure*/
  437. // Write the footer (restore the previous database settings)
  438. $sqlfooter='';
  439. $sqlfooter.="
  440. /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
  441. /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
  442. /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
  443. /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
  444. /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
  445. /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
  446. /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
  447. /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
  448. -- Dump completed on ".date('Y-m-d G-i-s');
  449. fwrite($handle, $sqlfooter);
  450. fclose($handle);
  451. return 1;
  452. }
  453. ?>