lib.mysqldump.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. <?php
  2. # ***** BEGIN LICENSE BLOCK *****
  3. # This file is part of DotClear.
  4. # Copyright (c) 2004-2005 Olivier Meunier and contributors. All rights
  5. # reserved.
  6. #
  7. # DotClear 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 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # DotClear 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 DotClear; if not, write to the Free Software
  19. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. #
  21. # ***** END LICENSE BLOCK *****
  22. /**
  23. * @class dbdump
  24. *
  25. */
  26. class dbdump {
  27. /**
  28. @function _getDCTablesList
  29. Création d'un tableau contenant la listes des tables DC à sauvegarder.
  30. Les tables 'log' et 'session' sont ignorées et les éventuelles tables
  31. de plugins ajoutées, si elles sont correctement préfixées.
  32. @return array
  33. */
  34. function _getDCTablesList()
  35. {
  36. global $con;
  37. // D'emblée, on précise les tables "natives" dans l'ordre d'importance
  38. // pour sécuriser au mieux la remontée.
  39. // NB : on ignore les tables 'log' et 'session'
  40. $dc_dump_tables =
  41. array(
  42. DB_PREFIX.'user',
  43. DB_PREFIX.'categorie',
  44. DB_PREFIX.'post',
  45. DB_PREFIX.'comment',
  46. DB_PREFIX.'ping',
  47. DB_PREFIX.'link'
  48. );
  49. // Récupération auprès de MySQL de la liste des tables préfixées
  50. // pour le DC courant
  51. $dc_tables = $con->select("SHOW TABLES LIKE '".DB_PREFIX."%'");
  52. // Maintenant on consolide le tout...
  53. while ($dc_tables->fetch()) {
  54. $dc_table = $dc_tables->f(0);
  55. // S'il s'agit de la table 'log' ou 'session', on écarte...
  56. if ($dc_table == DB_PREFIX.'log' ||
  57. $dc_table == DB_PREFIX.'session') {
  58. continue;
  59. }
  60. // On n'ajoute que les tables supplémentaires susceptibles
  61. // d'alimenter des plugins.
  62. if (in_array($dc_table, $dc_dump_tables)) {
  63. continue;
  64. } else {
  65. $dc_dump_tables[] = $dc_table;
  66. }
  67. }
  68. return($dc_dump_tables);
  69. }
  70. /**
  71. @function getDump
  72. Effectue un dump des tables DotClear sous forme d'un fichier SQL standard.
  73. L'export se compose pour chacune des tables :
  74. - d'une instruction conditionnelle DROP TABLE
  75. - de la clause complète CREATE TABLE (clés comprises)
  76. - des clauses INSERT nécessaires à la restauration des données.
  77. NB : Les noms des colonnes sont "backquotés".
  78. @return string La chaine représentant le dump.
  79. */
  80. function getDump()
  81. {
  82. global $con;
  83. $dc_tables = dbdump::_getDCTablesList();
  84. // On précise à MySQL qu'il doit "quoter" les résultats des
  85. // requêtes SHOW CREATE TABLE qui vont suivre.
  86. $con->execute("SET SQL_QUOTE_SHOW_CREATE = 1");
  87. // Récupération de la version du serveur MySQL
  88. $rs = $con->select("SELECT REPLACE(VERSION(),'-log','')");
  89. $mysql_version = 'unknown';
  90. if ($rs) $mysql_version = $rs->f(0);
  91. // Une entête pour mettre quelques infos (in)utiles
  92. $dump_str =
  93. "#-------------------------------------------------------------------\n".
  94. "# Dump MySQL\n".
  95. "#\n".
  96. "# Blog : ". dc_blog_name ."\n".
  97. "# DotClear : ". DC_VERSION ."\n".
  98. "# Serveur : ". DB_HOST ." (MySQL v ". $mysql_version .")\n".
  99. "# Base : ". DB_DBASE ."\n".
  100. "# Date : ". date("d/m/Y H:i") ."\n".
  101. "#-------------------------------------------------------------------\n".
  102. "\n";
  103. // C'est parti !
  104. foreach ($dc_tables as $dc_table) {
  105. $rs = $con->select("SHOW CREATE TABLE $dc_table");
  106. while($rs->fetch()) {
  107. // Dump de la clause CREATE TABLE
  108. $dump_str .=
  109. "#-------------------------------------------------------------------\n".
  110. "# Structure de la table $dc_table\n".
  111. "#-------------------------------------------------------------------\n".
  112. "DROP TABLE IF EXISTS `$dc_table`;\n".
  113. str_replace("\n","",$rs->f(1)).";".
  114. "\n\n";
  115. // Dump des clauses INSERT
  116. $dump_str .=
  117. "#-------------------------------------------------------------------\n".
  118. "# Données de la table $dc_table\n".
  119. "#-------------------------------------------------------------------\n";
  120. $col_rs = $con->select("SELECT * FROM $dc_table");
  121. while($col_rs->fetch()) {
  122. $values = array();
  123. for ($i = 0; $i < $col_rs->int_col_count; $i++) {
  124. $values[] = $con->escapeStr($col_rs->f($i));
  125. }
  126. $dump_str .= "INSERT INTO `$dc_table` VALUES ( '". implode("', '",$values) ."' );\n";
  127. }
  128. $dump_str .= "\n";
  129. }
  130. }
  131. $dump_str .= "#-- EOF --\n";
  132. return($dump_str);
  133. }
  134. /**
  135. @function saveDump
  136. Enregistre un fichier de dump des tables DotClear.
  137. Avec les paramètres par défaut, un fichier gzippé dump-YYYYMMDD.sql.gz est
  138. créé dans le répertoire share/mysql/ de l'installation DotClear.
  139. @param boolean transmit indicateur d'envoi du fichier de dump (false)
  140. @param string path le chemin d'enregistrement ('')
  141. @param string name le nom du fichier cible ('')
  142. @param boolean compressed indicateur de compression ou non (true)
  143. @return mixed Retourne une chaine représentant le nom du fichier dans lequel
  144. le dump a été sauvegardé. Retourne un boolean à false en cas
  145. de problème sinon.
  146. @see dbdump::getDump
  147. */
  148. function saveDump($transmit = false, $path = '', $name = '', $compressed = true)
  149. {
  150. if ($compressed && !function_exists('gzencode')) {
  151. return(false);
  152. }
  153. if (!empty($path) && is_dir($path) && is_writable($path)) {
  154. $trg_path = $path;
  155. } else {
  156. $trg_path = DC_SHARE_DIR.'/mysql';
  157. }
  158. if (!empty($name)) {
  159. $trg_name = $name;
  160. } else {
  161. $trg_name = 'dbdump-'.date("Ymd").'.sql';
  162. }
  163. $dump = dbdump::getDump();
  164. if ($compressed) {
  165. $dump = gzencode($dump);
  166. $trg_name .= '.gz';
  167. }
  168. if ($transmit) {
  169. header('Content-Type: application/x-gzip');
  170. header('Content-Disposition: attachment; filename='.$trg_name);
  171. echo $dump;
  172. exit;
  173. } else {
  174. $trg_fullname = $trg_path.'/'.$trg_name;
  175. if ($fh = fopen($trg_fullname,"wb")) {
  176. fwrite($fh, $dump);
  177. fclose($fh);
  178. } else {
  179. return(false);
  180. }
  181. return($trg_name);
  182. }
  183. }
  184. /**
  185. @function restoreDump
  186. Restaure des tables DotClear depuis un fichier de dump précédemment créé
  187. par l'opération de sauvegarde.
  188. @param string src_file le chemin du fichier de dump à restaurer
  189. @param boolean compressed indicateur de compression ou non (true)
  190. @return mixed Retourne une chaine indiquant que l'opération s'est correctement
  191. déroulée. Retourne un boolean à false en cas de problème sinon.
  192. @see dbdump::saveDump
  193. */
  194. function restoreDump($src_file, $compressed = true)
  195. {
  196. global $con;
  197. // Pour un fichier compressé, on crée un version décompressée
  198. // temporaire dans le répertoire share/mysql/
  199. $chrono_start = dbdump::_getChrono();
  200. if ($compressed) {
  201. if (!$fh = fopen($src_file, "rb")) {
  202. return(false);
  203. }
  204. $tmp_dump = fread($fh, filesize($src_file));
  205. fclose($fh);
  206. if (!$dump = gzinflate(substr($tmp_dump, 10))) {
  207. return(false);
  208. }
  209. unset($tmp_dump);
  210. $tmp_file = DC_SHARE_DIR.'/mysql/_'.basename($src_file);
  211. if (!$fh = fopen($tmp_file, "wb")) {
  212. return(false);
  213. }
  214. fwrite($fh, $dump);
  215. fclose($fh);
  216. unlink($src_file);
  217. unset($dump);
  218. $src_file = $tmp_file;
  219. }
  220. // Parsing "simpliste" du fichier dump pour la remontée en base.
  221. // Seules les requêtes DROP TABLE, CREATE TABLE et INSERT seront
  222. // traitées.
  223. $scan = file($src_file);
  224. $token = $sql = '';
  225. foreach ($scan as $line) {
  226. $line = rtrim($line);
  227. if (empty($line) || strpos(ltrim($line), "#") === 0) continue;
  228. $token .= $line;
  229. if (preg_match("/^((DROP|CREATE) TABLE .*);$/", $token, $matches) ||
  230. preg_match("/^(INSERT INTO (.*)'\s\));$/", $token, $matches)) {
  231. $sql = $matches[1];
  232. if (!empty($sql)) {
  233. $res = $con->execute($sql);
  234. if ($res === false) {
  235. unlink($src_file);
  236. return(false);
  237. }
  238. }
  239. $token = $sql = '';
  240. }
  241. }
  242. unlink($src_file);
  243. $chrono_end = dbdump::_getChrono();
  244. buffer::str(sprintf("(%.2f sec.)",$chrono_end - $chrono_start));
  245. return(__('Dump has been restored'));
  246. }
  247. /**
  248. @function _getChrono
  249. @return float
  250. */
  251. function _getChrono()
  252. {
  253. list($usec, $sec) = explode(" ", microtime());
  254. return ((float)$usec + (float)$sec);
  255. }
  256. }
  257. ?>