Esempio n. 1
0
 public function __construct($skin = null, $info = null, $shortinit = false)
 {
     global $wpdb;
     // Line up a wpdb-like object to use
     $this->use_wpdb = !function_exists('mysql_query') && !function_exists('mysqli_query') || !$wpdb->is_mysql || !$wpdb->ready ? true : false;
     $this->our_siteurl = untrailingslashit(site_url());
     if (false == $this->use_wpdb) {
         // We have our own extension which drops lots of the overhead on the query
         $wpdb_obj = new UpdraftPlus_WPDB(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
         // Was that successful?
         if (!$wpdb_obj->is_mysql || !$wpdb_obj->ready) {
             $this->use_wpdb = true;
         } else {
             $this->wpdb_obj = $wpdb_obj;
             $this->mysql_dbh = $wpdb_obj->updraftplus_getdbh();
             $this->use_mysqli = $wpdb_obj->updraftplus_use_mysqli();
         }
     }
     if ($shortinit) {
         return;
     }
     $this->ud_backup_info = $info;
     $this->ud_foreign = empty($info['meta_foreign']) ? false : $info['meta_foreign'];
     parent::__construct($skin);
     $this->init();
     $this->backup_strings();
     $this->is_multisite = is_multisite();
 }
 public function __construct($skin = null, $info = null, $shortinit = false, $restore_options = array())
 {
     global $wpdb;
     // Line up a wpdb-like object
     $this->use_wpdb = !function_exists('mysql_query') && !function_exists('mysqli_query') || !$wpdb->is_mysql || !$wpdb->ready ? true : false;
     $this->our_siteurl = untrailingslashit(site_url());
     if (false == $this->use_wpdb) {
         // We have our own extension which drops lots of the overhead on the query
         $wpdb_obj = new UpdraftPlus_WPDB(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
         // Was that successful?
         if (!$wpdb_obj->is_mysql || !$wpdb_obj->ready) {
             $this->use_wpdb = true;
         } else {
             $this->wpdb_obj = $wpdb_obj;
             $this->mysql_dbh = $wpdb_obj->updraftplus_getdbh();
             $this->use_mysqli = $wpdb_obj->updraftplus_use_mysqli();
         }
     }
     if ($shortinit) {
         return;
     }
     $this->ud_backup_info = $info;
     do_action('updraftplus_restorer_restore_options', $restore_options);
     $this->ud_multisite_selective_restore = is_array($restore_options) && !empty($restore_options['updraft_restore_ms_whichsites']) && $restore_options['updraft_restore_ms_whichsites'] > 0 ? $restore_options['updraft_restore_ms_whichsites'] : false;
     $this->ud_restore_options = $restore_options;
     $this->ud_foreign = empty($info['meta_foreign']) ? false : $info['meta_foreign'];
     if (isset($info['is_multisite'])) {
         $this->ud_backup_is_multisite = $info['is_multisite'];
     }
     if (isset($info['created_by_version'])) {
         $this->created_by_version = $info['created_by_version'];
     }
     add_filter('updraftplus_logline', array($this, 'updraftplus_logline'), 10, 5);
     parent::__construct($skin);
     $this->init();
     $this->backup_strings();
     $this->is_multisite = is_multisite();
 }
Esempio n. 3
0
 function restore_backup_db($working_dir, $working_dir_localpath, &$import_table_prefix)
 {
     do_action('updraftplus_restore_db_pre');
     # This is now a legacy option (at least on the front end), so we should not see it much
     $this->prior_upload_path = get_option('upload_path');
     // There is a file backup.db.gz inside the working directory
     # The 'off' check is for badly configured setups - http://wordpress.org/support/topic/plugin-wp-super-cache-warning-php-safe-mode-enabled-but-safe-mode-is-off
     if (@ini_get('safe_mode') && 'off' != strtolower(@ini_get('safe_mode'))) {
         echo "<p>" . __('Warning: PHP safe_mode is active on your server. Timeouts are much more likely. If these happen, then you will need to manually restore the file via phpMyAdmin or another method.', 'updraftplus') . "</p><br/>";
         return false;
     }
     // wp_filesystem has no gzopen method, so we switch to using the local filesystem (which is harmless, since we are performing read-only operations)
     if (!is_readable($working_dir_localpath . '/backup.db.gz')) {
         return new WP_Error('gzopen_failed', __('Failed to find database file', 'updraftplus') . " ({$working_dir}/backup.db.gz)");
     }
     global $wpdb, $updraftplus;
     $this->skin->feedback('restore_database');
     // Read-only access: don't need to go through WP_Filesystem
     $dbhandle = gzopen($working_dir_localpath . '/backup.db.gz', 'r');
     if (!$dbhandle) {
         return new WP_Error('gzopen_failed', __('Failed to open database file', 'updraftplus'));
     }
     $this->line = 0;
     // Line up a wpdb-like object to use
     // mysql_query will throw E_DEPRECATED from PHP 5.5, so we expect WordPress to have switched to something else by then
     // 			$use_wpdb = (version_compare(phpversion(), '5.5', '>=') || !function_exists('mysql_query') || !$wpdb->is_mysql || !$wpdb->ready) ? true : false;
     // Seems not - PHP 5.5 is immanent for release
     $this->use_wpdb = !function_exists('mysql_query') || !$wpdb->is_mysql || !$wpdb->ready ? true : false;
     if (false == $this->use_wpdb) {
         // We have our own extension which drops lots of the overhead on the query
         $wpdb_obj = new UpdraftPlus_WPDB(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
         // Was that successful?
         if (!$wpdb_obj->is_mysql || !$wpdb_obj->ready) {
             $this->use_wpdb = true;
         } else {
             $this->mysql_dbh = $wpdb_obj->updraftplus_getdbh();
         }
     }
     if (true == $this->use_wpdb) {
         $updraftplus->log_e('Database access: Direct MySQL access is not available, so we are falling back to wpdb (this will be considerably slower)');
     } else {
         @mysql_query('SET SESSION query_cache_type = OFF;', $this->mysql_dbh);
     }
     // Find the supported engines - in case the dump had something else (case seen: saved from MariaDB with engine Aria; imported into plain MySQL without)
     $supported_engines = $wpdb->get_results("SHOW ENGINES", OBJECT_K);
     $this->errors = 0;
     $this->statements_run = 0;
     $this->tables_created = 0;
     $sql_line = "";
     $sql_type = -1;
     $this->start_time = microtime(true);
     $old_wpversion = '';
     $this->old_siteurl = '';
     $this->old_home = '';
     $this->old_content = '';
     $old_table_prefix = '';
     $old_siteinfo = array();
     $gathering_siteinfo = true;
     $this->create_forbidden = false;
     $this->drop_forbidden = false;
     $this->last_error = '';
     $random_table_name = 'updraft_tmp_' . rand(0, 9999999) . md5(microtime(true));
     if ($this->use_wpdb) {
         $req = $wpdb->query("CREATE TABLE {$random_table_name}");
         if (!$req) {
             $this->last_error = $wpdb->last_error;
         }
         $this->last_error_no = false;
     } else {
         $req = mysql_unbuffered_query("CREATE TABLE {$random_table_name}", $this->mysql_dbh);
         if (!$req) {
             $this->last_error = mysql_error($this->mysql_dbh);
             $this->last_error_no = mysql_errno($this->mysql_dbh);
         }
     }
     if (!$req && ($this->use_wpdb || $this->last_error_no === 1142)) {
         $this->create_forbidden = true;
         # If we can't create, then there's no point dropping
         $this->drop_forbidden = true;
         echo '<strong>' . __('Warning:', 'updraftplus') . '</strong> ';
         $updraftplus->log_e('Your database user does not have permission to create tables. We will attempt to restore by simply emptying the tables; this should work as long as a) you are restoring from a WordPress version with the same database structure, and b) Your imported database does not contain any tables which are not already present on the importing site.', ' (' . $this->last_error . ')');
     } else {
         if ($this->use_wpdb) {
             $req = $wpdb->query("DROP TABLE {$random_table_name}");
             if (!$req) {
                 $this->last_error = $wpdb->last_error;
             }
             $this->last_error_no = false;
         } else {
             $req = mysql_unbuffered_query("DROP TABLE {$random_table_name}", $this->mysql_dbh);
             if (!$req) {
                 $this->last_error = mysql_error($this->mysql_dbh);
                 $this->last_error_no = mysql_errno($this->mysql_dbh);
             }
         }
         if (!$req && ($this->use_wpdb || $this->last_error_no === 1142)) {
             $this->drop_forbidden = true;
             echo '<strong>' . __('Warning:', 'updraftplus') . '</strong> ';
             $updraftplus->log_e('Your database user does not have permission to drop tables. We will attempt to restore by simply emptying the tables; this should work as long as you are restoring from a WordPress version with the same database structure (%s)', ' (' . $this->last_error . ')');
         }
     }
     $restoring_table = '';
     $max_allowed_packet = $updraftplus->get_max_packet_size();
     while (!gzeof($dbhandle)) {
         // Up to 1Mb
         $buffer = rtrim(gzgets($dbhandle, 1048576));
         // Discard comments
         if (empty($buffer) || substr($buffer, 0, 1) == '#') {
             if ('' == $this->old_siteurl && preg_match('/^\\# Backup of: (http(.*))$/', $buffer, $matches)) {
                 $this->old_siteurl = untrailingslashit($matches[1]);
                 $updraftplus->log_e('<strong>Backup of:</strong> %s', htmlspecialchars($this->old_siteurl));
                 do_action('updraftplus_restore_db_record_old_siteurl', $this->old_siteurl);
             } elseif (false === $this->created_by_version && preg_match('/^\\# Created by UpdraftPlus version ([\\d\\.]+)/', $buffer, $matches)) {
                 $this->created_by_version = trim($matches[1]);
                 echo '<strong>' . __('Backup created by:', 'updraftplus') . '</strong> ' . htmlspecialchars($this->created_by_version) . '<br>';
                 $updraftplus->log('Backup created by: ' . $this->created_by_version);
             } elseif ('' == $this->old_home && preg_match('/^\\# Home URL: (http(.*))$/', $buffer, $matches)) {
                 $this->old_home = untrailingslashit($matches[1]);
                 if ($this->old_siteurl && $this->old_home != $this->old_siteurl) {
                     echo '<strong>' . __('Site home:', 'updraftplus') . '</strong> ' . htmlspecialchars($this->old_home) . '<br>';
                     $updraftplus->log('Site home: ' . $this->old_home);
                 }
                 do_action('updraftplus_restore_db_record_old_home', $this->old_home);
             } elseif ('' == $this->old_content && preg_match('/^\\# Content URL: (http(.*))$/', $buffer, $matches)) {
                 $this->old_content = untrailingslashit($matches[1]);
                 echo '<strong>' . __('Content URL:', 'updraftplus') . '</strong> ' . htmlspecialchars($this->old_content) . '<br>';
                 $updraftplus->log('Content URL: ' . $this->old_content);
                 do_action('updraftplus_restore_db_record_old_content', $this->old_content);
             } elseif ('' == $old_table_prefix && preg_match('/^\\# Table prefix: (\\S+)$/', $buffer, $matches)) {
                 $old_table_prefix = $matches[1];
                 echo '<strong>' . __('Old table prefix:', 'updraftplus') . '</strong> ' . htmlspecialchars($old_table_prefix) . '<br>';
                 $updraftplus->log("Old table prefix: " . $old_table_prefix);
             } elseif ($gathering_siteinfo && preg_match('/^\\# Site info: (\\S+)$/', $buffer, $matches)) {
                 if ('end' == $matches[1]) {
                     $gathering_siteinfo = false;
                     // Sanity checks
                     if (isset($old_siteinfo['multisite']) && !$old_siteinfo['multisite'] && is_multisite()) {
                         // Just need to check that you're crazy
                         if (!defined('UPDRAFTPLUS_EXPERIMENTAL_IMPORTINTOMULTISITE') || UPDRAFTPLUS_EXPERIMENTAL_IMPORTINTOMULTISITE != true) {
                             return new WP_Error('multisite_error', $this->strings['multisite_error']);
                         }
                         // Got the needed code?
                         if (!class_exists('UpdraftPlusAddOn_MultiSite') || !class_exists('UpdraftPlus_Addons_Migrator')) {
                             return new WP_Error('missing_addons', __('To import an ordinary WordPress site into a multisite installation requires both the multisite and migrator add-ons.', 'updraftplus'));
                         }
                     }
                 } elseif (preg_match('/^([^=]+)=(.*)$/', $matches[1], $kvmatches)) {
                     $key = $kvmatches[1];
                     $val = $kvmatches[2];
                     echo '<strong>' . __('Site information:', 'updraftplus') . '</strong>' . ' ' . htmlspecialchars($key) . ' = ' . htmlspecialchars($val) . '<br>';
                     $updraftplus->log("Site information: " . $key . "=" . $val);
                     $old_siteinfo[$key] = $val;
                     if ('multisite' == $key) {
                         if ($val) {
                             $this->ud_backup_is_multisite = 1;
                         } else {
                             $this->ud_backup_is_multisite = 0;
                         }
                     }
                 }
             }
             continue;
         }
         // Detect INSERT commands early, so that we can split them if necessary
         if ($sql_line && preg_match('/^\\s*(insert into \\`?([^\\`]*)\\`?\\s+values)/i', $sql_line, $matches)) {
             $sql_type = 3;
             $insert_prefix = $matches[1];
         }
         # Deal with case where adding this line will take us over the MySQL max_allowed_packet limit - must split, if we can (if it looks like consecutive rows)
         # ALlow a 100-byte margin for error (including searching/replacing table prefix)
         if (3 == $sql_type && $sql_line && strlen($sql_line . $buffer) > $max_allowed_packet - 100 && preg_match('/,\\s*$/', $sql_line) && preg_match('/^\\s*\\(/', $buffer)) {
             // Remove the final comma; replace with semi-colon
             $sql_line = substr(rtrim($sql_line), 0, strlen($sql_line) - 1) . ';';
             if ('' != $old_table_prefix && $import_table_prefix != $old_table_prefix) {
                 $sql_line = $updraftplus->str_replace_once($old_table_prefix, $import_table_prefix, $sql_line);
             }
             # Run the SQL command; then set up for the next one.
             $this->line++;
             echo __("Split line to avoid exceeding maximum packet size", 'updraftplus') . " (" . strlen($sql_line) . " + " . strlen($buffer) . " : {$max_allowed_packet})<br>";
             $updraftplus->log("Split line to avoid exceeding maximum packet size (" . strlen($sql_line) . " + " . strlen($buffer) . " : {$max_allowed_packet})");
             $do_exec = $this->sql_exec($sql_line, $sql_type);
             # Reset, then carry on
             $sql_line = $insert_prefix . " ";
             if (is_wp_error($do_exec)) {
                 return $do_exec;
             }
         }
         $sql_line .= $buffer;
         # Do we have a complete line yet?
         if (';' != substr($sql_line, -1, 1)) {
             continue;
         }
         $this->line++;
         # We now have a complete line - process it
         if (3 == $sql_type && $sql_line && strlen($sql_line . $buffer) > $max_allowed_packet) {
             $logit = substr($sql_line . $buffer, 0, 100);
             $updraftplus->log(sprintf("An SQL line that is larger than the maximum packet size and cannot be split was found: %s", '(' . strlen($sql_line) . ', ' . strlen($buffer) . ', ' . $logit . ' ...)'));
             echo '<strong>' . __('Warning:', 'updraftplus') . '</strong> ' . sprintf(__("An SQL line that is larger than the maximum packet size and cannot be split was found; this line will not be processed, but will be dropped: %s", 'updraftplus'), '(' . strlen($sql_line) . ', ' . strlen($buffer) . ', ' . $logit . ' ...)') . "<br>";
             # Reset
             $sql_line = '';
             $sql_type = -1;
             continue;
         }
         # The timed overhead of this is negligible
         if (preg_match('/^\\s*drop table if exists \\`?([^\\`]*)\\`?\\s*;/i', $sql_line, $matches)) {
             $sql_type = 1;
             if (!isset($printed_new_table_prefix)) {
                 $import_table_prefix = $this->pre_sql_actions($import_table_prefix);
                 if (false === $import_table_prefix || is_wp_error($import_table_prefix)) {
                     return $import_table_prefix;
                 }
                 $printed_new_table_prefix = true;
             }
             $this->table_name = $matches[1];
             // Legacy, less reliable - in case it was not caught before
             if ('' == $old_table_prefix && preg_match('/^([a-z0-9]+)_.*$/i', $this->table_name, $tmatches)) {
                 $old_table_prefix = $tmatches[1] . '_';
                 echo '<strong>' . __('Old table prefix:', 'updraftplus') . '</strong> ' . htmlspecialchars($old_table_prefix) . '<br>';
                 $updraftplus->log("Old table prefix: {$old_table_prefix}");
             }
             $this->new_table_name = $old_table_prefix ? $updraftplus->str_replace_once($old_table_prefix, $import_table_prefix, $this->table_name) : $this->table_name;
             if ('' != $old_table_prefix && $import_table_prefix != $old_table_prefix) {
                 $sql_line = $updraftplus->str_replace_once($old_table_prefix, $import_table_prefix, $sql_line);
             }
         } elseif (preg_match('/^\\s*create table \\`?([^\\`\\(]*)\\`?\\s*\\(/i', $sql_line, $matches)) {
             $sql_type = 2;
             // MySQL 4.1 outputs TYPE=, but accepts ENGINE=; 5.1 onwards accept *only* ENGINE=
             $sql_line = $updraftplus->str_lreplace('TYPE=', 'ENGINE=', $sql_line);
             if (!isset($printed_new_table_prefix)) {
                 $import_table_prefix = $this->pre_sql_actions($import_table_prefix);
                 if (false === $import_table_prefix || is_wp_error($import_table_prefix)) {
                     return $import_table_prefix;
                 }
                 $printed_new_table_prefix = true;
             }
             // This CREATE TABLE command may be the de-facto mark for the end of processing a previous table (which is so if this is not the first table in the SQL dump)
             if ($restoring_table) {
                 // After restoring the options table, we can set old_siteurl if on legacy (i.e. not already set)
                 if ($restoring_table == $import_table_prefix . 'options') {
                     if ('' == $this->old_siteurl || '' == $this->old_home || '' == $this->old_content) {
                         global $updraftplus_addons_migrator;
                         if (isset($updraftplus_addons_migrator->new_blogid)) {
                             switch_to_blog($updraftplus_addons_migrator->new_blogid);
                         }
                         if ('' == $this->old_siteurl) {
                             $this->old_siteurl = untrailingslashit($wpdb->get_row("SELECT option_value FROM {$wpdb->options} WHERE option_name='siteurl'")->option_value);
                             do_action('updraftplus_restore_db_record_old_siteurl', $this->old_siteurl);
                         }
                         if ('' == $this->old_home) {
                             $this->old_home = untrailingslashit($wpdb->get_row("SELECT option_value FROM {$wpdb->options} WHERE option_name='home'")->option_value);
                             do_action('updraftplus_restore_db_record_old_home', $this->old_home);
                         }
                         if ('' == $this->old_content) {
                             $this->old_content = $this->old_siteurl . '/wp-content';
                             do_action('updraftplus_restore_db_record_old_content', $this->old_content);
                         }
                         if (isset($updraftplus_addons_migrator->new_blogid)) {
                             restore_current_blog();
                         }
                     }
                 }
                 $this->restored_table($restoring_table, $import_table_prefix, $old_table_prefix);
             }
             $engine = "(?)";
             $engine_change_message = '';
             if (preg_match('/ENGINE=([^\\s;]+)/', $sql_line, $eng_match)) {
                 $engine = $eng_match[1];
                 if (isset($supported_engines[$engine])) {
                     #echo sprintf(__('Requested table engine (%s) is present.', 'updraftplus'), $engine);
                     if ('myisam' == strtolower($engine)) {
                         $sql_line = preg_replace('/PAGE_CHECKSUM=\\d\\s?/', '', $sql_line, 1);
                     }
                 } else {
                     $engine_change_message = sprintf(__('Requested table engine (%s) is not present - changing to MyISAM.', 'updraftplus'), $engine) . "<br>";
                     $sql_line = $updraftplus->str_lreplace("ENGINE={$eng_match}", "ENGINE=MyISAM", $sql_line);
                     // Remove (M)aria options
                     if ('maria' == strtolower($engine) || 'aria' == strtolower($engine)) {
                         $sql_line = preg_replace('/PAGE_CHECKSUM=\\d\\s?/', '', $sql_line, 1);
                         $sql_line = preg_replace('/TRANSACTIONAL=\\d\\s?/', '', $sql_line, 1);
                     }
                 }
             }
             $this->table_name = $matches[1];
             echo '<strong>' . sprintf(__('Restoring table (%s)', 'updraftplus'), $engine) . ":</strong> " . htmlspecialchars($this->table_name);
             $logline = "Restoring table ({$engine}): " . $this->table_name;
             if ('' != $old_table_prefix && $import_table_prefix != $old_table_prefix) {
                 $new_table_name = $updraftplus->str_replace_once($old_table_prefix, $import_table_prefix, $this->table_name);
                 echo ' - ' . __('will restore as:', 'updraftplus') . ' ' . htmlspecialchars($new_table_name);
                 $logline .= " - will restore as: " . $new_table_name;
                 $sql_line = $updraftplus->str_replace_once($old_table_prefix, $import_table_prefix, $sql_line);
             } else {
                 $new_table_name = $this->table_name;
             }
             $updraftplus->log($logline);
             $restoring_table = $new_table_name;
             echo '<br>';
             if ($engine_change_message) {
                 echo $engine_change_message;
             }
         } elseif (preg_match('/^\\s*(insert into \\`?([^\\`]*)\\`?\\s+values)/i', $sql_line, $matches)) {
             $sql_type = 3;
             if ('' != $old_table_prefix && $import_table_prefix != $old_table_prefix) {
                 $sql_line = $updraftplus->str_replace_once($old_table_prefix, $import_table_prefix, $sql_line);
             }
         } elseif (preg_match('/^\\s*(\\/\\*\\!40000 alter|lock) tables? \\`?([^\\`\\(]*)\\`?\\s+(write|disable|enable)/i', $sql_line, $matches)) {
             # Only binary mysqldump produces this pattern (LOCK TABLES `table` WRITE, ALTER TABLE `table` (DISABLE|ENABLE) KEYS)
             $sql_type = 4;
             if ('' != $old_table_prefix && $import_table_prefix != $old_table_prefix) {
                 $sql_line = $updraftplus->str_replace_once($old_table_prefix, $import_table_prefix, $sql_line);
             }
         }
         $do_exec = $this->sql_exec($sql_line, $sql_type);
         if (is_wp_error($do_exec)) {
             return $do_exec;
         }
         # Reset
         $sql_line = '';
         $sql_type = -1;
     }
     if ($restoring_table) {
         $this->restored_table($restoring_table, $import_table_prefix, $old_table_prefix);
     }
     $time_taken = microtime(true) - $this->start_time;
     $updraftplus->log_e('Finished: lines processed: %d in %.2f seconds', $this->line, $time_taken);
     gzclose($dbhandle);
     global $wp_filesystem;
     $wp_filesystem->delete($working_dir . '/backup.db.gz', false, true);
     return true;
 }
Esempio n. 4
0
 public function updraftplus_restore_db_pre()
 {
     global $wpdb, $updraftplus;
     $this->siteurl = untrailingslashit(site_url());
     $this->home = untrailingslashit(home_url());
     $this->content = untrailingslashit(content_url());
     $this->use_wpdb = !function_exists('mysql_query') && !function_exists('mysqli_query') || !$wpdb->is_mysql || !$wpdb->ready ? true : false;
     $this->base_prefix = $updraftplus->get_table_prefix(false);
     $mysql_dbh = false;
     if (false == $this->use_wpdb) {
         // We have our own extension which drops lots of the overhead on the query
         // This class is defined in updraft-restorer.php, which has been included if we get here
         $wpdb_obj = new UpdraftPlus_WPDB(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
         // Was that successful?
         if (!$wpdb_obj->is_mysql || !$wpdb_obj->ready) {
             $this->use_wpdb = true;
         } else {
             $this->wpdb_obj = $wpdb_obj;
             $mysql_dbh = $wpdb_obj->updraftplus_getdbh();
             $use_mysqli = $wpdb_obj->updraftplus_use_mysqli();
         }
     }
     $this->mysql_dbh = $mysql_dbh;
     $this->use_mysqli = $use_mysqli;
     if (true == $this->use_wpdb) {
         $updraftplus->log_e('Database access: Direct MySQL access is not available, so we are falling back to wpdb (this will be considerably slower)');
     }
     if (is_multisite()) {
         $sites = $wpdb->get_results('SELECT id, domain, path FROM ' . esc_sql($this->base_prefix) . 'site', ARRAY_N);
         if (is_array($sites)) {
             $nsites = array();
             foreach ($sites as $site) {
                 $nsites[$site[0]] = array($site[1], $site[2]);
             }
             $this->original_sites = $nsites;
         }
     }
     $this->report = array('tables' => 0, 'rows' => 0, 'change' => 0, 'updates' => 0, 'timetaken' => 0, 'errors' => array());
 }
Esempio n. 5
0
 function restore_backup($backup_files, $type, $service, $info)
 {
     if (is_string($backup_files)) {
         $backup_files = array($backup_files);
     }
     // TODO
     $backup_file = $backup_files[0];
     if ($type == 'more') {
         show_message($this->strings['not_possible']);
         return;
     }
     global $wp_filesystem, $updraftplus_addons_migrator, $updraftplus;
     $wp_filesystem_dir = $this->get_wp_filesystem_dir($info['path']);
     if ($wp_filesystem_dir === false) {
         return false;
     }
     $wp_dir = trailingslashit($wp_filesystem->abspath());
     $wp_content_dir = trailingslashit($wp_filesystem->wp_content_dir());
     @set_time_limit(1800);
     $delete = UpdraftPlus_Options::get_updraft_option('updraft_delete_local') ? true : false;
     if ('none' == $service) {
         if ($delete) {
             _e('Will not delete the archive after unpacking it, because there was no cloud storage for this backup', 'updraftplus') . '<br>';
         }
         $delete = false;
     }
     // This returns the wp_filesystem path
     $working_dir = $this->unpack_package($backup_file, $delete);
     if (is_wp_error($working_dir)) {
         return $working_dir;
     }
     $working_dir_filesystem = WP_CONTENT_DIR . '/upgrade/' . basename($working_dir);
     global $table_prefix;
     // We copy the variable because we may be importing with a different prefix (e.g. on multisite imports of individual blog data)
     $import_table_prefix = $table_prefix;
     @set_time_limit(1800);
     if ($type == 'others') {
         $dirname = basename($info['path']);
         // In this special case, the backup contents are not in a folder, so it is not simply a case of moving the folder around, but rather looping over all that we find
         $this->move_backup_in($working_dir, trailingslashit($wp_filesystem_dir), true, array('plugins', 'themes', 'uploads', 'upgrade'), 'others');
     } elseif (is_multisite() && $this->ud_backup_is_multisite === 0 && ('plugins' == $type || 'themes' == $type || 'uploads' == $type && isset($updraftplus_addons_migrator['new_blogid'])) && $wp_filesystem->is_dir($working_dir . '/' . $type)) {
         # Migrating a single site into a multisite
         if ('plugins' == $type || 'themes' == $type) {
             // Only move in entities that are not already there (2)
             $this->move_backup_in($working_dir . '/' . $type, trailingslashit($wp_filesystem_dir), 2, array(), $type, true);
             @$wp_filesystem->delete($working_dir . '/' . $type);
         } else {
             // Uploads
             show_message($this->strings['moving_old']);
             switch_to_blog($updraftplus_addons_migrator['new_blogid']);
             $ud = wp_upload_dir();
             $wpud = $ud['basedir'];
             $fsud = trailingslashit($wp_filesystem->find_folder($wpud));
             restore_current_blog();
             // TODO: What is below will move the entire uploads directory if blog id is 1. Detect this situation. (Can that happen? We created a new blog, so should not be possible).
             // TODO: the upload dir is not necessarily reachable through wp_filesystem - try ordinary method instead
             if (is_string($fsud)) {
                 // This is not expected to exist, since we created a new blog
                 if ($wp_filesystem->exists($fsud) && !$wp_filesystem->move($fsud, untrailingslashit($fsud) . "-old", true)) {
                     return new WP_Error('old_move_failed', $this->strings['old_move_failed']);
                 }
                 show_message($this->strings['moving_backup']);
                 if (!$wp_filesystem->move($working_dir . "/" . $type, $fsud, true)) {
                     return new WP_Error('new_move_failed', $this->strings['new_move_failed']);
                 }
                 /*
                 					$this->move_backup_in($working_dir.'/'.$type, $wp_content_dir.$type.'/', 1, array(), $type);
                 					@$wp_filesystem->delete($working_dir.'/'.$type);*/
             } else {
                 return new WP_Error('move_failed', $this->strings['new_move_failed']);
             }
         }
     } elseif ('db' == $type) {
         do_action('updraftplus_restore_db_pre');
         // There is a file backup.db.gz inside the working directory
         # The 'off' check is for badly configured setups - http://wordpress.org/support/topic/plugin-wp-super-cache-warning-php-safe-mode-enabled-but-safe-mode-is-off
         if (@ini_get('safe_mode') && strtolower(@ini_get('safe_mode')) != "off") {
             echo "<p>" . __('Warning: PHP safe_mode is active on your server. Timeouts are much more likely. If these happen, then you will need to manually restore the file via phpMyAdmin or another method.', 'updraftplus') . "</p><br/>";
             return false;
         }
         // wp_filesystem has no gzopen method, so we switch to using the local filesystem (which is harmless, since we are performing read-only operations)
         if (!is_readable($working_dir_filesystem . '/backup.db.gz')) {
             return new WP_Error('gzopen_failed', __('Failed to find database file', 'updraftplus') . " ({$working_dir}/backup.db.gz)");
         }
         $this->skin->feedback('restore_database');
         // Read-only access: don't need to go through WP_Filesystem
         $dbhandle = gzopen($working_dir_filesystem . '/backup.db.gz', 'r');
         if (!$dbhandle) {
             return new WP_Error('gzopen_failed', __('Failed to open database file', 'updraftplus'));
         }
         $line = 0;
         global $wpdb;
         // Line up a wpdb-like object to use
         // mysql_query will throw E_DEPRECATED from PHP 5.5, so we expect WordPress to have switched to something else by then
         // 			$use_wpdb = (version_compare(phpversion(), '5.5', '>=') || !function_exists('mysql_query') || !$wpdb->is_mysql || !$wpdb->ready) ? true : false;
         // Seems not - PHP 5.5 is immanent for release
         $use_wpdb = !function_exists('mysql_query') || !$wpdb->is_mysql || !$wpdb->ready ? true : false;
         if (false == $use_wpdb) {
             // We have our own extension which drops lots of the overhead on the query
             $wpdb_obj = new UpdraftPlus_WPDB(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
             // Was that successful?
             if (!$wpdb_obj->is_mysql || !$wpdb_obj->ready) {
                 $use_wpdb = true;
             } else {
                 $mysql_dbh = $wpdb_obj->updraftplus_getdbh();
             }
         }
         if (true == $use_wpdb) {
             _e('Database access: Direct MySQL access is not available, so we are falling back to wpdb (this will be considerably slower)', 'updraftplus');
         } else {
             @mysql_query('SET SESSION query_cache_type = OFF;', $mysql_dbh);
         }
         // Find the supported engines - in case the dump had something else (case seen: saved from MariaDB with engine Aria; imported into plain MySQL without)
         $supported_engines = $wpdb->get_results("SHOW ENGINES", OBJECT_K);
         $errors = 0;
         $statements_run = 0;
         $tables_created = 0;
         $sql_line = "";
         $sql_type = -1;
         $start_time = microtime(true);
         // TODO: Print a warning if restoring to a different WP version
         $old_wpversion = '';
         $old_siteurl = '';
         $old_table_prefix = '';
         $old_siteinfo = array();
         $gathering_siteinfo = true;
         $create_forbidden = false;
         $drop_forbidden = false;
         $last_error = '';
         $random_table_name = 'updraft_tmp_' . rand(0, 9999999) . md5(microtime(true));
         if ($use_wpdb) {
             $req = $wpdb->query("CREATE TABLE {$random_table_name}");
             if (!$req) {
                 $last_error = $wpdb->last_error;
             }
             $last_error_no = false;
         } else {
             $req = mysql_unbuffered_query("CREATE TABLE {$random_table_name}", $mysql_dbh);
             if (!$req) {
                 $last_error = mysql_error($mysql_dbh);
                 $last_error_no = mysql_errno($mysql_dbh);
             }
         }
         if (!$req && ($use_wpdb || $last_error_no === 1142)) {
             $create_forbidden = true;
             # If we can't create, then there's no point dropping
             $drop_forbidden = true;
             echo '<strong>' . __('Warning:', 'updraftplus') . '</strong> ' . __('Your database user does not have permission to create tables. We will attempt to restore by simply emptying the tables; this should work as long as a) you are restoring from a WordPress version with the same database structure, and b) Your imported database does not contain any tables which are not already present on the importing site.', 'updraftplus') . ' (' . $last_error . ')' . "<br>";
         } else {
             if ($use_wpdb) {
                 $req = $wpdb->query("DROP TABLE {$random_table_name}");
                 if (!$req) {
                     $last_error = $wpdb->last_error;
                 }
                 $last_error_no = false;
             } else {
                 $req = mysql_unbuffered_query("DROP TABLE {$random_table_name}", $mysql_dbh);
                 if (!$req) {
                     $last_error = mysql_error($mysql_dbh);
                     $last_error_no = mysql_errno($mysql_dbh);
                 }
             }
             if (!$req && ($use_wpdb || $last_error_no === 1142)) {
                 $drop_forbidden = true;
                 echo '<strong>' . __('Warning:', 'updraftplus') . '</strong> ' . __('Your database user does not have permission to drop tables. We will attempt to restore by simply emptying the tables; this should work as long as you are restoring from a WordPress version with the same database structure', 'updraftplus') . ' (' . $last_error . ')' . "<br>";
             }
         }
         $restoring_table = '';
         while (!gzeof($dbhandle)) {
             // Up to 1Mb
             $buffer = rtrim(gzgets($dbhandle, 1048576));
             // Discard comments
             if (empty($buffer) || substr($buffer, 0, 1) == '#') {
                 if ('' == $old_siteurl && preg_match('/^\\# Backup of: (http(.*))$/', $buffer, $matches)) {
                     $old_siteurl = $matches[1];
                     echo '<strong>' . __('Backup of:', 'updraftplus') . '</strong> ' . htmlspecialchars($old_siteurl) . '<br>';
                     do_action('updraftplus_restore_db_record_old_siteurl', $old_siteurl);
                 } elseif ('' == $old_table_prefix && preg_match('/^\\# Table prefix: (\\S+)$/', $buffer, $matches)) {
                     $old_table_prefix = $matches[1];
                     echo '<strong>' . __('Old table prefix:', 'updraftplus') . '</strong> ' . htmlspecialchars($old_table_prefix) . '<br>';
                 } elseif ($gathering_siteinfo && preg_match('/^\\# Site info: (\\S+)$/', $buffer, $matches)) {
                     if ('end' == $matches[1]) {
                         $gathering_siteinfo = false;
                         // Sanity checks
                         if (isset($old_siteinfo['multisite']) && !$old_siteinfo['multisite'] && is_multisite()) {
                             // Just need to check that you're crazy
                             if (!defined('UPDRAFTPLUS_EXPERIMENTAL_IMPORTINTOMULTISITE') || UPDRAFTPLUS_EXPERIMENTAL_IMPORTINTOMULTISITE != true) {
                                 return new WP_Error('multisite_error', $this->strings['multisite_error']);
                             }
                             // Got the needed code?
                             if (!class_exists('UpdraftPlusAddOn_MultiSite') || !class_exists('UpdraftPlus_Addons_Migrator')) {
                                 return new WP_Error('missing_addons', __('To import an ordinary WordPress site into a multisite installation requires both the multisite and migrator add-ons.', 'updraftplus'));
                             }
                         }
                     } elseif (preg_match('/^([^=]+)=(.*)$/', $matches[1], $kvmatches)) {
                         $key = $kvmatches[1];
                         $val = $kvmatches[2];
                         echo '<strong>' . __('Site information:', 'updraftplus') . '</strong>' . ' ' . htmlspecialchars($key) . ' = ' . htmlspecialchars($val) . '<br>';
                         $old_siteinfo[$key] = $val;
                         if ('multisite' == $key) {
                             if ($val) {
                                 $this->ud_backup_is_multisite = 1;
                             } else {
                                 $this->ud_backup_is_multisite = 0;
                             }
                         }
                     }
                 }
                 continue;
             }
             $sql_line .= $buffer;
             # Do we have a complete line yet?
             if (';' != substr($sql_line, -1, 1)) {
                 continue;
             }
             $line++;
             # The timed overhead of this is negligible
             if (preg_match('/^\\s*drop table if exists \\`?([^\\`]*)\\`?\\s*;/i', $sql_line, $matches)) {
                 $sql_type = 1;
                 if (!isset($printed_new_table_prefix)) {
                     $import_table_prefix = $this->pre_sql_actions($import_table_prefix);
                     if (false === $import_table_prefix || is_wp_error($import_table_prefix)) {
                         return $import_table_prefix;
                     }
                     $printed_new_table_prefix = true;
                 }
                 $table_name = $matches[1];
                 // Legacy, less reliable - in case it was not caught before
                 if ($old_table_prefix == '' && preg_match('/^([a-z0-9]+)_.*$/i', $table_name, $tmatches)) {
                     $old_table_prefix = $tmatches[1] . '_';
                     echo '<strong>' . __('Old table prefix:', 'updraftplus') . '</strong> ' . htmlspecialchars($old_table_prefix) . '<br>';
                 }
                 if ('' != $old_table_prefix && $import_table_prefix != $old_table_prefix) {
                     $sql_line = $this->str_replace_once($old_table_prefix, $import_table_prefix, $sql_line);
                 }
             } elseif (preg_match('/^\\s*create table \\`?([^\\`\\(]*)\\`?\\s*\\(/i', $sql_line, $matches)) {
                 $sql_type = 2;
                 // MySQL 4.1 outputs TYPE=, but accepts ENGINE=; 5.1 onwards accept *only* ENGINE=
                 $sql_line = $updraftplus->str_lreplace('TYPE=', 'ENGINE=', $sql_line);
                 if (!isset($printed_new_table_prefix)) {
                     $import_table_prefix = $this->pre_sql_actions($import_table_prefix);
                     if (false === $import_table_prefix || is_wp_error($import_table_prefix)) {
                         return $import_table_prefix;
                     }
                     $printed_new_table_prefix = true;
                 }
                 // This CREATE TABLE command may be the de-facto mark for the end of processing a previous table (which is so if this is not the first table in the SQL dump)
                 if ($restoring_table) {
                     $this->restored_table($restoring_table, $import_table_prefix, $old_table_prefix);
                     // After restoring the options table, we can set old_siteurl if on legacy (i.e. not already set)
                     if ($restoring_table == $import_table_prefix . 'options') {
                         if ('' == $old_siteurl) {
                             global $updraftplus_addons_migrator;
                             if (isset($updraftplus_addons_migrator['new_blogid'])) {
                                 switch_to_blog($updraftplus_addons_migrator['new_blogid']);
                             }
                             $old_siteurl = $wpdb->get_row("SELECT option_value FROM {$wpdb->options} WHERE option_name='siteurl'")->option_value;
                             do_action('updraftplus_restore_db_record_old_siteurl', $old_siteurl);
                             if (isset($updraftplus_addons_migrator['new_blogid'])) {
                                 restore_current_blog();
                             }
                         }
                     }
                 }
                 $engine = "(?)";
                 $engine_change_message = '';
                 if (preg_match('/ENGINE=([^\\s;]+)/', $sql_line, $eng_match)) {
                     $engine = $eng_match[1];
                     if (isset($supported_engines[$engine])) {
                         #echo sprintf(__('Requested table engine (%s) is present.', 'updraftplus'), $engine);
                         if ('myisam' == strtolower($engine)) {
                             $sql_line = preg_replace('/PAGE_CHECKSUM=\\d\\s?/', '', $sql_line, 1);
                         }
                     } else {
                         $engine_change_message = sprintf(__('Requested table engine (%s) is not present - changing to MyISAM.', 'updraftplus'), $engine) . "<br>";
                         $sql_line = $updraftplus->str_lreplace("ENGINE={$eng_match}", "ENGINE=MyISAM", $sql_line);
                         // Remove (M)aria options
                         if ('maria' == strtolower($engine) || 'aria' == strtolower($engine)) {
                             $sql_line = preg_replace('/PAGE_CHECKSUM=\\d\\s?/', '', $sql_line, 1);
                             $sql_line = preg_replace('/TRANSACTIONAL=\\d\\s?/', '', $sql_line, 1);
                         }
                     }
                 }
                 $table_name = $matches[1];
                 echo '<strong>' . sprintf(__('Restoring table (%s)', 'updraftplus'), $engine) . ":</strong> " . htmlspecialchars($table_name);
                 if ('' != $old_table_prefix && $import_table_prefix != $old_table_prefix) {
                     $new_table_name = $this->str_replace_once($old_table_prefix, $import_table_prefix, $table_name);
                     echo ' - ' . __('will restore as:', 'updraftplus') . ' ' . htmlspecialchars($new_table_name);
                     $sql_line = $this->str_replace_once($old_table_prefix, $import_table_prefix, $sql_line);
                 } else {
                     $new_table_name = $table_name;
                 }
                 $restoring_table = $new_table_name;
                 echo '<br>';
                 if ($engine_change_message) {
                     echo $engine_change_message;
                 }
             } elseif ('' != $old_table_prefix && preg_match('/^\\s*insert into \\`?([^\\`]*)\\`?\\s+values/i', $sql_line, $matches)) {
                 $sql_type = 3;
                 if ($import_table_prefix != $old_table_prefix) {
                     $sql_line = $this->str_replace_once($old_table_prefix, $import_table_prefix, $sql_line);
                 }
             }
             if ($sql_type == 2 && $create_forbidden) {
                 echo sprintf(__('Cannot create new tables, so skipping this command (%s)', 'updraftplus'), htmlspecialchars("CREATE TABLE {$table_name}")) . "<br>";
                 $req = true;
             } else {
                 if ($sql_type == 1 && $drop_forbidden) {
                     $sql_line = "DELETE FROM " . $updraftplus->backquote($table_name);
                     echo sprintf(__('Cannot drop tables, so deleting instead (%s)', 'updraftplus'), $sql_line) . "<br>";
                 }
                 if ($use_wpdb) {
                     $req = $wpdb->query($sql_line);
                     if (!$req) {
                         $last_error = $wpdb->last_error;
                     }
                 } else {
                     $req = mysql_unbuffered_query($sql_line, $mysql_dbh);
                     if (!$req) {
                         $last_error = mysql_error($mysql_dbh);
                     }
                 }
                 $statements_run++;
             }
             if (!$req) {
                 $errors++;
                 echo sprintf(_x('An error (%s) occured:', 'The user is being told the number of times an error has happened, e.g. An error (27) occurred', 'updraftplus'), $errors) . " - " . htmlspecialchars($last_error) . " - " . __('the database query being run was:', 'updraftplus') . ' ' . htmlspecialchars($sql_line) . '<br>';
                 // First command is expected to be DROP TABLE
                 if (1 == $errors && 2 == $sql_type && 0 == $tables_created) {
                     return new WP_Error('initial_db_error', __('An error occured on the first CREATE TABLE command - aborting run', 'updraftplus'));
                 }
                 if ($errors > 49) {
                     return new WP_Error('too_many_db_errors', __('Too many database errors have occurred - aborting restoration (you will need to restore manually)', 'updraftplus'));
                 }
             } elseif ($sql_type == 2) {
                 $tables_created++;
             }
             if ($line % 50 == 0) {
                 if ($line % 250 == 0 || $line < 250) {
                     $time_taken = microtime(true) - $start_time;
                     echo sprintf(__('Database lines processed: %d in %.2f seconds', 'updraftplus'), $line, $time_taken) . "<br>";
                 }
             }
             # Reset
             $sql_line = '';
             $sql_type = -1;
         }
         if ($restoring_table) {
             $this->restored_table($restoring_table, $import_table_prefix, $old_table_prefix);
         }
         $time_taken = microtime(true) - $start_time;
         echo sprintf(__('Finished: lines processed: %d in %.2f seconds', 'updraftplus'), $line, $time_taken) . "<br>";
         gzclose($dbhandle);
         $wp_filesystem->delete($working_dir . '/backup.db.gz', false, true);
     } else {
         // Default action: used for plugins, themes and uploads (and wpcore, via a filter)
         $dirname = basename($info['path']);
         show_message($this->strings['moving_old']);
         $movedin = apply_filters('updraftplus_restore_movein_' . $type, $working_dir, $wp_dir, $wp_filesystem_dir);
         // A filter, to allow add-ons to perform the install of non-standard entities, or to indicate that it's not possible
         if (false === $movedin) {
             show_message($this->strings['not_possible']);
         } elseif ($movedin !== true) {
             if ($wp_filesystem->exists($wp_filesystem_dir . "-old")) {
                 // Is better to warn and delete the backup than abort mid-restore and leave inconsistent site
                 echo $wp_filesystem_dir . "-old: " . __('This directory already exists, and will be replaced', 'updraftplus') . '<br>';
                 # In theory, supply true as the 3rd parameter of true achieves this; in practice, not always so (leads to support requests)
                 $wp_filesystem->delete($wp_filesystem_dir . "-old", true);
             }
             if (!$wp_filesystem->move($wp_filesystem_dir, $wp_filesystem_dir . "-old", false)) {
                 return new WP_Error('old_move_failed', $this->strings['old_move_failed']);
             }
             // The backup may not actually have /$dirname, since that is info from the present site
             $dirlist = $wp_filesystem->dirlist($working_dir, true, true);
             if (is_array($dirlist)) {
                 $move_from = false;
                 foreach ($dirlist as $name => $struc) {
                     if (false === $move_from) {
                         if ($name == $dirname) {
                             $move_from = $working_dir . "/{$dirname}";
                         } elseif (preg_match('/^([^\\.].*)$/', $name, $fmatch)) {
                             $first_entry = $working_dir . "/" . $fmatch[1];
                         }
                     }
                 }
                 if ($move_from === false && isset($first_entry)) {
                     echo sprintf(__('Using directory from backup: %s', 'updraftplus'), basename($first_entry)) . '<br>';
                     $move_from = $first_entry;
                 }
             } else {
                 # That shouldn't happen. Fall back to default
                 $move_from = $working_dir . "/{$dirname}";
             }
             show_message($this->strings['moving_backup']);
             if (isset($move_from) && false === $move_from || !$wp_filesystem->move($move_from, $wp_filesystem_dir, true)) {
                 return new WP_Error('new_move_failed', $this->strings['new_move_failed']);
             }
         }
     }
     // Non-recursive, so the directory needs to be empty
     show_message($this->strings['cleaning_up']);
     if (!$wp_filesystem->delete($working_dir)) {
         echo sprintf(__('Error: %s', 'updraftplus'), $this->strings['delete_failed'] . ' (' . $working_dir . ')') . "<br>";
         # List contents
         // No need to make this a restoration-aborting error condition - it's not
         #return new WP_Error('delete_failed', $this->strings['delete_failed'].' ('.$working_dir.')');
         $dirlist = $wp_filesystem->dirlist($working_dir, true, true);
         if (is_array($dirlist)) {
             echo __('Files found:', 'updraftplus') . '<br><ul style="list-style: disc inside;">';
             foreach ($dirlist as $name => $struc) {
                 echo "<li>" . htmlspecialchars($name) . "</li>";
             }
             echo '</ul>';
         } else {
             echo __('Unable to enumerate files in that directory.', 'updraftplus') . '<br>';
         }
     }
     switch ($type) {
         case 'wpcore':
             @$wp_filesystem->chmod($wp_filesystem_dir, FS_CHMOD_DIR);
             // In case we restored a .htaccess which is incorrect for the local setup
             $this->flush_rewrite_rules();
             break;
         case 'uploads':
             @$wp_filesystem->chmod($wp_filesystem_dir, 0775, true);
             break;
         case 'db':
             do_action('updraftplus_restored_db', array('expected_oldsiteurl' => $old_siteurl), $import_table_prefix);
             $this->flush_rewrite_rules();
             break;
         default:
             @$wp_filesystem->chmod($wp_filesystem_dir, FS_CHMOD_DIR);
     }
     return true;
 }