DumpDatabase.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <?php
  2. /**
  3. * This file has a single job - database backup.
  4. *
  5. * Simple Machines Forum (SMF)
  6. *
  7. * @package SMF
  8. * @author Simple Machines http://www.simplemachines.org
  9. * @copyright 2012 Simple Machines
  10. * @license http://www.simplemachines.org/about/smf/license.php BSD
  11. *
  12. * @version 2.1 Alpha 1
  13. */
  14. if (!defined('SMF'))
  15. die('No direct access...');
  16. /**
  17. * Dumps the database.
  18. * It writes all of the database to standard output.
  19. * It uses gzip compression if compress is set in the URL/post data.
  20. * It may possibly time out, and mess up badly if you were relying on it. :P
  21. * The data dumped depends on whether "struct" and "data" are passed.
  22. * It requires an administrator and the session hash by post.
  23. * It is called from ManageMaintenance.php.
  24. */
  25. function DumpDatabase2()
  26. {
  27. global $db_name, $scripturl, $context, $modSettings, $crlf, $smcFunc, $db_prefix, $db_show_debug;
  28. // Administrators only!
  29. if (!allowedTo('admin_forum'))
  30. fatal_lang_error('no_dump_database', 'critical');
  31. // We don't need debug when dumping the database
  32. $modSettings['disableQueryCheck'] = true;
  33. $db_show_debug = false;
  34. // You can't dump nothing!
  35. if (!isset($_REQUEST['struct']) && !isset($_REQUEST['data']))
  36. $_REQUEST['data'] = true;
  37. checkSession('post');
  38. // We will need this, badly!
  39. db_extend();
  40. // Attempt to stop from dying...
  41. @set_time_limit(600);
  42. $time_limit = ini_get('max_execution_time');
  43. $start_time = time();
  44. // @todo ... fail on not getting the requested memory?
  45. setMemoryLimit('256M');
  46. $memory_limit = memoryReturnBytes(ini_get('memory_limit')) / 4;
  47. $current_used_memory = 0;
  48. $db_backup = '';
  49. $output_function = 'un_compressed';
  50. @ob_end_clean();
  51. // Start saving the output... (don't do it otherwise for memory reasons.)
  52. if (isset($_REQUEST['compress']) && function_exists('gzencode'))
  53. {
  54. $output_function = 'gzencode';
  55. // Send faked headers so it will just save the compressed output as a gzip.
  56. header('Content-Type: application/x-gzip');
  57. header('Accept-Ranges: bytes');
  58. header('Content-Encoding: none');
  59. // Gecko browsers... don't like this. (Mozilla, Firefox, etc.)
  60. if (!isBrowser('gecko'))
  61. header('Content-Transfer-Encoding: binary');
  62. // The file extension will include .gz...
  63. $extension = '.sql.gz';
  64. }
  65. else
  66. {
  67. // Get rid of the gzipping alreading being done.
  68. if (!empty($modSettings['enableCompressedOutput']))
  69. @ob_end_clean();
  70. // If we can, clean anything already sent from the output buffer...
  71. elseif (ob_get_length() != 0)
  72. ob_clean();
  73. // Tell the client to save this file, even though it's text.
  74. header('Content-Type: ' . (isBrowser('ie') || isBrowser('opera') ? 'application/octetstream' : 'application/octet-stream'));
  75. header('Content-Encoding: none');
  76. // This time the extension should just be .sql.
  77. $extension = '.sql';
  78. }
  79. // This should turn off the session URL parser.
  80. $scripturl = '';
  81. // If this database is flat file and has a handler function pass it to that.
  82. if (!empty($smcFunc['db_get_backup']))
  83. {
  84. $smcFunc['db_get_backup']();
  85. exit;
  86. }
  87. // Send the proper headers to let them download this file.
  88. header('Content-Disposition: attachment; filename="' . $db_name . '-' . (empty($_REQUEST['struct']) ? 'data' : (empty($_REQUEST['data']) ? 'structure' : 'complete')) . '_' . strftime('%Y-%m-%d') . $extension . '"');
  89. header('Cache-Control: private');
  90. header('Connection: close');
  91. // This makes things simpler when using it so very very often.
  92. $crlf = "\r\n";
  93. // SQL Dump Header.
  94. $db_chunks =
  95. '-- ==========================================================' . $crlf .
  96. '--' . $crlf .
  97. '-- Database dump of tables in `' . $db_name . '`' . $crlf .
  98. '-- ' . timeformat(time(), false) . $crlf .
  99. '--' . $crlf .
  100. '-- ==========================================================' . $crlf .
  101. $crlf;
  102. // Get all tables in the database....
  103. if (preg_match('~^`(.+?)`\.(.+?)$~', $db_prefix, $match) != 0)
  104. {
  105. $db = strtr($match[1], array('`' => ''));
  106. $dbp = str_replace('_', '\_', $match[2]);
  107. }
  108. else
  109. {
  110. $db = false;
  111. $dbp = $db_prefix;
  112. }
  113. // Dump each table.
  114. $tables = $smcFunc['db_list_tables'](false, $db_prefix . '%');
  115. foreach ($tables as $tableName)
  116. {
  117. // Are we dumping the structures?
  118. if (isset($_REQUEST['struct']))
  119. {
  120. $db_chunks .=
  121. $crlf .
  122. '--' . $crlf .
  123. '-- Table structure for table `' . $tableName . '`' . $crlf .
  124. '--' . $crlf .
  125. $crlf .
  126. $smcFunc['db_table_sql']($tableName) . ';' . $crlf;
  127. }
  128. else
  129. // This is needed to speedup things later
  130. $smcFunc['db_table_sql']($tableName);
  131. // How about the data?
  132. if (!isset($_REQUEST['data']) || substr($tableName, -10) == 'log_errors')
  133. continue;
  134. $first_round = true;
  135. $close_table = false;
  136. // Are there any rows in this table?
  137. while ($get_rows = $smcFunc['db_insert_sql']($tableName, $first_round))
  138. {
  139. if (empty($get_rows))
  140. break;
  141. // Time is what we need here!
  142. if (function_exists('apache_reset_timeout'))
  143. @apache_reset_timeout();
  144. elseif (!empty($time_limit) && ($start_time + $time_limit - 20 > time()))
  145. {
  146. $start_time = time();
  147. @set_time_limit(150);
  148. }
  149. if ($first_round)
  150. {
  151. $db_chunks .=
  152. $crlf .
  153. '--' . $crlf .
  154. '-- Dumping data in `' . $tableName . '`' . $crlf .
  155. '--' . $crlf .
  156. $crlf;
  157. $first_round = false;
  158. }
  159. $db_chunks .=
  160. $get_rows;
  161. $current_used_memory += $smcFunc['strlen']($db_chunks);
  162. $db_backup .= $db_chunks;
  163. unset($db_chunks);
  164. $db_chunks = '';
  165. if ($current_used_memory > $memory_limit)
  166. {
  167. echo $output_function($db_backup);
  168. $current_used_memory = 0;
  169. // This is probably redundant
  170. unset($db_backup);
  171. $db_backup = '';
  172. }
  173. $close_table = true;
  174. }
  175. // No rows to get - skip it.
  176. if ($close_table)
  177. $db_backup .=
  178. '-- --------------------------------------------------------' . $crlf;
  179. }
  180. $db_backup .=
  181. $crlf .
  182. '-- Done' . $crlf;
  183. echo $output_function($db_backup);
  184. exit;
  185. }
  186. /**
  187. * Dummy/helper function, it simply returns the string passed as argument
  188. * @param $string, a string
  189. * @return the string passed
  190. */
  191. function un_compressed($string = '')
  192. {
  193. return $string;
  194. }
  195. ?>