PageRenderTime 25ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/NCMS/public_html/forum/Sources/DumpDatabase.php

https://github.com/lefedor/mjncms
PHP | 335 lines | 188 code | 51 blank | 96 comment | 46 complexity | 8a3b1a54b9330564557c3054942fa538 MD5 | raw file
  1. <?php
  2. /**********************************************************************************
  3. * DumpDatabase.php *
  4. ***********************************************************************************
  5. * SMF: Simple Machines Forum *
  6. * Open-Source Project Inspired by Zef Hemel (zef@zefhemel.com) *
  7. * =============================================================================== *
  8. * Software Version: SMF 1.1 *
  9. * Software by: Simple Machines (http://www.simplemachines.org) *
  10. * Copyright 2006 by: Simple Machines LLC (http://www.simplemachines.org) *
  11. * 2001-2006 by: Lewis Media (http://www.lewismedia.com) *
  12. * Support, News, Updates at: http://www.simplemachines.org *
  13. ***********************************************************************************
  14. * This program is free software; you may redistribute it and/or modify it under *
  15. * the terms of the provided license as published by Simple Machines LLC. *
  16. * *
  17. * This program is distributed in the hope that it is and will be useful, but *
  18. * WITHOUT ANY WARRANTIES; without even any implied warranty of MERCHANTABILITY *
  19. * or FITNESS FOR A PARTICULAR PURPOSE. *
  20. * *
  21. * See the "license.txt" file for details of the Simple Machines license. *
  22. * The latest version can always be found at http://www.simplemachines.org. *
  23. **********************************************************************************/
  24. if (!defined('SMF'))
  25. die('Hacking attempt...');
  26. /* This file has a single job - database backup. Note that, because of the
  27. nature of its output, it uses the db_query() function without __FILE__ or
  28. __LINE__ so errors won't be outputted.
  29. void DumpDatabase2()
  30. - writes all of the database to standard output.
  31. - uses gzip compression if compress is set in the URL/post data.
  32. - may possibly time out in some cases.
  33. - the data dumped depends on whether "struct" and "data" are passed.
  34. - requires an administrator and the session hash by get.
  35. - is accessed via ?action=dumpdb.
  36. string getTableContent(string table_name)
  37. - gets all the necessary INSERTs for the table named table_name.
  38. - goes in 250 row segments.
  39. - returns the query to insert the data back in.
  40. - returns an empty string if the table was empty.
  41. string getTableSQLData(string table_name)
  42. - dumps the CREATE for the specified table. (by table_name.)
  43. - returns the CREATE statement.
  44. */
  45. // Dumps the database to a file.
  46. function DumpDatabase2()
  47. {
  48. global $db_name, $db_prefix, $scripturl, $context, $modSettings, $crlf;
  49. // Administrators only!
  50. if (!allowedTo('admin_forum'))
  51. fatal_lang_error('no_dump_database');
  52. // You can't dump nothing!
  53. if (!isset($_GET['struct']) && !isset($_GET['data']))
  54. $_GET['data'] = true;
  55. checkSession('get');
  56. // Attempt to stop from dying...
  57. @set_time_limit(600);
  58. @ini_set('memory_limit', '128M');
  59. // Start saving the output... (don't do it otherwise for memory reasons.)
  60. if (isset($_REQUEST['compress']) && function_exists('gzencode'))
  61. {
  62. // Make sure we're gzipping output, but then say we're not in the header ^_^.
  63. if (empty($modSettings['enableCompressedOutput']))
  64. @ob_start('ob_gzhandler');
  65. // Try to clean any data already outputted.
  66. elseif (ob_get_length() != 0)
  67. {
  68. ob_end_clean();
  69. @ob_start('ob_gzhandler');
  70. }
  71. // Send faked headers so it will just save the compressed output as a gzip.
  72. header('Content-Type: application/x-gzip');
  73. header('Accept-Ranges: bytes');
  74. header('Content-Encoding: none');
  75. // Gecko browsers... don't like this. (Mozilla, Firefox, etc.)
  76. if (!$context['browser']['is_gecko'])
  77. header('Content-Transfer-Encoding: binary');
  78. // The file extension will include .gz...
  79. $extension = '.sql.gz';
  80. }
  81. else
  82. {
  83. // Get rid of the gzipping alreading being done.
  84. if (!empty($modSettings['enableCompressedOutput']))
  85. @ob_end_clean();
  86. // If we can, clean anything already sent from the output buffer...
  87. elseif (function_exists('ob_clean') && ob_get_length() != 0)
  88. ob_clean();
  89. // Tell the client to save this file, even though it's text.
  90. header('Content-Type: application/octetstream');
  91. header('Content-Encoding: none');
  92. // This time the extension should just be .sql.
  93. $extension = '.sql';
  94. }
  95. // This should turn off the session URL parser.
  96. $scripturl = '';
  97. // Send the proper headers to let them download this file.
  98. header('Content-Disposition: filename="' . $db_name . '-' . (empty($_GET['struct']) ? 'data' : (empty($_GET['data']) ? 'structure' : 'complete')) . '_' . strftime('%Y-%m-%d') . $extension . '"');
  99. header('Cache-Control: private');
  100. header('Connection: close');
  101. // This makes things simpler when using it so very very often.
  102. $crlf = "\r\n";
  103. // SQL Dump Header.
  104. echo
  105. '# ==========================================================', $crlf,
  106. '#', $crlf,
  107. '# Database dump of tables in `', $db_name, '`', $crlf,
  108. '# ', timeformat(time(), false), $crlf,
  109. '#', $crlf,
  110. '# ==========================================================', $crlf,
  111. $crlf;
  112. // Get all tables in the database....
  113. if (preg_match('~^`(.+?)`\.(.+?)$~', $db_prefix, $match) != 0)
  114. {
  115. $queryTables = db_query("
  116. SHOW TABLES
  117. FROM `" . strtr($match[1], array('`' => '')) . "`
  118. LIKE '" . str_replace('_', '\_', $match[2]) . "%'", false, false);
  119. }
  120. else
  121. {
  122. $queryTables = db_query("
  123. SHOW TABLES
  124. LIKE '" . str_replace('_', '\_', $db_prefix) . "%'", false, false);
  125. }
  126. // Dump each table.
  127. while ($tableName = mysql_fetch_row($queryTables))
  128. {
  129. if (function_exists('apache_reset_timeout'))
  130. apache_reset_timeout();
  131. // Are we dumping the structures?
  132. if (isset($_GET['struct']))
  133. {
  134. echo
  135. $crlf,
  136. '#', $crlf,
  137. '# Table structure for table `', $tableName[0], '`', $crlf,
  138. '#', $crlf,
  139. $crlf,
  140. 'DROP TABLE IF EXISTS `', $tableName[0], '`;', $crlf,
  141. $crlf,
  142. getTableSQLData($tableName[0]), ';', $crlf;
  143. }
  144. // How about the data?
  145. if (!isset($_GET['data']) || substr($tableName[0], -10) == 'log_errors')
  146. continue;
  147. // Are there any rows in this table?
  148. $get_rows = getTableContent($tableName[0]);
  149. // No rows to get - skip it.
  150. if (empty($get_rows))
  151. continue;
  152. echo
  153. $crlf,
  154. '#', $crlf,
  155. '# Dumping data in `', $tableName[0], '`', $crlf,
  156. '#', $crlf,
  157. $crlf,
  158. $get_rows,
  159. '# --------------------------------------------------------', $crlf;
  160. }
  161. mysql_free_result($queryTables);
  162. echo
  163. $crlf,
  164. '# Done', $crlf;
  165. exit;
  166. }
  167. // Get the content (INSERTs) for a table.
  168. function getTableContent($tableName)
  169. {
  170. global $crlf;
  171. // Get everything from the table.
  172. $result = db_query("
  173. SELECT /*!40001 SQL_NO_CACHE */ *
  174. FROM `$tableName`", false, false);
  175. // The number of rows, just for record keeping and breaking INSERTs up.
  176. $num_rows = @mysql_num_rows($result);
  177. $current_row = 0;
  178. if ($num_rows == 0)
  179. return '';
  180. $fields = array_keys(mysql_fetch_assoc($result));
  181. mysql_data_seek($result, 0);
  182. // Start it off with the basic INSERT INTO.
  183. $data = 'INSERT INTO `' . $tableName . '`' . $crlf . "\t(`" . implode('`, `', $fields) . '`)' . $crlf . 'VALUES ';
  184. // Loop through each row.
  185. while ($row = mysql_fetch_row($result))
  186. {
  187. $current_row++;
  188. // Get the fields in this row...
  189. $field_list = array();
  190. for ($j = 0; $j < mysql_num_fields($result); $j++)
  191. {
  192. // Try to figure out the type of each field. (NULL, number, or 'string'.)
  193. if (!isset($row[$j]))
  194. $field_list[] = 'NULL';
  195. elseif (is_numeric($row[$j]))
  196. $field_list[] = $row[$j];
  197. else
  198. $field_list[] = "'" . mysql_escape_string($row[$j]) . "'";
  199. }
  200. // 'Insert' the data.
  201. $data .= '(' . implode(', ', $field_list) . ')';
  202. // Start a new INSERT statement after every 250....
  203. if ($current_row > 249 && $current_row % 250 == 0)
  204. $data .= ';' . $crlf . 'INSERT INTO `' . $tableName . '`' . $crlf . "\t(`" . implode('`, `', $fields) . '`)' . $crlf . 'VALUES ';
  205. // All done!
  206. elseif ($current_row == $num_rows)
  207. $data .= ';' . $crlf;
  208. // Otherwise, go to the next line.
  209. else
  210. $data .= ',' . $crlf . "\t";
  211. }
  212. mysql_free_result($result);
  213. // Return an empty string if there were no rows.
  214. return $num_rows == 0 ? '' : $data;
  215. }
  216. // Get the schema (CREATE) for a table.
  217. function getTableSQLData($tableName)
  218. {
  219. global $crlf;
  220. // Start the create table...
  221. $schema_create = 'CREATE TABLE `' . $tableName . '` (' . $crlf;
  222. // Find all the fields.
  223. $result = db_query("
  224. SHOW FIELDS
  225. FROM `$tableName`", false, false);
  226. while ($row = @mysql_fetch_assoc($result))
  227. {
  228. // Make the CREATE for this column.
  229. $schema_create .= ' ' . $row['Field'] . ' ' . $row['Type'] . ($row['Null'] != 'YES' ? ' NOT NULL' : '');
  230. // Add a default...?
  231. if (isset($row['Default']))
  232. {
  233. // Make a special case of auto-timestamp.
  234. if ($row['Default'] == 'CURRENT_TIMESTAMP')
  235. $schema_create .= ' /*!40102 NOT NULL default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP */';
  236. else
  237. $schema_create .= ' default ' . (is_numeric($row['Default']) ? $row['Default'] : "'" . mysql_escape_string($row['Default']) . "'");
  238. }
  239. // And now any extra information. (such as auto_increment.)
  240. $schema_create .= ($row['Extra'] != '' ? ' ' . $row['Extra'] : '') . ',' . $crlf;
  241. }
  242. @mysql_free_result($result);
  243. // Take off the last comma.
  244. $schema_create = substr($schema_create, 0, -strlen($crlf) - 1);
  245. // Find the keys.
  246. $result = db_query("
  247. SHOW KEYS
  248. FROM `$tableName`", false, false);
  249. $indexes = array();
  250. while ($row = @mysql_fetch_assoc($result))
  251. {
  252. // IS this a primary key, unique index, or regular index?
  253. $row['Key_name'] = $row['Key_name'] == 'PRIMARY' ? 'PRIMARY KEY' : (empty($row['Non_unique']) ? 'UNIQUE ' : ($row['Comment'] == 'FULLTEXT' || (isset($row['Index_type']) && $row['Index_type'] == 'FULLTEXT') ? 'FULLTEXT ' : 'KEY ')) . $row['Key_name'];
  254. // Is this the first column in the index?
  255. if (empty($indexes[$row['Key_name']]))
  256. $indexes[$row['Key_name']] = array();
  257. // A sub part, like only indexing 15 characters of a varchar.
  258. if (!empty($row['Sub_part']))
  259. $indexes[$row['Key_name']][$row['Seq_in_index']] = $row['Column_name'] . '(' . $row['Sub_part'] . ')';
  260. else
  261. $indexes[$row['Key_name']][$row['Seq_in_index']] = $row['Column_name'];
  262. }
  263. @mysql_free_result($result);
  264. // Build the CREATEs for the keys.
  265. foreach ($indexes as $keyname => $columns)
  266. {
  267. // Ensure the columns are in proper order.
  268. ksort($columns);
  269. $schema_create .= ',' . $crlf . ' ' . $keyname . ' (' . implode($columns, ', ') . ')';
  270. }
  271. // Now just get the comment and type... (MyISAM, etc.)
  272. $result = db_query("
  273. SHOW TABLE STATUS
  274. LIKE '" . strtr($tableName, array('_' => '\\_', '%' => '\\%')) . "'", false, false);
  275. $row = @mysql_fetch_assoc($result);
  276. @mysql_free_result($result);
  277. // Probably MyISAM.... and it might have a comment.
  278. $schema_create .= $crlf . ') TYPE=' . (isset($row['Type']) ? $row['Type'] : $row['Engine']) . ($row['Comment'] != '' ? ' COMMENT="' . $row['Comment'] . '"' : '');
  279. return $schema_create;
  280. }
  281. ?>