getPlugin($row['pfile']); if ( $plug ) { $tables = array_merge($tables, (array) $plug->getTableList()); } } ob_end_clean(); // remove duplicates $tables = array_unique($tables); // make sure browsers don't cache the backup header("Pragma: no-cache"); // don't allow gzip compression when extension is not loaded if ( ($gzip != 0) && !extension_loaded("zlib") ) { $gzip = 0; } if ( !$gzip ) { $filename = 'nucleus_db_backup_' . i18n::formatted_datetime('%Y-%m-%d-%H-%M-%S', time()) . ".sql"; } else { // use an output buffer @ob_start(); @ob_implicit_flush(0); // set filename $filename = 'nucleus_db_backup_' . i18n::formatted_datetime('%Y-%m-%d-%H-%M-%S', time()) . ".sql.gz"; } // send headers that tell the browser a file is coming header("Content-Type: text/x-delimtext; name=\"$filename\""); header("Content-disposition: attachment; filename=$filename"); // dump header echo "/*\n"; echo " * This is a backup file generated by Nucleus \n"; echo " * http://www.nucleuscms.org/\n"; echo " * \n"; echo " * backup-date: " . i18n::formatted_datetime('rfc822GMT', time()) . "\n"; echo " * Nucleus CMS version: " . $nucleus['version'] . "\n"; echo " * \n"; echo " * WARNING: Only try to restore on servers running the exact same version of Nucleus\n"; echo " */\n"; // dump all tables reset($tables); /* NOTE: hope to use 'self' keyword here but works bad so here use __CLASS__ macro. */ array_walk($tables, array(__CLASS__, 'dump_table')); if ( $gzip ) { $Size = ob_get_length(); $Crc = crc32(ob_get_contents()); $contents = gzcompress(ob_get_contents()); ob_end_clean(); echo "\x1f\x8b\x08\x00\x00\x00\x00\x00" . substr($contents, 0, strlen($contents) - 4) . self::gzip_print_four_characters($Crc) . self::gzip_print_four_characters($Size); } exit; } /** * Backup::dump_table() * Creates a dump for a single table * ($tablename and $key are filled in by array_walk) * * @static * @param string $tablename * @param string $key */ static private function dump_table($tablename, $key) { echo "/*\n"; echo " * TABLE: " . $tablename . "\n"; echo " */\n"; // dump table structure self::dump_structure($tablename); // dump table contents self::dump_contents($tablename); return; } /** * Backup::dump_structure() * Creates a dump of the table structure for one table * * @static * @param string $tablename * @return void * */ static private function dump_structure($tablename) { // add command to drop table on restore echo "DROP TABLE IF EXISTS {$tablename};\n\n"; $result = DB::getRow("SHOW CREATE TABLE {$tablename}"); echo $result['Create Table']; echo ";\n\n"; return; } /** * Backup::get_field_names() * Returns the field named for the given table in the * following format: * (column1, column2, ..., columnn) * * @static * @param resource $result * @param integer $num_fields * @return string */ static private function get_field_names($result, $num_fields) { $fields = array(); for ( $j = 0; $j < $num_fields; $j++ ) { $col = $result->getColumnMeta($j); $fields[] = $col['name']; } return '(' . implode(', ', $fields) . ')'; } /** * Backup::dump_contents() * Creates a dump of the table content for one table * * @static * @param string $tablename * @return void * */ static private function dump_contents($tablename) { /* * Grab the data from the table. */ $result = DB::getResult("SELECT * FROM $tablename"); if ( $result->rowCount() > 0 ) { echo "\n"; echo "/*\n"; echo " * Table Data for {$tablename}\n"; echo " */\n"; } $num_fields = $result->columnCount(); /* * Compose fieldname list */ $tablename_list = self::get_field_names($result, $num_fields); /* * Loop through the resulting rows and build the sql statement. */ foreach ( $result as $row ) { // Start building the SQL statement. echo 'INSERT INTO ' . $tablename . ' ' . $tablename_list . ' VALUES('; // Loop through the rows and fill in data for each column for ( $j = 0; $j < $num_fields; $j++ ) { if ( !isset($row[$j]) ) { // no data for column echo ' NULL'; } elseif ( $row[$j] != '' ) { // data echo ' ' . DB::quoteValue($row[$j]); } else { // empty column (!= no data!) echo "''"; } // only add comma when not last column if ( $j != ($num_fields - 1) ) { echo ','; } } echo ");\n"; } echo "\n"; return; } /** * Backup::gzip_print_four_characters() * * @static * @param integer $val * @return integer */ static private function gzip_print_four_characters($Val) { for ( $i = 0; $i < 4; $i ++ ) { $return .= chr($Val % 256); $Val = floor($Val / 256); } return $return; } /** * Backup::do_restore() * Restores a database backup * * NOTE: this remains not-static for compatibility * * @param void * @return void */ public function do_restore() { $uploadInfo = postFileInfo('backup_file'); // first of all: get uploaded file: if ( array_key_exists('name', $uploadInfo) && empty($uploadInfo['name']) ) { return 'No file uploaded'; } if ( !is_uploaded_file($uploadInfo['tmp_name']) ) { return 'No file uploaded'; } $backup_file_name = $uploadInfo['name']; $backup_file_tmpname = $uploadInfo['tmp_name']; $backup_file_type = $uploadInfo['type']; if ( !file_exists($backup_file_tmpname) ) { return 'File Upload Error'; } if ( !preg_match("#^(text/[a-zA-Z]+)|(application/(x\-)?gzip(\-compressed)?)|(application/octet-stream)$#i", $backup_file_type) ) { return 'The uploaded file is not of the correct type'; } $gzip = 0; if ( preg_match("#\.gz#i", $backup_file_name) ) { $gzip = 1; } if ( !extension_loaded("zlib") && $gzip ) { return 'Cannot decompress gzipped backup (zlib package not installed)'; } // get sql query according to gzip setting (either decompress, or not) $contents = self::get_contents($backup_file_tmpname, $gzip); if ( $contents == '' ) { return 'Cannot get contents from this file.'; } /* detect lines */ $lines = preg_split('/[\r\n]/', $contents); if( $lines === $contents ) { return 'Cannot parse contents from this file'; } /* get sql statements from each lines */ $queries = self::get_queries($lines); if ( $queries === array() ) { return "Cannot get SQL queries from this file."; } /* execute sql statements */ foreach ( $queries as $query ) { if ( DB::execute($query) === FALSE ) { $error = DB::getError(); debug('SQL Error: ' . $error[2]); break; } continue; } return; } static private function get_contents($temporary_name, $gzip = 0) { $contents = ''; if ( $gzip ) { // decompress and read $gz_ptr = gzopen($temporary_name, 'rb'); while ( !gzeof($gz_ptr) ) { $contents .= gzgets($gz_ptr, 100000); } } else { // just read $fsize = filesize($temporary_name); if ( $fsize > 0 ) { $contents = fread(fopen($temporary_name, 'r'), $fsize); } } return $contents; } static private function get_queries($lines) { $query = ''; $queries = array(); foreach ( $lines as $line ) { $line = trim($line); if ( !$line || $line[0] == '#' || preg_match('#^[\s|/]?\*#', $line) ) { continue; } if ( preg_match('/^(.*);$/', $line, $matches) === 0 ) { $query .= $line; } else { $query .= $matches[1]; $queries[] = $query; $query = ''; } continue; } return $queries; } }