/httpdocs/wp-content/plugins/worker/backup.class.php
PHP | 3260 lines | 2217 code | 366 blank | 677 comment | 518 complexity | e08f2907f3248351fd2aaa3a810e8175 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-3.0, LGPL-2.1, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- <?php
- /*************************************************************
- *
- * backup.class.php
- *
- * Manage Backups
- *
- *
- * Copyright (c) 2011 Prelovac Media
- * www.prelovac.com
- **************************************************************/
- if(basename($_SERVER['SCRIPT_FILENAME']) == "backup.class.php"):
- echo "Sorry but you cannot browse this file directly!";
- exit;
- endif;
- define('MWP_BACKUP_DIR', WP_CONTENT_DIR . '/managewp/backups');
- define('MWP_DB_DIR', MWP_BACKUP_DIR . '/mwp_db');
- $zip_errors = array(
- 'No error',
- 'No error',
- 'Unexpected end of zip file',
- 'A generic error in the zipfile format was detected.',
- 'zip was unable to allocate itself memory',
- 'A severe error in the zipfile format was detected',
- 'Entry too large to be split with zipsplit',
- 'Invalid comment format',
- 'zip -T failed or out of memory',
- 'The user aborted zip prematurely',
- 'zip encountered an error while using a temp file',
- 'Read or seek error',
- 'zip has nothing to do',
- 'Missing or empty zip file',
- 'Error writing to a file',
- 'zip was unable to create a file to write to',
- 'bad command line parameters',
- 'no error',
- 'zip could not open a specified file to read'
- );
- $unzip_errors = array(
- 'No error',
- 'One or more warning errors were encountered, but processing completed successfully anyway',
- 'A generic error in the zipfile format was detected',
- 'A severe error in the zipfile format was detected.',
- 'unzip was unable to allocate itself memory.',
- 'unzip was unable to allocate memory, or encountered an encryption error',
- 'unzip was unable to allocate memory during decompression to disk',
- 'unzip was unable allocate memory during in-memory decompression',
- 'unused',
- 'The specified zipfiles were not found',
- 'Bad command line parameters',
- 'No matching files were found',
- 50 => 'The disk is (or was) full during extraction',
- 51 => 'The end of the ZIP archive was encountered prematurely.',
- 80 => 'The user aborted unzip prematurely.',
- 81 => 'Testing or extraction of one or more files failed due to unsupported compression methods or unsupported decryption.',
- 82 => 'No files were found due to bad decryption password(s)'
- );
- /**
- * The main class for processing database and full backups on ManageWP worker.
- *
- * @copyright 2011-2012 Prelovac Media
- * @version 3.9.24
- * @package ManageWP
- * @subpackage backup
- *
- */
- class MMB_Backup extends MMB_Core {
- var $site_name;
- var $statuses;
- var $tasks;
- var $s3;
- var $ftp;
- var $dropbox;
- var $google_drive;
-
- /**
- * Initializes site_name, statuses, and tasks attributes.
- *
- * @return void
- */
- function __construct() {
- parent::__construct();
- $this->site_name = str_replace(array(
- "_",
- "/",
- "~"
- ), array(
- "",
- "-",
- "-"
- ), rtrim($this->remove_http(get_bloginfo('url')), "/"));
- $this->statuses = array(
- 'db_dump' => 1,
- 'db_zip' => 2,
- 'files_zip' => 3,
- 's3' => 4,
- 'dropbox' => 5,
- 'ftp' => 6,
- 'email' => 7,
- 'google_drive' => 8,
- 'finished' => 100
- );
- $this->tasks = get_option('mwp_backup_tasks');
- }
-
- /**
- * Tries to increase memory limit to 384M and execution time to 600s.
- *
- * @return array an array with two keys for execution time and memory limit (0 - if not changed, 1 - if succesfully)
- */
- function set_memory() {
- $changed = array('execution_time' => 0, 'memory_limit' => 0);
-
- $memory_limit = trim(ini_get('memory_limit'));
- $last = strtolower(substr($memory_limit, -1));
-
- if($last == 'g')
- $memory_limit = ((int) $memory_limit)*1024;
- else if($last == 'm')
- $memory_limit = (int) $memory_limit;
- if($last == 'k')
- $memory_limit = ((int) $memory_limit)/1024;
-
- if ( $memory_limit < 384 ) {
- @ini_set('memory_limit', '384M');
- $changed['memory_limit'] = 1;
- }
-
- if ( (int) @ini_get('max_execution_time') < 600 ) {
- @set_time_limit(600); //ten minutes
- $changed['execution_time'] = 1;
- }
-
- return $changed;
- }
-
- /**
- * Returns backup settings from local database for all tasks
- *
- * @return mixed|boolean
- */
- function get_backup_settings() {
- $backup_settings = get_option('mwp_backup_tasks');
-
- if (!empty($backup_settings))
- return $backup_settings;
- else
- return false;
- }
-
- /**
- * Sets backup task defined from master, if task name is "Backup Now" this function fires processing backup.
- *
- * @param mixed $params parameters sent from master
- * @return mixed|boolean $this->tasks variable if success, array with error message if error has ocurred, false if $params are empty
- */
- function set_backup_task($params) {
- //$params => [$task_name, $args, $error]
- if (!empty($params)) {
-
- //Make sure backup cron job is set
- if (!wp_next_scheduled('mwp_backup_tasks')) {
- wp_schedule_event( time(), 'tenminutes', 'mwp_backup_tasks' );
- }
-
- extract($params);
-
- //$before = $this->get_backup_settings();
- $before = $this->tasks;
- if (!$before || empty($before))
- $before = array();
-
- if (isset($args['remove'])) {
- unset($before[$task_name]);
- $return = array(
- 'removed' => true
- );
- } else {
- if (isset($params['account_info']) && is_array($params['account_info'])) { //only if sends from master first time(secure data)
- $args['account_info'] = $account_info;
- }
-
- $before[$task_name]['task_args'] = $args;
- if (strlen($args['schedule']))
- $before[$task_name]['task_args']['next'] = $this->schedule_next($args['type'], $args['schedule']);
-
- $return = $before[$task_name];
- }
-
- //Update with error
- if (isset($error)) {
- if (is_array($error)) {
- $before[$task_name]['task_results'][count($before[$task_name]['task_results']) - 1]['error'] = $error['error'];
- } else {
- $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['error'] = $error;
- }
- }
-
- if (isset($time) && $time) { //set next result time before backup
- if (is_array($before[$task_name]['task_results'])) {
- $before[$task_name]['task_results'] = array_values($before[$task_name]['task_results']);
- }
- $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['time'] = $time;
- }
-
- $this->update_tasks($before);
- //update_option('mwp_backup_tasks', $before);
-
- if ($task_name == 'Backup Now') {
- $result = $this->backup($args, $task_name);
- $backup_settings = $this->tasks;
-
- if (is_array($result) && array_key_exists('error', $result)) {
- $return = $result;
- } else {
- $return = $backup_settings[$task_name];
- }
- }
- return $return;
- }
-
- return false;
- }
-
- /**
- * Checks if scheduled task is ready for execution,
- * if it is ready master sends google_drive_token, failed_emails, success_emails if are needed.
- *
- * @return void
- */
- function check_backup_tasks() {
- $this->check_cron_remove();
-
- $failed_emails = array();
- $settings = $this->tasks;
- if (is_array($settings) && !empty($settings)) {
- foreach ($settings as $task_name => $setting) {
- if ($setting['task_args']['next'] && $setting['task_args']['next'] < time()) {
- //if ($setting['task_args']['next'] && $_GET['force_backup']) {
- if ($setting['task_args']['url'] && $setting['task_args']['task_id'] && $setting['task_args']['site_key']) {
- //Check orphan task
- $check_data = array(
- 'task_name' => $task_name,
- 'task_id' => $setting['task_args']['task_id'],
- 'site_key' => $setting['task_args']['site_key'],
- 'worker_version' => MMB_WORKER_VERSION
- );
-
- if (isset($setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'])) {
- $check_data['mwp_google_drive_refresh_token'] = true;
- }
-
- $check = $this->validate_task($check_data, $setting['task_args']['url']);
- $worker_upto_3_9_22 = (MMB_WORKER_VERSION <= '3.9.22'); // worker version is less or equals to 3.9.22
-
- if ($worker_upto_3_9_22) {
- $potential_token = substr($check, 8);
- if (substr($check, 0, 8) == 'token - ' && $potential_token != 'not found') {
- $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
- $settings[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
- $setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
- }
- } else {
- $potential_token = isset($check['google_drive_token']) ? $check['google_drive_token'] : false;
- if ($potential_token) {
- $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
- $settings[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
- $setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
- }
- }
-
- }
-
- $update = array(
- 'task_name' => $task_name,
- 'args' => $settings[$task_name]['task_args']
- );
-
- if($check != 'paused'){
- $update['time'] = time();
- }
-
- //Update task with next schedule
- $this->set_backup_task($update);
-
- if($check == 'paused'){
- continue;
- }
-
- $result = $this->backup($setting['task_args'], $task_name);
- $error = '';
-
- if (is_array($result) && array_key_exists('error', $result)) {
- $error = $result;
- $this->set_backup_task(array(
- 'task_name' => $task_name,
- 'args' => $settings[$task_name]['task_args'],
- 'error' => $error
- ));
- } else {
- //$setting = $this->tasks[$task_name];
- if (@count($setting['task_args']['account_info'])) {
- /*$last_result = $setting['task_results'][count($setting['task_results']) - 1];
- $backup_file = $last_result['server']['file_path'];
- $del_host_file = $setting['task_args']['del_host_file'];*/
- wp_schedule_single_event(time(), 'mmb_scheduled_remote_upload', array('args' => array('task_name' => $task_name)));
- //spawn_cron(time() + 150);
- //wp_remote_post(site_url('index.php'), array( 'timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters( 'https_local_ssl_verify', true ) ));
- //update_option('_transient_doing_cron', 0);
- /*$nonce = substr(wp_hash(wp_nonce_tick() . 'mmb-backup-nonce' . 0, 'nonce'), -12, 10);
- $cron_url = site_url('index.php');
- $args = array(
- 'body' => array(
- 'backup_cron_action' => 'mmb_remote_upload',
- 'args' => json_encode(array('task_name' => $task_name, 'backup_file' => $backup_file, 'del_host_file' => $del_host_file)),
- 'mmb_backup_nonce' => $nonce,
- ),
- 'timeout' => 0.01,
- 'blocking' => false,
- 'sslverify' => apply_filters('https_local_ssl_verify', true)
- );
- wp_remote_post($cron_url, $args);*/
- }
- }
-
- break; //Only one backup per cron
- }
- }
- }
-
- }
-
- /**
- * Runs backup task invoked from ManageWP master.
- *
- * @param string $task_name name of backup task
- * @param string|bool[optional] $google_drive_token false if backup destination is not Google Drive, json of Google Drive token if it is remote destination (default: false)
- * @return mixed array with backup statistics if successful, array with error message if not
- */
- function task_now($task_name, $google_drive_token = false) {
- if ($google_drive_token) {
- $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
- }
-
- $settings = $this->tasks;
- if(!array_key_exists($task_name,$settings)){
- return array('error' => $task_name." does not exist.");
- } else {
- $setting = $settings[$task_name];
- }
-
- $this->set_backup_task(array(
- 'task_name' => $task_name,
- 'args' => $settings[$task_name]['task_args'],
- 'time' => time()
- ));
-
- //Run backup
- $result = $this->backup($setting['task_args'], $task_name);
-
- //Check for error
- if (is_array($result) && array_key_exists('error', $result)) {
- $this->set_backup_task(array(
- 'task_name' => $task_name,
- 'args' => $settings[$task_name]['task_args'],
- 'error' => $result
- ));
- return $result;
- } else {
- return $this->get_backup_stats();
- }
- }
-
- /**
- * Backup a full wordpress instance, including a database dump, which is placed in mwp_db dir in root folder.
- * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
- *
- * @param string $args arguments passed from master
- * [type] -> db, full,
- * [what] -> daily, weekly, monthly,
- * [account_info] -> remote destinations ftp, amazons3, dropbox, google_drive, email with their parameters
- * [include] -> array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
- * [exclude] -> array of files of folders to exclude, relative to site's root
- * @param bool|string[optional] $task_name the name of backup task, which backup is done (default: false)
- * @return bool|array false if $args are missing, array with error if error has occured, ture if is successful
- */
- function backup($args, $task_name = false) {
- if (!$args || empty($args))
- return false;
-
- extract($args); //extract settings
-
- if (!empty($account_info)) {
- $found = false;
- $destinations = array('mwp_ftp', 'mwp_amazon_s3', 'mwp_dropbox', 'mwp_google_drive', 'mwp_email');
- foreach($destinations as $dest) {
- $found = $found || (isset($account_info[$dest]));
- }
- if (!$found) {
- $error_message = 'Remote destination is not supported, please update your client plugin.';
- return array(
- 'error' => $error_message
- );
- }
- }
-
- //Try increase memory limit and execution time
- $this->set_memory();
-
- //Remove old backup(s)
- $removed = $this->remove_old_backups($task_name);
- if (is_array($removed) && isset($removed['error'])) {
- $error_message = $removed['error'];
- return $removed;
- }
-
- $new_file_path = MWP_BACKUP_DIR;
-
- if (!file_exists($new_file_path)) {
- if (!mkdir($new_file_path, 0755, true))
- $error_message = 'Permission denied, make sure you have write permission to wp-content folder.';
- return array(
- 'error' => $error_message
- );
- }
-
- @file_put_contents($new_file_path . '/index.php', ''); //safe
-
- //Prepare .zip file name
- $hash = md5(time());
- $label = $type ? $type : 'manual';
- $backup_file = $new_file_path . '/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
- $backup_url = WP_CONTENT_URL . '/managewp/backups/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
-
- $begin_compress = microtime(true);
-
- //Optimize tables?
- if (isset($optimize_tables) && !empty($optimize_tables)) {
- $this->optimize_tables();
- }
-
- //What to backup - db or full?
- if (trim($what) == 'db') {
- $db_backup = $this->backup_db_compress($task_name, $backup_file);
- if (is_array($db_backup) && array_key_exists('error', $db_backup)) {
- $error_message = $db_backup['error'];
- return array(
- 'error' => $error_message
- );
- }
- } elseif (trim($what) == 'full') {
- if (!$exclude) {
- $exclude = array();
- }
- if (!$include) {
- $include = array();
- }
- $content_backup = $this->backup_full($task_name, $backup_file, $exclude, $include);
- if (is_array($content_backup) && array_key_exists('error', $content_backup)) {
- $error_message = $content_backup['error'];
- return array(
- 'error' => $error_message
- );
- }
- }
-
- $end_compress = microtime(true);
-
- //Update backup info
- if ($task_name) {
- //backup task (scheduled)
- $backup_settings = $this->tasks;
- $paths = array();
- $size = ceil(filesize($backup_file) / 1024);
- $duration = round($end_compress - $begin_compress, 2);
-
- if ($size > 1000) {
- $paths['size'] = ceil($size / 1024) . "mb";
- } else {
- $paths['size'] = $size . 'kb';
- }
-
- $paths['duration'] = $duration . 's';
-
- if ($task_name != 'Backup Now') {
- $paths['server'] = array(
- 'file_path' => $backup_file,
- 'file_url' => $backup_url
- );
- } else {
- $paths['server'] = array(
- 'file_path' => $backup_file,
- 'file_url' => $backup_url
- );
- }
-
- if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_ftp'])) {
- $paths['ftp'] = basename($backup_url);
- }
-
- if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_amazon_s3'])) {
- $paths['amazons3'] = basename($backup_url);
- }
-
- if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_dropbox'])) {
- $paths['dropbox'] = basename($backup_url);
- }
-
- if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_email'])) {
- $paths['email'] = basename($backup_url);
- }
-
- if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_google_drive'])) {
- $paths['google_drive'] = basename($backup_url);
- }
-
- $temp = $backup_settings[$task_name]['task_results'];
- $temp = array_values($temp);
- $paths['time'] = time();
-
- if ($task_name != 'Backup Now') {
- $paths['status'] = $temp[count($temp) - 1]['status'];
- $temp[count($temp) - 1] = $paths;
-
- } else {
- $temp[count($temp)] = $paths;
- }
-
- $backup_settings[$task_name]['task_results'] = $temp;
- $this->update_tasks($backup_settings);
- //update_option('mwp_backup_tasks', $backup_settings);
- }
-
- // If there are not remote destination, set up task status to finished
- if (@count($backup_settings[$task_name]['task_args']['account_info']) == 0) {
- $this->update_status($task_name, $this->statuses['finished'], true);
- }
-
- return true;
- }
-
- /**
- * Backup a full wordpress instance, including a database dump, which is placed in mwp_db dir in root folder.
- * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
- *
- * @param string $task_name the name of backup task, which backup is done
- * @param string $backup_file relative path to file which backup is stored
- * @param array[optional] $exclude the list of files and folders, which are excluded from backup (default: array())
- * @param array[optional] $include the list of folders in wordpress root which are included to backup, expect wp-admin, wp-content, wp-includes, which are default (default: array())
- * @return bool|array true if backup is successful, or an array with error message if is failed
- */
- function backup_full($task_name, $backup_file, $exclude = array(), $include = array()) {
- $this->update_status($task_name, $this->statuses['db_dump']);
- $db_result = $this->backup_db();
-
- if ($db_result == false) {
- return array(
- 'error' => 'Failed to backup database.'
- );
- } else if (is_array($db_result) && isset($db_result['error'])) {
- return array(
- 'error' => $db_result['error']
- );
- }
-
- $this->update_status($task_name, $this->statuses['db_dump'], true);
- $this->update_status($task_name, $this->statuses['db_zip']);
-
- @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
- $zip_db_result = $this->zip_backup_db($task_name, $backup_file);
-
- if (!$zip_db_result) {
- $zip_archive_db_result = false;
- if (class_exists("ZipArchive")) {
- $this->_log("DB zip, fallback to ZipArchive");
- $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
- }
-
- if (!$zip_archive_db_result) {
- $this->_log("DB zip, fallback to PclZip");
- $pclzip_db_result = $this->pclzip_backup_db($task_name, $backup_file);
- if (!$pclzip_db_result) {
- @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
- @unlink($db_result);
- @rmdir(MWP_DB_DIR);
-
- return array(
- 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
- );
- }
- }
- }
-
- @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
- @unlink($db_result);
- @rmdir(MWP_DB_DIR);
-
- $remove = array(
- trim(basename(WP_CONTENT_DIR)) . "/managewp/backups",
- trim(basename(WP_CONTENT_DIR)) . "/" . md5('mmb-worker') . "/mwp_backups"
- );
- $exclude = array_merge($exclude, $remove);
-
- $this->update_status($task_name, $this->statuses['db_zip'], true);
- $this->update_status($task_name, $this->statuses['files_zip']);
-
- $zip_result = $this->zip_backup($task_name, $backup_file, $exclude, $include);
-
- if (isset($zip_result['error'])) {
- return $zip_result;
- }
-
- if (!$zip_result) {
- $zip_archive_result = false;
- if (class_exists("ZipArchive")) {
- $this->_log("Files zip fallback to ZipArchive");
- $zip_archive_result = $this->zip_archive_backup($task_name, $backup_file, $exclude, $include);
- }
-
- if (!$zip_archive_result) {
- $this->_log("Files zip fallback to PclZip");
- $pclzip_result = $this->pclzip_backup($task_name, $backup_file, $exclude, $include);
- if (!$pclzip_result) {
- @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
- @unlink($db_result);
- @rmdir(MWP_DB_DIR);
-
- if (!$pclzip_result) {
- @unlink($backup_file);
- return array(
- 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
- );
- }
- }
- }
- }
-
- //Reconnect
- $this->wpdb_reconnect();
-
- $this->update_status($task_name, $this->statuses['files_zip'], true);
- return true;
- }
-
- /**
- * Zipping database dump and index.php in folder mwp_db by system zip command, requires zip installed on OS.
- *
- * @param string $task_name the name of backup task
- * @param string $backup_file absolute path to zip file
- * @return bool is compress successful or not
- */
- function zip_backup_db($task_name, $backup_file) {
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
- $comp_level = $disable_comp ? '-0' : '-1';
- $zip = $this->get_zip();
- //Add database file
- chdir(MWP_BACKUP_DIR);
- $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
-
- ob_start();
- $this->_log("Executing $command");
- $result = $this->mmb_exec($command);
- ob_get_clean();
-
- return $result;
- }
-
- /**
- * Zipping database dump and index.php in folder mwp_db by ZipArchive class, requires php zip extension.
- *
- * @param string $task_name the name of backup task
- * @param string $db_result relative path to database dump file
- * @param string $backup_file absolute path to zip file
- * @return bool is compress successful or not
- */
- function zip_archive_backup_db($task_name, $db_result, $backup_file) {
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
- if (!$disable_comp) {
- $this->_log("Compression is not supported by ZipArchive");
- }
- $zip = new ZipArchive();
- $result = $zip->open($backup_file, ZIPARCHIVE::OVERWRITE); // Tries to open $backup_file for acrhiving
- if ($result === true) {
- $result = $result && $zip->addFile(MWP_BACKUP_DIR.'/mwp_db/index.php', "mwp_db/index.php"); // Tries to add mwp_db/index.php to $backup_file
- $result = $result && $zip->addFile($db_result, "mwp_db/" . basename($db_result)); // Tries to add db dump form mwp_db dir to $backup_file
- $result = $result && $zip->close(); // Tries to close $backup_file
- } else {
- $result = false;
- }
-
- return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
- }
-
- /**
- * Zipping database dump and index.php in folder mwp_db by PclZip library.
- *
- * @param string $task_name the name of backup task
- * @param string $backup_file absolute path to zip file
- * @return bool is compress successful or not
- */
- function pclzip_backup_db($task_name, $backup_file) {
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
- define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
- require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
- $zip = new PclZip($backup_file);
-
- if ($disable_comp) {
- $result = $zip->add(MWP_BACKUP_DIR, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION) !== 0;
- } else {
- $result = $zip->add(MWP_BACKUP_DIR, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR) !== 0;
- }
-
- return $result;
- }
-
- /**
- * Zipping whole site root folder and append to backup file with database dump
- * by system zip command, requires zip installed on OS.
- *
- * @param string $task_name the name of backup task
- * @param string $backup_file absolute path to zip file
- * @param array $exclude array of files of folders to exclude, relative to site's root
- * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
- * @return array|bool true if successful or an array with error message if not
- */
- function zip_backup($task_name, $backup_file, $exclude, $include) {
- global $zip_errors;
- $sys = substr(PHP_OS, 0, 3);
-
- //Exclude paths
- $exclude_data = "-x";
-
- $exclude_file_data = '';
-
- if (!empty($exclude)) {
- foreach ($exclude as $data) {
- if (is_dir(ABSPATH . $data)) {
- if ($sys == 'WIN')
- $exclude_data .= " $data/*.*";
- else
- $exclude_data .= " '$data/*'";
- } else {
- if ($sys == 'WIN'){
- if(file_exists(ABSPATH . $data)){
- $exclude_data .= " $data";
- $exclude_file_data .= " $data";
- }
- } else {
- if(file_exists(ABSPATH . $data)){
- $exclude_data .= " '$data'";
- $exclude_file_data .= " '$data'";
- }
- }
- }
- }
- }
-
- if($exclude_file_data){
- $exclude_file_data = "-x".$exclude_file_data;
- }
-
- //Include paths by default
- $add = array(
- trim(WPINC),
- trim(basename(WP_CONTENT_DIR)),
- "wp-admin"
- );
-
- $include_data = ". -i";
- foreach ($add as $data) {
- if ($sys == 'WIN')
- $include_data .= " $data/*.*";
- else
- $include_data .= " '$data/*'";
- }
-
- //Additional includes?
- if (!empty($include)) {
- foreach ($include as $data) {
- if ($data) {
- if ($sys == 'WIN')
- $include_data .= " $data/*.*";
- else
- $include_data .= " '$data/*'";
- }
- }
- }
-
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
- $comp_level = $disable_comp ? '-0' : '-1';
- $zip = $this->get_zip();
- chdir(ABSPATH);
- ob_start();
- $command = "$zip -q -j $comp_level $backup_file .* * $exclude_file_data";
- $this->_log("Executing $command");
- $result_f = $this->mmb_exec($command, false, true);
- if (!$result_f || $result_f == 18) { // disregard permissions error, file can't be accessed
- $command = "$zip -q -r $comp_level $backup_file $include_data $exclude_data";
- $result_d = $this->mmb_exec($command, false, true);
- $this->_log("Executing $command");
- if ($result_d && $result_d != 18) {
- @unlink($backup_file);
- if ($result_d > 0 && $result_d < 18)
- return array(
- 'error' => 'Failed to archive files (' . $zip_errors[$result_d] . ') .'
- );
- else {
- if ($result_d === -1) return false;
- return array(
- 'error' => 'Failed to archive files.'
- );
- }
- }
- } else {
- return false;
- }
-
- ob_get_clean();
-
- return true;
- }
-
- /**
- * Zipping whole site root folder and append to backup file with database dump
- * by ZipArchive class, requires php zip extension.
- *
- * @param string $task_name the name of backup task
- * @param string $backup_file absolute path to zip file
- * @param array $exclude array of files of folders to exclude, relative to site's root
- * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
- * @return array|bool true if successful or an array with error message if not
- */
- function zip_archive_backup($task_name, $backup_file, $exclude, $include, $overwrite = false) {
- $filelist = $this->get_backup_files($exclude, $include);
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
- if (!$disable_comp) {
- $this->_log("Compression is not supported by ZipArchive");
- }
-
- $zip = new ZipArchive();
- if ($overwrite) {
- $result = $zip->open($backup_file, ZipArchive::OVERWRITE); // Tries to open $backup_file for acrhiving
- } else {
- $result = $zip->open($backup_file); // Tries to open $backup_file for acrhiving
- }
- if ($result === true) {
- foreach ($filelist as $file) {
- $result = $result && $zip->addFile($file, sprintf("%s", str_replace(ABSPATH, '', $file))); // Tries to add a new file to $backup_file
- }
- $result = $result && $zip->close(); // Tries to close $backup_file
- } else {
- $result = false;
- }
-
- return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
- }
-
- /**
- * Zipping whole site root folder and append to backup file with database dump
- * by PclZip library.
- *
- * @param string $task_name the name of backup task
- * @param string $backup_file absolute path to zip file
- * @param array $exclude array of files of folders to exclude, relative to site's root
- * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
- * @return array|bool true if successful or an array with error message if not
- */
- function pclzip_backup($task_name, $backup_file, $exclude, $include) {
- define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
- require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
- $zip = new PclZip($backup_file);
- $add = array(
- trim(WPINC),
- trim(basename(WP_CONTENT_DIR)),
- "wp-admin"
- );
-
- $include_data = array();
- if (!empty($include)) {
- foreach ($include as $data) {
- if ($data && file_exists(ABSPATH . $data))
- $include_data[] = ABSPATH . $data . '/';
- }
- }
- $include_data = array_merge($add, $include_data);
-
- if ($handle = opendir(ABSPATH)) {
- while (false !== ($file = readdir($handle))) {
- if ($file != "." && $file != ".." && !is_dir($file) && file_exists(ABSPATH . $file)) {
- $include_data[] = ABSPATH . $file;
- }
- }
- closedir($handle);
- }
-
- $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
-
- if ($disable_comp) {
- $result = $zip->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_NO_COMPRESSION) !== 0;
- } else {
- $result = $zip->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH) !== 0;
- }
-
- $exclude_data = array();
- if (!empty($exclude)) {
- foreach ($exclude as $data) {
- if (file_exists(ABSPATH . $data)) {
- if (is_dir(ABSPATH . $data))
- $exclude_data[] = $data . '/';
- else
- $exclude_data[] = $data;
- }
- }
- }
- $result = $result && $zip->delete(PCLZIP_OPT_BY_NAME, $exclude_data);
-
- return $result;
- }
-
- /**
- * Gets an array of relative paths of all files in site root recursively.
- * By default, there are all files from root folder, all files from folders wp-admin, wp-content, wp-includes recursively.
- * Parameter $include adds other folders from site root, and excludes any file or folder by relative path to site's root.
- *
- * @param array $exclude array of files of folders to exclude, relative to site's root
- * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
- * @return array array with all files in site root dir
- */
- function get_backup_files($exclude, $include) {
- $add = array(
- trim(WPINC),
- trim(basename(WP_CONTENT_DIR)),
- "wp-admin"
- );
-
- $include = array_merge($add, $include);
-
- $filelist = array();
- if ($handle = opendir(ABSPATH)) {
- while (false !== ($file = readdir($handle))) {
- if (is_dir($file) && file_exists(ABSPATH . $file) && !(in_array($file, $include))) {
- $exclude[] = $file;
- }
- }
- closedir($handle);
- }
-
- $filelist = get_all_files_from_dir(ABSPATH, $exclude);
-
- return $filelist;
- }
-
- /**
- * Backup a database dump of WordPress site.
- * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
- *
- * @param string $task_name the name of backup task, which backup is done
- * @param string $backup_file relative path to file which backup is stored
- * @return bool|array true if backup is successful, or an array with error message if is failed
- */
- function backup_db_compress($task_name, $backup_file) {
- $this->update_status($task_name, $this->statuses['db_dump']);
- $db_result = $this->backup_db();
-
- if ($db_result == false) {
- return array(
- 'error' => 'Failed to backup database.'
- );
- } else if (is_array($db_result) && isset($db_result['error'])) {
- return array(
- 'error' => $db_result['error']
- );
- }
-
- $this->update_status($task_name, $this->statuses['db_dump'], true);
- $this->update_status($task_name, $this->statuses['db_zip']);
- @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
- $zip_db_result = $this->zip_backup_db($task_name, $backup_file);
-
- if (!$zip_db_result) {
- $zip_archive_db_result = false;
- if (class_exists("ZipArchive")) {
- $this->_log("DB zip, fallback to ZipArchive");
- $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
- }
-
- if (!$zip_archive_db_result) {
- $this->_log("DB zip, fallback to PclZip");
- $pclzip_db_result = $this->pclzip_backup_db($task_name, $backup_file);
- if (!$pclzip_db_result) {
- @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
- @unlink($db_result);
- @rmdir(MWP_DB_DIR);
-
- return array(
- 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
- );
- }
- }
- }
-
- @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
- @unlink($db_result);
- @rmdir(MWP_DB_DIR);
-
- $this->update_status($task_name, $this->statuses['db_zip'], true);
-
- return true;
- }
-
- /**
- * Creates database dump and places it in mwp_db folder in site's root.
- * This function dispatches if OS mysql command does not work calls a php alternative.
- *
- * @return string|array path to dump file if successful, or an array with error message if is failed
- */
- function backup_db() {
- $db_folder = MWP_DB_DIR . '/';
- if (!file_exists($db_folder)) {
- if (!mkdir($db_folder, 0755, true))
- return array(
- 'error' => 'Error creating database backup folder (' . $db_folder . '). Make sure you have corrrect write permissions.'
- );
- }
-
- $file = $db_folder . DB_NAME . '.sql';
- $result = $this->backup_db_dump($file); // try mysqldump always then fallback to php dump
- return $result;
- }
-
- /**
- * Creates database dump by system mysql command.
- *
- * @param string $file absolute path to file in which dump should be placed
- * @return string|array path to dump file if successful, or an array with error message if is failed
- */
- function backup_db_dump($file) {
- global $wpdb;
- $paths = $this->check_mysql_paths();
- $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
- $command = $brace . $paths['mysqldump'] . $brace . ' --force --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" --add-drop-table --skip-lock-tables "' . DB_NAME . '" > ' . $brace . $file . $brace;
- ob_start();
- $result = $this->mmb_exec($command);
- ob_get_clean();
-
- if (!$result) { // Fallback to php
- $this->_log("DB dump fallback to php");
- $result = $this->backup_db_php($file);
- return $result;
- }
-
- if (filesize($file) == 0 || !is_file($file) || !$result) {
- @unlink($file);
- return false;
- } else {
- return $file;
- }
- }
-
- /**
- * Creates database dump by php functions.
- *
- * @param string $file absolute path to file in which dump should be placed
- * @return string|array path to dump file if successful, or an array with error message if is failed
- */
- function backup_db_php($file) {
- global $wpdb;
- $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
- foreach ($tables as $table) {
- //drop existing table
- $dump_data = "DROP TABLE IF EXISTS $table[0];";
- file_put_contents($file, $dump_data, FILE_APPEND);
- //create table
- $create_table = $wpdb->get_row("SHOW CREATE TABLE $table[0]", ARRAY_N);
- $dump_data = "\n\n" . $create_table[1] . ";\n\n";
- file_put_contents($file, $dump_data, FILE_APPEND);
-
- $count = $wpdb->get_var("SELECT count(*) FROM $table[0]");
- if ($count > 100)
- $count = ceil($count / 100);
- else if ($count > 0)
- $count = 1;
-
- for ($i = 0; $i < $count; $i++) {
- $low_limit = $i * 100;
- $qry = "SELECT * FROM $table[0] LIMIT $low_limit, 100";
- $rows = $wpdb->get_results($qry, ARRAY_A);
- if (is_array($rows)) {
- foreach ($rows as $row) {
- //insert single row
- $dump_data = "INSERT INTO $table[0] VALUES(";
- $num_values = count($row);
- $j = 1;
- foreach ($row as $value) {
- $value = addslashes($value);
- $value = preg_replace("/\n/Ui", "\\n", $value);
- $num_values == $j ? $dump_data .= "'" . $value . "'" : $dump_data .= "'" . $value . "', ";
- $j++;
- unset($value);
- }
- $dump_data .= ");\n";
- file_put_contents($file, $dump_data, FILE_APPEND);
- }
- }
- }
- $dump_data = "\n\n\n";
- file_put_contents($file, $dump_data, FILE_APPEND);
-
- unset($rows);
- unset($dump_data);
- }
-
- if (filesize($file) == 0 || !is_file($file)) {
- @unlink($file);
- return array(
- 'error' => 'Database backup failed. Try to enable MySQL dump on your server.'
- );
- }
-
- return $file;
- }
-
- /**
- * Restores full WordPress site or database only form backup zip file.
- *
- * @param array array of arguments passed to backup restore
- * [task_name] -> name of backup task
- * [result_id] -> id of baskup task result, which should be restored
- * [google_drive_token] -> json of Google Drive token, if it is remote destination
- * @return bool|array true if successful, or an array with error message if is failed
- */
- function restore($args) {
- global $wpdb;
- if (empty($args)) {
- return false;
- }
-
- extract($args);
- if (isset($google_drive_token)) {
- $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
- }
- $this->set_memory();
-
- $unlink_file = true; //Delete file after restore
-
- //Detect source
- if ($backup_url) {
- //This is for clone (overwrite)
- include_once ABSPATH . 'wp-admin/includes/file.php';
- $backup_file = download_url($backup_url);
- if (is_wp_error($backup_file)) {
- return array(
- 'error' => 'Unable to download backup file ('.$backup_file->get_error_message().')'
- );
- }
- $what = 'full';
- } else {
- $tasks = $this->tasks;
- $task = $tasks[$task_name];
- if (isset($task['task_results'][$result_id]['server'])) {
- $backup_file = $task['task_results'][$result_id]['server']['file_path'];
- $unlink_file = false; //Don't delete file if stored on server
- } elseif (isset($task['task_results'][$result_id]['ftp'])) {
- $ftp_file = $task['task_results'][$result_id]['ftp'];
- $args = $task['task_args']['account_info']['mwp_ftp'];
- $args['backup_file'] = $ftp_file;
- $backup_file = $this->get_ftp_backup($args);
-
- if ($backup_file == false) {
- return array(
- 'error' => 'Failed to download file from FTP.'
- );
- }
- } elseif (isset($task['task_results'][$result_id]['amazons3'])) {
- $amazons3_file = $task['task_results'][$result_id]['amazons3'];
- $args = $task['task_args']['account_info']['mwp_amazon_s3'];
- $args['backup_file'] = $amazons3_file;
- $backup_file = $this->get_amazons3_backup($args);
-
- if ($backup_file == false) {
- return array(
- 'error' => 'Failed to download file from Amazon S3.'
- );
- }
- } elseif(isset($task['task_results'][$result_id]['dropbox'])){
- $dropbox_file = $task['task_results'][$result_id]['dropbox'];
- $args = $task['task_args']['account_info']['mwp_dropbox'];
- $args['backup_file'] = $dropbox_file;
- $backup_file = $this->get_dropbox_backup($args);
-
- if ($backup_file == false) {
- return array(
- 'error' => 'Failed to download file from Dropbox.'
- );
- }
- } elseif (isset($task['task_results'][$result_id]['google_drive'])) {
- $google_drive_file = $task['task_results'][$result_id]['google_drive'];
- $args = $task['task_args']['account_info']['mwp_google_drive'];
- $args['backup_file'] = $google_drive_file;
- $backup_file = $this->get_google_drive_backup($args);
-
- if (is_array($backup_file) && isset($backup_file['error'])) {
- return array(
- 'error' => 'Failed to download file from Google Drive, reason: ' . $backup_file['error']
- );
- } elseif ($backup_file == false) {
- return array(
- 'error' => 'Failed to download file from Google Drive.'
- );
- }
- }
-
- $what = $tasks[$task_name]['task_args']['what'];
- }
-
- $this->wpdb_reconnect();
-
- if ($backup_file && file_exists($backup_file)) {
- if ($overwrite) {
- //Keep old db credentials before overwrite
- if (!copy(ABSPATH . 'wp-config.php', ABSPATH . 'mwp-temp-wp-config.php')) {
- @unlink($backup_file);
- return array(
- 'error' => 'Error creating wp-config. Please check your write permissions.'
- );
- }
-
- $db_host = DB_HOST;
- $db_user = DB_USER;
- $db_password = DB_PASSWORD;
- $home = rtrim(get_option('home'), "/");
- $site_url = get_option('site_url');
-
- $clone_options = array();
- if (trim($clone_from_url) || trim($mwp_clone)) {
- $clone_options['_worker_nossl_key'] = get_option('_worker_nossl_key');
- $clone_options['_worker_public_key'] = get_option('_worker_public_key');
- $clone_options['_action_message_id'] = get_option('_action_message_id');
- }
- $clone_options['upload_path'] = get_option('upload_path');
- $clone_options['upload_url_path'] = get_option('upload_url_path');
-
- $clone_options['mwp_backup_tasks'] = serialize(get_option('mwp_backup_tasks'));
- $clone…
Large files files are truncated, but you can click here to view the full file