4 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
\r
5 * Copyright (C) 2002-2012 The Nucleus Group
\r
7 * This program is free software; you can redistribute it and/or
\r
8 * modify it under the terms of the GNU General Public License
\r
9 * as published by the Free Software Foundation; either version 2
\r
10 * of the License, or (at your option) any later version.
\r
11 * (see nucleus/documentation/index.html#license for more info)
\r
14 * Scripts to create/restore a backup of the Nucleus database
\r
16 * @license http://nucleuscms.org/license.txt GNU General Public License
\r
17 * @copyright Copyright (C) 2002-2012 The Nucleus Group
\r
18 * @version $Id: backup.php 1624 2012-01-09 11:36:20Z sakamocchi $
\r
25 * Constructor, just for compatibility
\r
32 public function Backup()
\r
38 * Backup::do_backup()
\r
39 * This function creates an sql dump of the database and sends it to
\r
40 * the user as a file (can be gzipped if they want)
\r
42 * NOTE: this remains not-static for compatibility
\r
44 * @param boolean $gzip 1 = compress backup file, 0 = no compression (default)
\r
48 public function do_backup($gzip = 0)
\r
50 global $manager, $nucleus;
\r
52 // tables of which backup is needed
\r
54 sql_table('actionlog'),
\r
57 sql_table('comment'),
\r
58 sql_table('config'),
\r
61 sql_table('member'),
\r
63 sql_table('skin_desc'),
\r
65 sql_table('template'),
\r
66 sql_table('template_desc'),
\r
67 sql_table('plugin'),
\r
68 sql_table('plugin_event'),
\r
69 sql_table('plugin_option'),
\r
70 sql_table('plugin_option_desc'),
\r
71 sql_table('category'),
\r
72 sql_table('activation'),
\r
73 sql_table('tickets'),
\r
76 // add tables that plugins want to backup to the list
\r
77 // catch all output generated by plugins
\r
79 $query = sprintf('SELECT pfile FROM %s', sql_table('plugin'));
\r
80 $res = DB::getResult($query);
\r
81 foreach ( $res as $row )
\r
83 $plug =& $manager->getPlugin($row['pfile']);
\r
86 $tables = array_merge($tables, (array) $plug->getTableList());
\r
91 // remove duplicates
\r
92 $tables = array_unique($tables);
\r
94 // make sure browsers don't cache the backup
\r
95 header("Pragma: no-cache");
\r
97 // don't allow gzip compression when extension is not loaded
\r
98 if ( ($gzip != 0) && !extension_loaded("zlib") )
\r
105 $filename = 'nucleus_db_backup_' . i18n::formatted_datetime('%Y-%m-%d-%H-%M-%S', time()) . ".sql";
\r
109 // use an output buffer
\r
111 @ob_implicit_flush(0);
\r
114 $filename = 'nucleus_db_backup_' . i18n::formatted_datetime('%Y-%m-%d-%H-%M-%S', time()) . ".sql.gz";
\r
117 // send headers that tell the browser a file is coming
\r
118 header("Content-Type: text/x-delimtext; name=\"$filename\"");
\r
119 header("Content-disposition: attachment; filename=$filename");
\r
123 echo " * This is a backup file generated by Nucleus \n";
\r
124 echo " * http://www.nucleuscms.org/\n";
\r
126 echo " * backup-date: " . i18n::formatted_datetime('rfc822GMT', time()) . "\n";
\r
127 echo " * Nucleus CMS version: " . $nucleus['version'] . "\n";
\r
129 echo " * WARNING: Only try to restore on servers running the exact same version of Nucleus\n";
\r
134 array_walk($tables, array(__CLASS__, 'dump_table'));
\r
138 $Size = ob_get_length();
\r
139 $Crc = crc32(ob_get_contents());
\r
140 $contents = gzcompress(ob_get_contents());
\r
142 echo "\x1f\x8b\x08\x00\x00\x00\x00\x00" . substr($contents, 0, strlen($contents) - 4)
\r
143 . self::gzip_print_four_characters($Crc) . self::gzip_print_four_characters($Size);
\r
149 * Backup::dump_table()
\r
150 * Creates a dump for a single table
\r
151 * ($tablename and $key are filled in by array_walk)
\r
154 * @param string $tablename
\r
155 * @param string $key
\r
157 static private function dump_table($tablename, $key)
\r
160 echo " * TABLE: " . $tablename . "\n";
\r
163 // dump table structure
\r
164 self::dump_structure($tablename);
\r
166 // dump table contents
\r
167 self::dump_contents($tablename);
\r
172 * Backup::dump_structure()
\r
173 * Creates a dump of the table structure for one table
\r
176 * @param string $tablename
\r
180 static private function dump_structure($tablename)
\r
182 // add command to drop table on restore
\r
183 echo "DROP TABLE IF EXISTS {$tablename};\n\n";
\r
184 $result = DB::getRow("SHOW CREATE TABLE {$tablename}");
\r
185 echo $result['Create Table'];
\r
191 * Backup::get_field_names()
\r
192 * Returns the field named for the given table in the
\r
193 * following format:
\r
194 * (column1, column2, ..., columnn)
\r
197 * @param resource $result
\r
198 * @param integer $num_fields
\r
201 static private function get_field_names($result, $num_fields)
\r
204 for ( $j = 0; $j < $num_fields; $j++ )
\r
206 $col = $result->getColumnMeta($j);
\r
207 $fields[] = $col['name'];
\r
210 return '(' . implode(', ', $fields) . ')';
\r
214 * Backup::dump_contents()
\r
215 * Creates a dump of the table content for one table
\r
218 * @param string $tablename
\r
222 static private function dump_contents($tablename)
\r
225 * Grab the data from the table.
\r
227 $result = DB::getResult("SELECT * FROM $tablename");
\r
229 if ( $result->rowCount() > 0 )
\r
233 echo " * Table Data for {$tablename}\n";
\r
237 $num_fields = $result->columnCount();
\r
240 * Compose fieldname list
\r
242 $tablename_list = self::get_field_names($result, $num_fields);
\r
245 * Loop through the resulting rows and build the sql statement.
\r
247 foreach ( $result as $row )
\r
249 // Start building the SQL statement.
\r
250 echo 'INSERT INTO ' . $tablename . ' ' . $tablename_list . ' VALUES(';
\r
252 // Loop through the rows and fill in data for each column
\r
253 for ( $j = 0; $j < $num_fields; $j++ )
\r
255 if ( !isset($row[$j]) )
\r
257 // no data for column
\r
260 elseif ( $row[$j] != '' )
\r
263 echo ' ' . DB::quoteValue($row[$j]);
\r
267 // empty column (!= no data!)
\r
271 // only add comma when not last column
\r
272 if ( $j != ($num_fields - 1) )
\r
284 * Backup::gzip_print_four_characters()
\r
287 * @param integer $val
\r
290 static private function gzip_print_four_characters($Val)
\r
292 for ( $i = 0; $i < 4; $i ++ )
\r
294 $return .= chr($Val % 256);
\r
295 $Val = floor($Val / 256);
\r
301 * Backup::do_restore()
\r
302 * Restores a database backup
\r
304 * NOTE: this remains not-static for compatibility
\r
309 public function do_restore()
\r
311 $uploadInfo = postFileInfo('backup_file');
\r
313 // first of all: get uploaded file:
\r
314 if ( array_key_exists('name', $uploadInfo) && empty($uploadInfo['name']) )
\r
316 return 'No file uploaded';
\r
318 if ( !is_uploaded_file($uploadInfo['tmp_name']) )
\r
320 return 'No file uploaded';
\r
323 $backup_file_name = $uploadInfo['name'];
\r
324 $backup_file_tmpname = $uploadInfo['tmp_name'];
\r
325 $backup_file_type = $uploadInfo['type'];
\r
327 if ( !file_exists($backup_file_tmpname) )
\r
329 return 'File Upload Error';
\r
332 if ( !preg_match("#^(text/[a-zA-Z]+)|(application/(x\-)?gzip(\-compressed)?)|(application/octet-stream)$#i", $backup_file_type) )
\r
334 return 'The uploaded file is not of the correct type';
\r
338 if ( preg_match("#\.gz#i", $backup_file_name) )
\r
343 if ( !extension_loaded("zlib") && $gzip )
\r
345 return 'Cannot decompress gzipped backup (zlib package not installed)';
\r
348 // get sql query according to gzip setting (either decompress, or not)
\r
349 $contents = self::get_contents($backup_file_tmpname, $gzip);
\r
350 if ( $contents == '' )
\r
352 return 'Cannot get contents from this file.';
\r
356 $lines = preg_split('/[\r\n]/', $contents);
\r
357 if( $lines === $contents )
\r
359 return 'Cannot parse contents from this file';
\r
362 /* get sql statements from each lines */
\r
363 $queries = self::get_queries($lines);
\r
364 if ( $queries === array() )
\r
366 return "Cannot get SQL queries from this file.";
\r
369 /* execute sql statements */
\r
370 foreach ( $queries as $query )
\r
372 if ( DB::execute($query) === FALSE )
\r
374 $error = DB::getError();
\r
375 debug('SQL Error: ' . $error[2]);
\r
383 static private function get_contents($temporary_name, $gzip = 0)
\r
388 // decompress and read
\r
389 $gz_ptr = gzopen($temporary_name, 'rb');
\r
390 while ( !gzeof($gz_ptr) )
\r
392 $contents .= gzgets($gz_ptr, 100000);
\r
398 $fsize = filesize($temporary_name);
\r
401 $contents = fread(fopen($temporary_name, 'r'), $fsize);
\r
407 static private function get_queries($lines)
\r
410 $queries = array();
\r
411 foreach ( $lines as $line )
\r
413 $line = trim($line);
\r
414 if ( !$line || $line[0] == '#' || preg_match('#^[\s|/]?\*#', $line) )
\r
419 if ( preg_match('/^(.*);$/', $line, $matches) === 0 )
\r
425 $query .= $matches[1];
\r
426 $queries[] = $query;
\r
436 * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
437 * Copyright (C) 2002-2009 The Nucleus Group
439 * This program is free software; you can redistribute it and/or
440 * modify it under the terms of the GNU General Public License
441 * as published by the Free Software Foundation; either version 2
442 * of the License, or (at your option) any later version.
443 * (see nucleus/documentation/index.html#license for more info)
446 * Scripts to create/restore a backup of the Nucleus database
448 * @license http://nucleuscms.org/license.txt GNU General Public License
449 * @copyright Copyright (C) 2002-2009 The Nucleus Group
450 * @version $Id: backup.php 1812 2012-05-01 14:59:07Z sakamocchi $
457 * Constructor, just for compatibility
464 public function Backup()
470 * Backup::do_backup()
471 * This function creates an sql dump of the database and sends it to
472 * the user as a file (can be gzipped if they want)
474 * NOTE: this remains not-static for compatibility
476 * @param boolean $gzip 1 = compress backup file, 0 = no compression (default)
480 public function do_backup($gzip = 0)
482 global $manager, $nucleus;
484 // tables of which backup is needed
486 sql_table('actionlog'),
489 sql_table('comment'),
495 sql_table('skin_desc'),
497 sql_table('template'),
498 sql_table('template_desc'),
500 sql_table('plugin_event'),
501 sql_table('plugin_option'),
502 sql_table('plugin_option_desc'),
503 sql_table('category'),
504 sql_table('activation'),
505 sql_table('tickets'),
508 // add tables that plugins want to backup to the list
509 // catch all output generated by plugins
511 $query = sprintf('SELECT pfile FROM %s', sql_table('plugin'));
512 $res = DB::getResult($query);
513 foreach ( $res as $row )
515 $plug =& $manager->getPlugin($row['pfile']);
518 $tables = array_merge($tables, (array) $plug->getTableList());
524 $tables = array_unique($tables);
526 // make sure browsers don't cache the backup
527 header("Pragma: no-cache");
529 // don't allow gzip compression when extension is not loaded
530 if ( ($gzip != 0) && !extension_loaded("zlib") )
537 $filename = 'nucleus_db_backup_' . i18n::formatted_datetime('%Y-%m-%d-%H-%M-%S', time()) . ".sql";
541 // use an output buffer
543 @ob_implicit_flush(0);
546 $filename = 'nucleus_db_backup_' . i18n::formatted_datetime('%Y-%m-%d-%H-%M-%S', time()) . ".sql.gz";
549 // send headers that tell the browser a file is coming
550 header("Content-Type: text/x-delimtext; name=\"$filename\"");
551 header("Content-disposition: attachment; filename=$filename");
555 echo " * This is a backup file generated by Nucleus \n";
556 echo " * http://www.nucleuscms.org/\n";
558 echo " * backup-date: " . i18n::formatted_datetime('rfc822GMT', time()) . "\n";
559 echo " * Nucleus CMS version: " . $nucleus['version'] . "\n";
561 echo " * WARNING: Only try to restore on servers running the exact same version of Nucleus\n";
566 /* NOTE: hope to use 'self' keyword here but works bad so here use __CLASS__ macro. */
567 array_walk($tables, array(__CLASS__, 'dump_table'));
571 $Size = ob_get_length();
572 $Crc = crc32(ob_get_contents());
573 $contents = gzcompress(ob_get_contents());
575 echo "\x1f\x8b\x08\x00\x00\x00\x00\x00" . substr($contents, 0, strlen($contents) - 4)
576 . self::gzip_print_four_characters($Crc) . self::gzip_print_four_characters($Size);
582 * Backup::dump_table()
583 * Creates a dump for a single table
584 * ($tablename and $key are filled in by array_walk)
587 * @param string $tablename
590 static private function dump_table($tablename, $key)
593 echo " * TABLE: " . $tablename . "\n";
596 // dump table structure
597 self::dump_structure($tablename);
599 // dump table contents
600 self::dump_contents($tablename);
605 * Backup::dump_structure()
606 * Creates a dump of the table structure for one table
609 * @param string $tablename
613 static private function dump_structure($tablename)
615 // add command to drop table on restore
616 echo "DROP TABLE IF EXISTS {$tablename};\n\n";
617 $result = DB::getRow("SHOW CREATE TABLE {$tablename}");
618 echo $result['Create Table'];
624 * Backup::get_field_names()
625 * Returns the field named for the given table in the
627 * (column1, column2, ..., columnn)
630 * @param resource $result
631 * @param integer $num_fields
634 static private function get_field_names($result, $num_fields)
637 for ( $j = 0; $j < $num_fields; $j++ )
639 $col = $result->getColumnMeta($j);
640 $fields[] = $col['name'];
643 return '(' . implode(', ', $fields) . ')';
647 * Backup::dump_contents()
648 * Creates a dump of the table content for one table
651 * @param string $tablename
655 static private function dump_contents($tablename)
658 * Grab the data from the table.
660 $result = DB::getResult("SELECT * FROM $tablename");
662 if ( $result->rowCount() > 0 )
666 echo " * Table Data for {$tablename}\n";
670 $num_fields = $result->columnCount();
673 * Compose fieldname list
675 $tablename_list = self::get_field_names($result, $num_fields);
678 * Loop through the resulting rows and build the sql statement.
680 foreach ( $result as $row )
682 // Start building the SQL statement.
683 echo 'INSERT INTO ' . $tablename . ' ' . $tablename_list . ' VALUES(';
685 // Loop through the rows and fill in data for each column
686 for ( $j = 0; $j < $num_fields; $j++ )
688 if ( !isset($row[$j]) )
690 // no data for column
693 elseif ( $row[$j] != '' )
696 echo ' ' . DB::quoteValue($row[$j]);
700 // empty column (!= no data!)
704 // only add comma when not last column
705 if ( $j != ($num_fields - 1) )
717 * Backup::gzip_print_four_characters()
720 * @param integer $val
723 static private function gzip_print_four_characters($Val)
725 for ( $i = 0; $i < 4; $i ++ )
727 $return .= chr($Val % 256);
728 $Val = floor($Val / 256);
734 * Backup::do_restore()
735 * Restores a database backup
737 * NOTE: this remains not-static for compatibility
742 public function do_restore()
744 $uploadInfo = postFileInfo('backup_file');
746 // first of all: get uploaded file:
747 if ( array_key_exists('name', $uploadInfo) && empty($uploadInfo['name']) )
749 return 'No file uploaded';
751 if ( !is_uploaded_file($uploadInfo['tmp_name']) )
753 return 'No file uploaded';
756 $backup_file_name = $uploadInfo['name'];
757 $backup_file_tmpname = $uploadInfo['tmp_name'];
758 $backup_file_type = $uploadInfo['type'];
760 if ( !file_exists($backup_file_tmpname) )
762 return 'File Upload Error';
765 if ( !preg_match("#^(text/[a-zA-Z]+)|(application/(x\-)?gzip(\-compressed)?)|(application/octet-stream)$#i", $backup_file_type) )
767 return 'The uploaded file is not of the correct type';
771 if ( preg_match("#\.gz#i", $backup_file_name) )
776 if ( !extension_loaded("zlib") && $gzip )
778 return 'Cannot decompress gzipped backup (zlib package not installed)';
781 // get sql query according to gzip setting (either decompress, or not)
782 $contents = self::get_contents($backup_file_tmpname, $gzip);
783 if ( $contents == '' )
785 return 'Cannot get contents from this file.';
789 $lines = preg_split('/[\r\n]/', $contents);
790 if( $lines === $contents )
792 return 'Cannot parse contents from this file';
795 /* get sql statements from each lines */
796 $queries = self::get_queries($lines);
797 if ( $queries === array() )
799 return "Cannot get SQL queries from this file.";
802 /* execute sql statements */
803 foreach ( $queries as $query )
805 if ( DB::execute($query) === FALSE )
807 $error = DB::getError();
808 debug('SQL Error: ' . $error[2]);
816 static private function get_contents($temporary_name, $gzip = 0)
821 // decompress and read
822 $gz_ptr = gzopen($temporary_name, 'rb');
823 while ( !gzeof($gz_ptr) )
825 $contents .= gzgets($gz_ptr, 100000);
831 $fsize = filesize($temporary_name);
834 $contents = fread(fopen($temporary_name, 'r'), $fsize);
840 static private function get_queries($lines)
844 foreach ( $lines as $line )
847 if ( !$line || $line[0] == '#' || preg_match('#^[\s|/]?\*#', $line) )
852 if ( preg_match('/^(.*);$/', $line, $matches) === 0 )
858 $query .= $matches[1];
866 >>>>>>> skinnable-master