PluginProbe
ManageWP Worker / 3.9.23
ManageWP Worker v3.9.23
4.9.38 4.9.37 4.9.36 4.9.35 4.9.34 3.8.7 3.8.8 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.18 3.9.19 3.9.2 3.9.20 3.9.21 3.9.22 3.9.23 3.9.24 All 73 releases
worker / backup.class.php

backup.class.php in ManageWP Worker 3.9.23, at backup.class.php

3,320 lines 129.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*************************************************************
3 *
4 * backup.class.php
5 *
6 * Manage Backups
7 *
8 *
9 * Copyright (c) 2011 Prelovac Media
10 * www.prelovac.com
11 **************************************************************/
12 if(basename($_SERVER['SCRIPT_FILENAME']) == "backup.class.php"):
13 echo "Sorry but you cannot browse this file directly!";
14 exit;
15 endif;
16 define('MWP_BACKUP_DIR', WP_CONTENT_DIR . '/managewp/backups');
17 define('MWP_DB_DIR', MWP_BACKUP_DIR . '/mwp_db');
18
19 $zip_errors = array(
20 'No error',
21 'No error',
22 'Unexpected end of zip file',
23 'A generic error in the zipfile format was detected.',
24 'zip was unable to allocate itself memory',
25 'A severe error in the zipfile format was detected',
26 'Entry too large to be split with zipsplit',
27 'Invalid comment format',
28 'zip -T failed or out of memory',
29 'The user aborted zip prematurely',
30 'zip encountered an error while using a temp file',
31 'Read or seek error',
32 'zip has nothing to do',
33 'Missing or empty zip file',
34 'Error writing to a file',
35 'zip was unable to create a file to write to',
36 'bad command line parameters',
37 'no error',
38 'zip could not open a specified file to read'
39 );
40 $unzip_errors = array(
41 'No error',
42 'One or more warning errors were encountered, but processing completed successfully anyway',
43 'A generic error in the zipfile format was detected',
44 'A severe error in the zipfile format was detected.',
45 'unzip was unable to allocate itself memory.',
46 'unzip was unable to allocate memory, or encountered an encryption error',
47 'unzip was unable to allocate memory during decompression to disk',
48 'unzip was unable allocate memory during in-memory decompression',
49 'unused',
50 'The specified zipfiles were not found',
51 'Bad command line parameters',
52 'No matching files were found',
53 50 => 'The disk is (or was) full during extraction',
54 51 => 'The end of the ZIP archive was encountered prematurely.',
55 80 => 'The user aborted unzip prematurely.',
56 81 => 'Testing or extraction of one or more files failed due to unsupported compression methods or unsupported decryption.',
57 82 => 'No files were found due to bad decryption password(s)'
58 );
59
60 /**
61 * The main class for processing database and full backups on ManageWP worker.
62 *
63 * @copyright 2011-2012 Prelovac Media
64 * @version 3.9.24
65 * @package ManageWP
66 * @subpackage backup
67 *
68 */
69 class MMB_Backup extends MMB_Core {
70 var $site_name;
71 var $statuses;
72 var $tasks;
73 var $s3;
74 var $ftp;
75 var $dropbox;
76 var $google_drive;
77
78 /**
79 * Initializes site_name, statuses, and tasks attributes.
80 *
81 * @return void
82 */
83 function __construct() {
84 parent::__construct();
85 $this->site_name = str_replace(array(
86 "_",
87 "/",
88 "~"
89 ), array(
90 "",
91 "-",
92 "-"
93 ), rtrim($this->remove_http(get_bloginfo('url')), "/"));
94 $this->statuses = array(
95 'db_dump' => 1,
96 'db_zip' => 2,
97 'files_zip' => 3,
98 's3' => 4,
99 'dropbox' => 5,
100 'ftp' => 6,
101 'email' => 7,
102 'google_drive' => 8,
103 'finished' => 100
104 );
105 $this->tasks = get_option('mwp_backup_tasks');
106 }
107
108 /**
109 * Tries to increase memory limit to 384M and execution time to 600s.
110 *
111 * @return array an array with two keys for execution time and memory limit (0 - if not changed, 1 - if succesfully)
112 */
113 function set_memory() {
114 $changed = array('execution_time' => 0, 'memory_limit' => 0);
115
116 $memory_limit = trim(ini_get('memory_limit'));
117 $last = strtolower(substr($memory_limit, -1));
118
119 if($last == 'g')
120 $memory_limit = ((int) $memory_limit)*1024;
121 else if($last == 'm')
122 $memory_limit = (int) $memory_limit;
123 if($last == 'k')
124 $memory_limit = ((int) $memory_limit)/1024;
125
126 if ( $memory_limit < 384 ) {
127 @ini_set('memory_limit', '384M');
128 $changed['memory_limit'] = 1;
129 }
130
131 if ( (int) @ini_get('max_execution_time') < 600 ) {
132 @set_time_limit(600); //ten minutes
133 $changed['execution_time'] = 1;
134 }
135
136 return $changed;
137 }
138
139 /**
140 * Returns backup settings from local database for all tasks
141 *
142 * @return mixed|boolean
143 */
144 function get_backup_settings() {
145 $backup_settings = get_option('mwp_backup_tasks');
146
147 if (!empty($backup_settings))
148 return $backup_settings;
149 else
150 return false;
151 }
152
153 /**
154 * Sets backup task defined from master, if task name is "Backup Now" this function fires processing backup.
155 *
156 * @param mixed $params parameters sent from master
157 * @return mixed|boolean $this->tasks variable if success, array with error message if error has ocurred, false if $params are empty
158 */
159 function set_backup_task($params) {
160 //$params => [$task_name, $args, $error]
161 if (!empty($params)) {
162
163 //Make sure backup cron job is set
164 if (!wp_next_scheduled('mwp_backup_tasks')) {
165 wp_schedule_event( time(), 'tenminutes', 'mwp_backup_tasks' );
166 }
167
168 extract($params);
169
170 //$before = $this->get_backup_settings();
171 $before = $this->tasks;
172 if (!$before || empty($before))
173 $before = array();
174
175 if (isset($args['remove'])) {
176 unset($before[$task_name]);
177 $return = array(
178 'removed' => true
179 );
180 } else {
181 if (isset($params['account_info']) && is_array($params['account_info'])) { //only if sends from master first time(secure data)
182 $args['account_info'] = $account_info;
183 }
184
185 $before[$task_name]['task_args'] = $args;
186 if (strlen($args['schedule']))
187 $before[$task_name]['task_args']['next'] = $this->schedule_next($args['type'], $args['schedule']);
188
189 $return = $before[$task_name];
190 }
191
192 //Update with error
193 if (isset($error)) {
194 if (is_array($error)) {
195 $before[$task_name]['task_results'][count($before[$task_name]['task_results']) - 1]['error'] = $error['error'];
196 } else {
197 $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['error'] = $error;
198 }
199 }
200
201 if ($time) { //set next result time before backup
202 if (is_array($before[$task_name]['task_results'])) {
203 $before[$task_name]['task_results'] = array_values($before[$task_name]['task_results']);
204 }
205 $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['time'] = $time;
206 }
207
208 $this->update_tasks($before);
209 //update_option('mwp_backup_tasks', $before);
210
211 if ($task_name == 'Backup Now') {
212 $result = $this->backup($args, $task_name);
213 $backup_settings = $this->tasks;
214
215 if (is_array($result) && array_key_exists('error', $result)) {
216 $return = $result;
217 } else {
218 $return = $backup_settings[$task_name];
219 }
220 }
221 return $return;
222 }
223
224 return false;
225 }
226
227 /**
228 * Checks if scheduled task is ready for execution,
229 * if it is ready master sends google_drive_token, failed_emails, success_emails if are needed.
230 *
231 * @return void
232 */
233 function check_backup_tasks() {
234 $this->check_cron_remove();
235
236 $failed_emails = array();
237 $settings = $this->tasks;
238 if (is_array($settings) && !empty($settings)) {
239 foreach ($settings as $task_name => $setting) {
240 if ($setting['task_args']['next'] && $setting['task_args']['next'] < time()) {
241 //if ($setting['task_args']['next'] && $_GET['force_backup']) {
242 if ($setting['task_args']['url'] && $setting['task_args']['task_id'] && $setting['task_args']['site_key']) {
243 //Check orphan task
244 $check_data = array(
245 'task_name' => $task_name,
246 'task_id' => $setting['task_args']['task_id'],
247 'site_key' => $setting['task_args']['site_key'],
248 'worker_version' => MMB_WORKER_VERSION
249 );
250
251 if (isset($setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'])) {
252 $check_data['mwp_google_drive_refresh_token'] = true;
253 }
254
255 $check = $this->validate_task($check_data, $setting['task_args']['url']);
256 $worker_upto_3_9_22 = (MMB_WORKER_VERSION <= '3.9.22'); // worker version is less or equals to 3.9.22
257
258 if ($worker_upto_3_9_22) {
259 $potential_token = substr($check, 8);
260 if (substr($check, 0, 8) == 'token - ' && $potential_token != 'not found') {
261 $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
262 $settings[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
263 $setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
264 }
265 } else {
266 $potential_token = isset($check['google_drive_token']) ? $check['google_drive_token'] : false;
267 if ($potential_token) {
268 $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
269 $settings[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
270 $setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
271 }
272 }
273
274 }
275
276 $update = array(
277 'task_name' => $task_name,
278 'args' => $settings[$task_name]['task_args']
279 );
280
281 if($check != 'paused'){
282 $update['time'] = time();
283 }
284
285 //Update task with next schedule
286 $this->set_backup_task($update);
287
288 if($check == 'paused'){
289 continue;
290 }
291
292 $result = $this->backup($setting['task_args'], $task_name);
293 $error = '';
294
295 if (is_array($result) && array_key_exists('error', $result)) {
296 $error = $result;
297 $this->set_backup_task(array(
298 'task_name' => $task_name,
299 'args' => $settings[$task_name]['task_args'],
300 'error' => $error
301 ));
302 } else {
303 $setting = $this->tasks[$task_name];
304 if (@count($setting['task_args']['account_info'])) {
305 $last_result = $setting['task_results'][count($setting['task_results']) - 1];
306 $backup_file = $last_result['server']['file_path'];
307 $del_host_file = $setting['task_args']['del_host_file'];
308 wp_schedule_single_event(time(), 'mmb_scheduled_remote_upload', array('args' => array('task_name' => $task_name, 'backup_file' => $backup_file, 'del_host_file' => $del_host_file)));
309 //spawn_cron(time() + 150);
310 //wp_remote_post(site_url('index.php'), array( 'timeout' => 0.01, 'blocking' => false, 'sslverify' => apply_filters( 'https_local_ssl_verify', true ) ));
311 //update_option('_transient_doing_cron', 0);
312 /*$nonce = substr(wp_hash(wp_nonce_tick() . 'mmb-backup-nonce' . 0, 'nonce'), -12, 10);
313 $cron_url = site_url('index.php');
314 $args = array(
315 'body' => array(
316 'backup_cron_action' => 'mmb_remote_upload',
317 'args' => json_encode(array('task_name' => $task_name, 'backup_file' => $backup_file, 'del_host_file' => $del_host_file)),
318 'mmb_backup_nonce' => $nonce,
319 ),
320 'timeout' => 0.01,
321 'blocking' => false,
322 'sslverify' => apply_filters('https_local_ssl_verify', true)
323 );
324 wp_remote_post($cron_url, $args);*/
325 }
326 }
327
328 break; //Only one backup per cron
329 }
330 }
331 }
332
333 }
334
335 /**
336 * Runs backup task invoked from ManageWP master.
337 *
338 * @param string $task_name name of backup task
339 * @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)
340 * @return mixed array with backup statistics if successful, array with error message if not
341 */
342 function task_now($task_name, $google_drive_token = false) {
343 if ($google_drive_token) {
344 $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
345 }
346
347 $settings = $this->tasks;
348 if(!array_key_exists($task_name,$settings)){
349 return array('error' => $task_name." does not exist.");
350 } else {
351 $setting = $settings[$task_name];
352 }
353
354 $this->set_backup_task(array(
355 'task_name' => $task_name,
356 'args' => $settings[$task_name]['task_args'],
357 'time' => time()
358 ));
359
360 //Run backup
361 $result = $this->backup($setting['task_args'], $task_name);
362
363 //Check for error
364 if (is_array($result) && array_key_exists('error', $result)) {
365 $this->set_backup_task(array(
366 'task_name' => $task_name,
367 'args' => $settings[$task_name]['task_args'],
368 'error' => $result
369 ));
370 return $result;
371 } else {
372 return $this->get_backup_stats();
373 }
374 }
375
376 /**
377 * Backup a full wordpress instance, including a database dump, which is placed in mwp_db dir in root folder.
378 * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
379 *
380 * @param string $args arguments passed from master
381 * [type] -> db, full,
382 * [what] -> daily, weekly, monthly,
383 * [account_info] -> remote destinations ftp, amazons3, dropbox, google_drive, email with their parameters
384 * [include] -> array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
385 * [exclude] -> array of files of folders to exclude, relative to site's root
386 * @param bool|string[optional] $task_name the name of backup task, which backup is done (default: false)
387 * @return bool|array false if $args are missing, array with error if error has occured, ture if is successful
388 */
389 function backup($args, $task_name = false) {
390 if (!$args || empty($args))
391 return false;
392
393 extract($args); //extract settings
394
395 if (!empty($account_info)) {
396 $found = false;
397 $destinations = array('mwp_ftp', 'mwp_amazon_s3', 'mwp_dropbox', 'mwp_google_drive', 'mwp_email');
398 foreach($destinations as $dest) {
399 $found = $found || (isset($account_info[$dest]));
400 }
401 if (!$found) {
402 $error_message = 'Remote destination is not supported, please update your client plugin.';
403 return array(
404 'error' => $error_message
405 );
406 }
407 }
408
409 //Try increase memory limit and execution time
410 $this->set_memory();
411
412 //Remove old backup(s)
413 $removed = $this->remove_old_backups($task_name);
414 if (is_array($removed) && isset($removed['error'])) {
415 $error_message = $removed['error'];
416 return $removed;
417 }
418
419 $new_file_path = MWP_BACKUP_DIR;
420
421 if (!file_exists($new_file_path)) {
422 if (!mkdir($new_file_path, 0755, true))
423 $error_message = 'Permission denied, make sure you have write permission to wp-content folder.';
424 return array(
425 'error' => $error_message
426 );
427 }
428
429 @file_put_contents($new_file_path . '/index.php', ''); //safe
430
431 //Prepare .zip file name
432 $hash = md5(time());
433 $label = $type ? $type : 'manual';
434 $backup_file = $new_file_path . '/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
435 $backup_url = WP_CONTENT_URL . '/managewp/backups/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
436
437 $begin_compress = microtime(true);
438
439 //Optimize tables?
440 if (isset($optimize_tables) && !empty($optimize_tables)) {
441 $this->optimize_tables();
442 }
443
444 //What to backup - db or full?
445 if (trim($what) == 'db') {
446 $db_backup = $this->backup_db_compress($task_name, $backup_file);
447 if (is_array($db_backup) && array_key_exists('error', $db_backup)) {
448 $error_message = $db_backup['error'];
449 return array(
450 'error' => $error_message
451 );
452 }
453 } elseif (trim($what) == 'full') {
454 if (!$exclude) {
455 $exclude = array();
456 }
457 if (!$include) {
458 $include = array();
459 }
460 $content_backup = $this->backup_full($task_name, $backup_file, $exclude, $include);
461 if (is_array($content_backup) && array_key_exists('error', $content_backup)) {
462 $error_message = $content_backup['error'];
463 return array(
464 'error' => $error_message
465 );
466 }
467 }
468
469 $end_compress = microtime(true);
470
471 //Update backup info
472 if ($task_name) {
473 //backup task (scheduled)
474 $backup_settings = $this->tasks;
475 $paths = array();
476 $size = ceil(filesize($backup_file) / 1024);
477 $duration = round($end_compress - $begin_compress, 2);
478
479 if ($size > 1000) {
480 $paths['size'] = ceil($size / 1024) . "mb";
481 } else {
482 $paths['size'] = $size . 'kb';
483 }
484
485 $paths['duration'] = $duration . 's';
486
487 if ($task_name != 'Backup Now') {
488 $paths['server'] = array(
489 'file_path' => $backup_file,
490 'file_url' => $backup_url
491 );
492 } else {
493 $paths['server'] = array(
494 'file_path' => $backup_file,
495 'file_url' => $backup_url
496 );
497 }
498
499 if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_ftp'])) {
500 $paths['ftp'] = basename($backup_url);
501 }
502
503 if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_amazon_s3'])) {
504 $paths['amazons3'] = basename($backup_url);
505 }
506
507 if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_dropbox'])) {
508 $paths['dropbox'] = basename($backup_url);
509 }
510
511 if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_email'])) {
512 $paths['email'] = basename($backup_url);
513 }
514
515 if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_google_drive'])) {
516 $paths['google_drive'] = basename($backup_url);
517 }
518
519 $temp = $backup_settings[$task_name]['task_results'];
520 $temp = array_values($temp);
521 $paths['time'] = time();
522
523 if ($task_name != 'Backup Now') {
524 $paths['status'] = $temp[count($temp) - 1]['status'];
525 $temp[count($temp) - 1] = $paths;
526
527 } else {
528 $temp[count($temp)] = $paths;
529 }
530
531 $backup_settings[$task_name]['task_results'] = $temp;
532 $this->update_tasks($backup_settings);
533 //update_option('mwp_backup_tasks', $backup_settings);
534 }
535
536 // If there are not remote destination, set up task status to finished
537 if (@count($backup_settings[$task_name]['task_args']['account_info']) == 0) {
538 $this->update_status($task_name,$this->statuses['finished'], true);
539 }
540
541 return true;
542 }
543
544 /**
545 * Backup a full wordpress instance, including a database dump, which is placed in mwp_db dir in root folder.
546 * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
547 *
548 * @param string $task_name the name of backup task, which backup is done
549 * @param string $backup_file relative path to file which backup is stored
550 * @param array[optional] $exclude the list of files and folders, which are excluded from backup (default: array())
551 * @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())
552 * @return bool|array true if backup is successful, or an array with error message if is failed
553 */
554 function backup_full($task_name, $backup_file, $exclude = array(), $include = array()) {
555 $this->update_status($task_name, $this->statuses['db_dump']);
556 $db_result = $this->backup_db();
557
558 if ($db_result == false) {
559 return array(
560 'error' => 'Failed to backup database.'
561 );
562 } else if (is_array($db_result) && isset($db_result['error'])) {
563 return array(
564 'error' => $db_result['error']
565 );
566 }
567
568 $this->update_status($task_name, $this->statuses['db_dump'], true);
569 $this->update_status($task_name, $this->statuses['db_zip']);
570
571 @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
572 $zip_db_result = $this->zip_backup_db($task_name, $backup_file);
573
574 if (!$zip_db_result) {
575 $zip_archive_db_result = false;
576 if (class_exists("ZipArchive")) {
577 $this->_log("DB zip, fallback to ZipArchive");
578 $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
579 }
580
581 if (!$zip_archive_db_result) {
582 $this->_log("DB zip, fallback to PclZip");
583 $pclzip_db_result = $this->pclzip_backup_db($task_name, $backup_file);
584 if (!$pclzip_db_result) {
585 @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
586 @unlink($db_result);
587 @rmdir(MWP_DB_DIR);
588
589 return array(
590 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
591 );
592 }
593 }
594 }
595
596 @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
597 @unlink($db_result);
598 @rmdir(MWP_DB_DIR);
599
600 $remove = array(
601 trim(basename(WP_CONTENT_DIR)) . "/managewp/backups",
602 trim(basename(WP_CONTENT_DIR)) . "/" . md5('mmb-worker') . "/mwp_backups"
603 );
604 $exclude = array_merge($exclude, $remove);
605
606 $this->update_status($task_name, $this->statuses['db_zip'], true);
607 $this->update_status($task_name, $this->statuses['files_zip']);
608
609 $zip_result = $this->zip_backup($task_name, $backup_file, $exclude, $include);
610
611 if (isset($zip_result['error'])) {
612 return $zip_result;
613 }
614
615 if (!$zip_result) {
616 $zip_archive_result = false;
617 if (class_exists("ZipArchive")) {
618 $this->_log("Files zip fallback to ZipArchive");
619 $zip_archive_result = $this->zip_archive_backup($task_name, $backup_file, $exclude, $include);
620 }
621
622 if (!$zip_archive_result) {
623 $this->_log("Files zip fallback to PclZip");
624 $pclzip_result = $this->pclzip_backup($task_name, $backup_file, $exclude, $include);
625 if (!$pclzip_result) {
626 @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
627 @unlink($db_result);
628 @rmdir(MWP_DB_DIR);
629
630 if (!$pclzip_result) {
631 @unlink($backup_file);
632 return array(
633 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
634 );
635 }
636 }
637 }
638 }
639
640 //Reconnect
641 $this->wpdb_reconnect();
642
643 $this->update_status($task_name, $this->statuses['files_zip'], true);
644 return true;
645 }
646
647 /**
648 * Zipping database dump and index.php in folder mwp_db by system zip command, requires zip installed on OS.
649 *
650 * @param string $task_name the name of backup task
651 * @param string $backup_file absolute path to zip file
652 * @return bool is compress successful or not
653 */
654 function zip_backup_db($task_name, $backup_file) {
655 $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
656 $comp_level = $disable_comp ? '-0' : '-1';
657 $zip = $this->get_zip();
658 //Add database file
659 chdir(MWP_BACKUP_DIR);
660 $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
661
662 ob_start();
663 $this->_log("Executing $command");
664 $result = $this->mmb_exec($command);
665 ob_get_clean();
666
667 return $result;
668 }
669
670 /**
671 * Zipping database dump and index.php in folder mwp_db by ZipArchive class, requires php zip extension.
672 *
673 * @param string $task_name the name of backup task
674 * @param string $db_result relative path to database dump file
675 * @param string $backup_file absolute path to zip file
676 * @return bool is compress successful or not
677 */
678 function zip_archive_backup_db($task_name, $db_result, $backup_file) {
679 $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
680 if (!$disable_comp) {
681 $this->_log("Compression is not supported by ZipArchive");
682 }
683 $zip = new ZipArchive();
684 $result = $zip->open($backup_file, ZIPARCHIVE::OVERWRITE); // Tries to open $backup_file for acrhiving
685 if ($result === true) {
686 $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
687 $result = $result && $zip->addFile($db_result, "mwp_db/" . basename($db_result)); // Tries to add db dump form mwp_db dir to $backup_file
688 $result = $result && $zip->close(); // Tries to close $backup_file
689 } else {
690 $result = false;
691 }
692
693 return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
694 }
695
696 /**
697 * Zipping database dump and index.php in folder mwp_db by PclZip library.
698 *
699 * @param string $task_name the name of backup task
700 * @param string $backup_file absolute path to zip file
701 * @return bool is compress successful or not
702 */
703 function pclzip_backup_db($task_name, $backup_file) {
704 $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
705 define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
706 require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
707 $zip = new PclZip($backup_file);
708
709 if ($disable_comp) {
710 $result = $zip->add(MWP_BACKUP_DIR, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION) !== 0;
711 } else {
712 $result = $zip->add(MWP_BACKUP_DIR, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR) !== 0;
713 }
714
715 return $result;
716 }
717
718 /**
719 * Zipping whole site root folder and append to backup file with database dump
720 * by system zip command, requires zip installed on OS.
721 *
722 * @param string $task_name the name of backup task
723 * @param string $backup_file absolute path to zip file
724 * @param array $exclude array of files of folders to exclude, relative to site's root
725 * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
726 * @return array|bool true if successful or an array with error message if not
727 */
728 function zip_backup($task_name, $backup_file, $exclude, $include) {
729 global $zip_errors;
730 $sys = substr(PHP_OS, 0, 3);
731
732 //Exclude paths
733 $exclude_data = "-x";
734
735 $exclude_file_data = '';
736
737 if (!empty($exclude)) {
738 foreach ($exclude as $data) {
739 if (is_dir(ABSPATH . $data)) {
740 if ($sys == 'WIN')
741 $exclude_data .= " $data/*.*";
742 else
743 $exclude_data .= " '$data/*'";
744 } else {
745 if ($sys == 'WIN'){
746 if(file_exists(ABSPATH . $data)){
747 $exclude_data .= " $data";
748 $exclude_file_data .= " $data";
749 }
750 } else {
751 if(file_exists(ABSPATH . $data)){
752 $exclude_data .= " '$data'";
753 $exclude_file_data .= " '$data'";
754 }
755 }
756 }
757 }
758 }
759
760 if($exclude_file_data){
761 $exclude_file_data = "-x".$exclude_file_data;
762 }
763
764 //Include paths by default
765 $add = array(
766 trim(WPINC),
767 trim(basename(WP_CONTENT_DIR)),
768 "wp-admin"
769 );
770
771 $include_data = ". -i";
772 foreach ($add as $data) {
773 if ($sys == 'WIN')
774 $include_data .= " $data/*.*";
775 else
776 $include_data .= " '$data/*'";
777 }
778
779 //Additional includes?
780 if (!empty($include)) {
781 foreach ($include as $data) {
782 if ($data) {
783 if ($sys == 'WIN')
784 $include_data .= " $data/*.*";
785 else
786 $include_data .= " '$data/*'";
787 }
788 }
789 }
790
791 $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
792 $comp_level = $disable_comp ? '-0' : '-1';
793 $zip = $this->get_zip();
794 chdir(ABSPATH);
795 ob_start();
796 $command = "$zip -q -j $comp_level $backup_file .* * $exclude_file_data";
797 $this->_log("Executing $command");
798 $result_f = $this->mmb_exec($command, false, true);
799 if (!$result_f || $result_f == 18) { // disregard permissions error, file can't be accessed
800 $command = "$zip -q -r $comp_level $backup_file $include_data $exclude_data";
801 $result_d = $this->mmb_exec($command, false, true);
802 $this->_log("Executing $command");
803 if ($result_d && $result_d != 18) {
804 @unlink($backup_file);
805 if ($result_d > 0 && $result_d < 18)
806 return array(
807 'error' => 'Failed to archive files (' . $zip_errors[$result_d] . ') .'
808 );
809 else {
810 if ($result_d === -1) return false;
811 return array(
812 'error' => 'Failed to archive files.'
813 );
814 }
815 }
816 } else {
817 return false;
818 }
819
820 ob_get_clean();
821
822 return true;
823 }
824
825 /**
826 * Zipping whole site root folder and append to backup file with database dump
827 * by ZipArchive class, requires php zip extension.
828 *
829 * @param string $task_name the name of backup task
830 * @param string $backup_file absolute path to zip file
831 * @param array $exclude array of files of folders to exclude, relative to site's root
832 * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
833 * @return array|bool true if successful or an array with error message if not
834 */
835 function zip_archive_backup($task_name, $backup_file, $exclude, $include, $overwrite = false) {
836 $filelist = $this->get_backup_files($exclude, $include);
837 $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
838 if (!$disable_comp) {
839 $this->_log("Compression is not supported by ZipArchive");
840 }
841
842 $zip = new ZipArchive();
843 if ($overwrite) {
844 $result = $zip->open($backup_file, ZipArchive::OVERWRITE); // Tries to open $backup_file for acrhiving
845 } else {
846 $result = $zip->open($backup_file); // Tries to open $backup_file for acrhiving
847 }
848 if ($result === true) {
849 foreach ($filelist as $file) {
850 $result = $result && $zip->addFile($file, sprintf("%s", str_replace(ABSPATH, '', $file))); // Tries to add a new file to $backup_file
851 }
852 $result = $result && $zip->close(); // Tries to close $backup_file
853 } else {
854 $result = false;
855 }
856
857 return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
858 }
859
860 /**
861 * Zipping whole site root folder and append to backup file with database dump
862 * by PclZip library.
863 *
864 * @param string $task_name the name of backup task
865 * @param string $backup_file absolute path to zip file
866 * @param array $exclude array of files of folders to exclude, relative to site's root
867 * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
868 * @return array|bool true if successful or an array with error message if not
869 */
870 function pclzip_backup($task_name, $backup_file, $exclude, $include) {
871 define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
872 require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
873 $zip = new PclZip($backup_file);
874 $add = array(
875 trim(WPINC),
876 trim(basename(WP_CONTENT_DIR)),
877 "wp-admin"
878 );
879
880 $include_data = array();
881 if (!empty($include)) {
882 foreach ($include as $data) {
883 if ($data && file_exists(ABSPATH . $data))
884 $include_data[] = ABSPATH . $data . '/';
885 }
886 }
887 $include_data = array_merge($add, $include_data);
888
889 if ($handle = opendir(ABSPATH)) {
890 while (false !== ($file = readdir($handle))) {
891 if ($file != "." && $file != ".." && !is_dir($file) && file_exists(ABSPATH . $file)) {
892 $include_data[] = ABSPATH . $file;
893 }
894 }
895 closedir($handle);
896 }
897
898 $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
899
900 if ($disable_comp) {
901 $result = $zip->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_NO_COMPRESSION) !== 0;
902 } else {
903 $result = $zip->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH) !== 0;
904 }
905
906 $exclude_data = array();
907 if (!empty($exclude)) {
908 foreach ($exclude as $data) {
909 if (file_exists(ABSPATH . $data)) {
910 if (is_dir(ABSPATH . $data))
911 $exclude_data[] = $data . '/';
912 else
913 $exclude_data[] = $data;
914 }
915 }
916 }
917 $result = $result && $zip->delete(PCLZIP_OPT_BY_NAME, $exclude_data);
918
919 return $result;
920 }
921
922 /**
923 * Gets an array of relative paths of all files in site root recursively.
924 * By default, there are all files from root folder, all files from folders wp-admin, wp-content, wp-includes recursively.
925 * Parameter $include adds other folders from site root, and excludes any file or folder by relative path to site's root.
926 *
927 * @param array $exclude array of files of folders to exclude, relative to site's root
928 * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
929 * @return array array with all files in site root dir
930 */
931 function get_backup_files($exclude, $include) {
932 $add = array(
933 trim(WPINC),
934 trim(basename(WP_CONTENT_DIR)),
935 "wp-admin"
936 );
937
938 $include = array_merge($add, $include);
939
940 $filelist = array();
941 if ($handle = opendir(ABSPATH)) {
942 while (false !== ($file = readdir($handle))) {
943 if (is_dir($file) && file_exists(ABSPATH . $file) && !(in_array($file, $include))) {
944 $exclude[] = $file;
945 }
946 }
947 closedir($handle);
948 }
949
950 $filelist = get_all_files_from_dir(ABSPATH, $exclude);
951
952 return $filelist;
953 }
954
955 /**
956 * Backup a database dump of WordPress site.
957 * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
958 *
959 * @param string $task_name the name of backup task, which backup is done
960 * @param string $backup_file relative path to file which backup is stored
961 * @return bool|array true if backup is successful, or an array with error message if is failed
962 */
963 function backup_db_compress($task_name, $backup_file) {
964 $this->update_status($task_name, $this->statuses['db_dump']);
965 $db_result = $this->backup_db();
966
967 if ($db_result == false) {
968 return array(
969 'error' => 'Failed to backup database.'
970 );
971 } else if (is_array($db_result) && isset($db_result['error'])) {
972 return array(
973 'error' => $db_result['error']
974 );
975 }
976
977 $this->update_status($task_name, $this->statuses['db_dump'], true);
978 $this->update_status($task_name, $this->statuses['db_zip']);
979 @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
980 $zip_db_result = $this->zip_backup_db($task_name, $backup_file);
981
982 if (!$zip_db_result) {
983 $zip_archive_db_result = false;
984 if (class_exists("ZipArchive")) {
985 $this->_log("DB zip, fallback to ZipArchive");
986 $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
987 }
988
989 if (!$zip_archive_db_result) {
990 $this->_log("DB zip, fallback to PclZip");
991 $pclzip_db_result = $this->pclzip_backup_db($task_name, $backup_file);
992 if (!$pclzip_db_result) {
993 @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
994 @unlink($db_result);
995 @rmdir(MWP_DB_DIR);
996
997 return array(
998 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
999 );
1000 }
1001 }
1002 }
1003
1004 @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
1005 @unlink($db_result);
1006 @rmdir(MWP_DB_DIR);
1007
1008 $this->update_status($task_name, $this->statuses['db_zip'], true);
1009
1010 return true;
1011 }
1012
1013 /**
1014 * Creates database dump and places it in mwp_db folder in site's root.
1015 * This function dispatches if OS mysql command does not work calls a php alternative.
1016 *
1017 * @return string|array path to dump file if successful, or an array with error message if is failed
1018 */
1019 function backup_db() {
1020 $db_folder = MWP_DB_DIR . '/';
1021 if (!file_exists($db_folder)) {
1022 if (!mkdir($db_folder, 0755, true))
1023 return array(
1024 'error' => 'Error creating database backup folder (' . $db_folder . '). Make sure you have corrrect write permissions.'
1025 );
1026 }
1027
1028 $file = $db_folder . DB_NAME . '.sql';
1029 $result = $this->backup_db_dump($file); // try mysqldump always then fallback to php dump
1030 return $result;
1031 }
1032
1033 /**
1034 * Creates database dump by system mysql command.
1035 *
1036 * @param string $file absolute path to file in which dump should be placed
1037 * @return string|array path to dump file if successful, or an array with error message if is failed
1038 */
1039 function backup_db_dump($file) {
1040 global $wpdb;
1041 $paths = $this->check_mysql_paths();
1042 $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
1043 $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;
1044 ob_start();
1045 $result = $this->mmb_exec($command);
1046 ob_get_clean();
1047
1048 if (!$result) { // Fallback to php
1049 $this->_log("DB dump fallback to php");
1050 $result = $this->backup_db_php($file);
1051 return $result;
1052 }
1053
1054 if (filesize($file) == 0 || !is_file($file) || !$result) {
1055 @unlink($file);
1056 return false;
1057 } else {
1058 return $file;
1059 }
1060 }
1061
1062 /**
1063 * Creates database dump by php functions.
1064 *
1065 * @param string $file absolute path to file in which dump should be placed
1066 * @return string|array path to dump file if successful, or an array with error message if is failed
1067 */
1068 function backup_db_php($file) {
1069 global $wpdb;
1070 $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
1071 foreach ($tables as $table) {
1072 //drop existing table
1073 $dump_data = "DROP TABLE IF EXISTS $table[0];";
1074 //create table
1075 $create_table = $wpdb->get_row("SHOW CREATE TABLE $table[0]", ARRAY_N);
1076 $dump_data .= "\n\n" . $create_table[1] . ";\n\n";
1077
1078 $count = $wpdb->get_var("SELECT count(*) FROM $table[0]");
1079 if ($count > 100)
1080 $count = ceil($count / 100);
1081 else if ($count > 0)
1082 $count = 1;
1083
1084 for ($i = 0; $i < $count; $i++) {
1085 $low_limit = $i * 100;
1086 $qry = "SELECT * FROM $table[0] LIMIT $low_limit, 100";
1087 $rows = $wpdb->get_results($qry, ARRAY_A);
1088 if (is_array($rows)) {
1089 foreach ($rows as $row) {
1090 //insert single row
1091 $dump_data .= "INSERT INTO $table[0] VALUES(";
1092 $num_values = count($row);
1093 $j = 1;
1094 foreach ($row as $value) {
1095 $value = addslashes($value);
1096 $value = preg_replace("/\n/Ui", "\\n", $value);
1097 $num_values == $j ? $dump_data .= "'" . $value . "'" : $dump_data .= "'" . $value . "', ";
1098 $j++;
1099 unset($value);
1100 }
1101 $dump_data .= ");\n";
1102 }
1103 }
1104 }
1105 $dump_data .= "\n\n\n";
1106
1107 unset($rows);
1108 file_put_contents($file, $dump_data, FILE_APPEND);
1109 unset($dump_data);
1110 }
1111
1112 if (filesize($file) == 0 || !is_file($file)) {
1113 @unlink($file);
1114 return array(
1115 'error' => 'Database backup failed. Try to enable MySQL dump on your server.'
1116 );
1117 }
1118
1119 return $file;
1120 }
1121
1122 /**
1123 * Restores full WordPress site or database only form backup zip file.
1124 *
1125 * @param array array of arguments passed to backup restore
1126 * [task_name] -> name of backup task
1127 * [result_id] -> id of baskup task result, which should be restored
1128 * [google_drive_token] -> json of Google Drive token, if it is remote destination
1129 * @return bool|array true if successful, or an array with error message if is failed
1130 */
1131 function restore($args) {
1132 global $wpdb;
1133 if (empty($args)) {
1134 return false;
1135 }
1136
1137 extract($args);
1138 if (isset($google_drive_token)) {
1139 $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
1140 }
1141 $this->set_memory();
1142
1143 $unlink_file = true; //Delete file after restore
1144
1145 //Detect source
1146 if ($backup_url) {
1147 //This is for clone (overwrite)
1148 include_once ABSPATH . 'wp-admin/includes/file.php';
1149 $backup_file = download_url($backup_url);
1150 if (is_wp_error($backup_file)) {
1151 return array(
1152 'error' => 'Unable to download backup file ('.$backup_file->get_error_message().')'
1153 );
1154 }
1155 $what = 'full';
1156 } else {
1157 $tasks = $this->tasks;
1158 $task = $tasks[$task_name];
1159 if (isset($task['task_results'][$result_id]['server'])) {
1160 $backup_file = $task['task_results'][$result_id]['server']['file_path'];
1161 $unlink_file = false; //Don't delete file if stored on server
1162 } elseif (isset($task['task_results'][$result_id]['ftp'])) {
1163 $ftp_file = $task['task_results'][$result_id]['ftp'];
1164 $args = $task['task_args']['account_info']['mwp_ftp'];
1165 $args['backup_file'] = $ftp_file;
1166 $backup_file = $this->get_ftp_backup($args);
1167
1168 if ($backup_file == false) {
1169 return array(
1170 'error' => 'Failed to download file from FTP.'
1171 );
1172 }
1173 } elseif (isset($task['task_results'][$result_id]['amazons3'])) {
1174 $amazons3_file = $task['task_results'][$result_id]['amazons3'];
1175 $args = $task['task_args']['account_info']['mwp_amazon_s3'];
1176 $args['backup_file'] = $amazons3_file;
1177 $backup_file = $this->get_amazons3_backup($args);
1178
1179 if ($backup_file == false) {
1180 return array(
1181 'error' => 'Failed to download file from Amazon S3.'
1182 );
1183 }
1184 } elseif(isset($task['task_results'][$result_id]['dropbox'])){
1185 $dropbox_file = $task['task_results'][$result_id]['dropbox'];
1186 $args = $task['task_args']['account_info']['mwp_dropbox'];
1187 $args['backup_file'] = $dropbox_file;
1188 $backup_file = $this->get_dropbox_backup($args);
1189
1190 if ($backup_file == false) {
1191 return array(
1192 'error' => 'Failed to download file from Dropbox.'
1193 );
1194 }
1195 } elseif (isset($task['task_results'][$result_id]['google_drive'])) {
1196 $google_drive_file = $task['task_results'][$result_id]['google_drive'];
1197 $args = $task['task_args']['account_info']['mwp_google_drive'];
1198 $args['backup_file'] = $google_drive_file;
1199 $backup_file = $this->get_google_drive_backup($args);
1200
1201 if (is_array($backup_file) && isset($backup_file['error'])) {
1202 return array(
1203 'error' => 'Failed to download file from Google Drive, reason: ' . $backup_file['error']
1204 );
1205 } elseif ($backup_file == false) {
1206 return array(
1207 'error' => 'Failed to download file from Google Drive.'
1208 );
1209 }
1210 }
1211
1212 $what = $tasks[$task_name]['task_args']['what'];
1213 }
1214
1215 $this->wpdb_reconnect();
1216
1217 if ($backup_file && file_exists($backup_file)) {
1218 if ($overwrite) {
1219 //Keep old db credentials before overwrite
1220 if (!copy(ABSPATH . 'wp-config.php', ABSPATH . 'mwp-temp-wp-config.php')) {
1221 @unlink($backup_file);
1222 return array(
1223 'error' => 'Error creating wp-config. Please check your write permissions.'
1224 );
1225 }
1226
1227 $db_host = DB_HOST;
1228 $db_user = DB_USER;
1229 $db_password = DB_PASSWORD;
1230 $home = rtrim(get_option('home'), "/");
1231 $site_url = get_option('site_url');
1232
1233 $clone_options = array();
1234 if (trim($clone_from_url) || trim($mwp_clone)) {
1235 $clone_options['_worker_nossl_key'] = get_option('_worker_nossl_key');
1236 $clone_options['_worker_public_key'] = get_option('_worker_public_key');
1237 $clone_options['_action_message_id'] = get_option('_action_message_id');
1238 }
1239 $clone_options['upload_path'] = get_option('upload_path');
1240 $clone_options['upload_url_path'] = get_option('upload_url_path');
1241
1242 $clone_options['mwp_backup_tasks'] = serialize(get_option('mwp_backup_tasks'));
1243 $clone_options['mwp_notifications'] = serialize(get_option('mwp_notifications'));
1244 $clone_options['mwp_pageview_alerts'] = serialize(get_option('mwp_pageview_alerts'));
1245 } else {
1246 $restore_options = array();
1247 $restore_options['mwp_notifications'] = get_option('mwp_notifications');
1248 $restore_options['mwp_pageview_alerts'] = get_option('mwp_pageview_alerts');
1249 $restore_options['user_hit_count'] = get_option('user_hit_count');
1250 }
1251
1252 chdir(ABSPATH);
1253 $unzip = $this->get_unzip();
1254 $command = "$unzip -o $backup_file";
1255 ob_start();
1256 $result = $this->mmb_exec($command);
1257 ob_get_clean();
1258
1259 if (!$result) { //fallback to pclzip
1260 $this->_log("Files uznip fallback to pclZip");
1261 define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
1262 require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
1263 $archive = new PclZip($backup_file);
1264 $result = $archive->extract(PCLZIP_OPT_PATH, ABSPATH, PCLZIP_OPT_REPLACE_NEWER);
1265 }
1266
1267 if ($unlink_file) {
1268 @unlink($backup_file);
1269 }
1270
1271 if (!$result) {
1272 return array(
1273 'error' => 'Failed to unzip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
1274 );
1275 }
1276
1277 $db_result = $this->restore_db();
1278
1279 if (!$db_result) {
1280 return array(
1281 'error' => 'Error restoring database.'
1282 );
1283 } else if(is_array($db_result) && isset($db_result['error'])){
1284 return array(
1285 'error' => $db_result['error']
1286 );
1287 }
1288
1289 } else {
1290 return array(
1291 'error' => 'Error restoring. Cannot find backup file.'
1292 );
1293 }
1294
1295 $this->wpdb_reconnect();
1296
1297 //Replace options and content urls
1298 if ($overwrite) {
1299 //Get New Table prefix
1300 $new_table_prefix = trim($this->get_table_prefix());
1301 //Retrieve old wp_config
1302 @unlink(ABSPATH . 'wp-config.php');
1303 //Replace table prefix
1304 $lines = file(ABSPATH . 'mwp-temp-wp-config.php');
1305
1306 foreach ($lines as $line) {
1307 if (strstr($line, '$table_prefix')) {
1308 $line = '$table_prefix = "' . $new_table_prefix . '";' . PHP_EOL;
1309 }
1310 file_put_contents(ABSPATH . 'wp-config.php', $line, FILE_APPEND);
1311 }
1312
1313 @unlink(ABSPATH . 'mwp-temp-wp-config.php');
1314
1315 //Replace options
1316 $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = 'home'";
1317 $old = $wpdb->get_var($wpdb->prepare($query));
1318 $old = rtrim($old, "/");
1319 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$home' WHERE option_name = 'home'";
1320 $wpdb->query($wpdb->prepare($query));
1321 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$home' WHERE option_name = 'siteurl'";
1322 $wpdb->query($wpdb->prepare($query));
1323 //Replace content urls
1324 $query = "UPDATE " . $new_table_prefix . "posts SET post_content = REPLACE (post_content, '$old','$home') WHERE post_content REGEXP 'src=\"(.*)$old(.*)\"' OR post_content REGEXP 'href=\"(.*)$old(.*)\"'";
1325 $wpdb->query($wpdb->prepare($query));
1326
1327 if (trim($new_password)) {
1328 $new_password = wp_hash_password($new_password);
1329 }
1330 if (!trim($clone_from_url) && !trim($mwp_clone)) {
1331 if ($new_user && $new_password) {
1332 $query = "UPDATE " . $new_table_prefix . "users SET user_login = '$new_user', user_pass = '$new_password' WHERE user_login = '$old_user'";
1333 $wpdb->query($wpdb->prepare($query));
1334 }
1335 } else {
1336 if ($clone_from_url) {
1337 if ($new_user && $new_password) {
1338 $query = "UPDATE " . $new_table_prefix . "users SET user_pass = '$new_password' WHERE user_login = '$new_user'";
1339 $wpdb->query($wpdb->prepare($query));
1340 }
1341 }
1342
1343 if ($mwp_clone) {
1344 if ($admin_email) {
1345 //Clean Install
1346 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$admin_email' WHERE option_name = 'admin_email'";
1347 $wpdb->query($wpdb->prepare($query));
1348 $query = "SELECT * FROM " . $new_table_prefix . "users LIMIT 1";
1349 $temp_user = $wpdb->get_row($query);
1350 if (!empty($temp_user)) {
1351 $query = "UPDATE " . $new_table_prefix . "users SET user_email='$admin_email', user_login = '$new_user', user_pass = '$new_password' WHERE user_login = '$temp_user->user_login'";
1352 $wpdb->query($wpdb->prepare($query));
1353 }
1354
1355 }
1356 }
1357 }
1358
1359 if (is_array($clone_options) && !empty($clone_options)) {
1360 foreach ($clone_options as $key => $option) {
1361 if (!empty($key)) {
1362 $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = '$key'";
1363 $res = $wpdb->get_var($query);
1364 if ($res == false) {
1365 $query = "INSERT INTO " . $new_table_prefix . "options (option_value,option_name) VALUES('$option','$key')";
1366 $wpdb->query($wpdb->prepare($query));
1367 } else {
1368 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$option' WHERE option_name = '$key'";
1369 $wpdb->query($wpdb->prepare($query));
1370 }
1371 }
1372 }
1373 }
1374
1375 //Remove hit count
1376 $query = "DELETE FROM " . $new_table_prefix . "options WHERE option_name = 'user_hit_count'";
1377 $wpdb->query($wpdb->prepare($query));
1378
1379 //Check for .htaccess permalinks update
1380 $this->replace_htaccess($home);
1381 } else {
1382 //restore worker options
1383 if (is_array($restore_options) && !empty($restore_options)) {
1384 foreach ($restore_options as $key => $option) {
1385 update_option($key,$option);
1386 }
1387 }
1388 }
1389
1390 return true;
1391 }
1392
1393 /**
1394 * This function dispathces database restoring between mysql system command and php functions.
1395 * If system command fails, it calls the php alternative.
1396 *
1397 * @return bool|array true if successful, array with error message if not
1398 */
1399 function restore_db() {
1400 global $wpdb;
1401 $paths = $this->check_mysql_paths();
1402 $file_path = ABSPATH . 'mwp_db';
1403 @chmod($file_path,0755);
1404 $file_name = glob($file_path . '/*.sql');
1405 $file_name = $file_name[0];
1406
1407 if(!$file_name){
1408 return array('error' => 'Cannot access database file.');
1409 }
1410
1411 $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
1412 $command = $brace . $paths['mysql'] . $brace . ' --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" --default-character-set="utf8" ' . DB_NAME . ' < ' . $brace . $file_name . $brace;
1413
1414 ob_start();
1415 $result = $this->mmb_exec($command);
1416 ob_get_clean();
1417 if (!$result) {
1418 $this->_log('DB restore fallback to PHP');
1419 //try php
1420 $this->restore_db_php($file_name);
1421 }
1422
1423 @unlink($file_name);
1424 return true;
1425 }
1426
1427 /**
1428 * Restores database dump by php functions.
1429 *
1430 * @param string $file_name relative path to database dump, which should be restored
1431 * @return bool is successful or not
1432 */
1433 function restore_db_php($file_name) {
1434 global $wpdb;
1435 $current_query = '';
1436 // Read in entire file
1437 $lines = file($file_name);
1438 // Loop through each line
1439 foreach ($lines as $line) {
1440 // Skip it if it's a comment
1441 if (substr($line, 0, 2) == '--' || $line == '')
1442 continue;
1443
1444 // Add this line to the current query
1445 $current_query .= $line;
1446 // If it has a semicolon at the end, it's the end of the query
1447 if (substr(trim($line), -1, 1) == ';') {
1448 // Perform the query
1449 $result = $wpdb->query($current_query);
1450 if ($result === false)
1451 return false;
1452 // Reset temp variable to empty
1453 $current_query = '';
1454 }
1455 }
1456
1457 @unlink($file_name);
1458 return true;
1459 }
1460
1461 /**
1462 * Retruns table_prefix for this WordPress installation.
1463 * It is used by restore.
1464 *
1465 * @return string table prefix from wp-config.php file, (default: wp_)
1466 */
1467 function get_table_prefix() {
1468 $lines = file(ABSPATH . 'wp-config.php');
1469 foreach ($lines as $line) {
1470 if (strstr($line, '$table_prefix')) {
1471 $pattern = "/(\'|\")[^(\'|\")]*/";
1472 preg_match($pattern, $line, $matches);
1473 $prefix = substr($matches[0], 1);
1474 return $prefix;
1475 break;
1476 }
1477 }
1478 return 'wp_'; //default
1479 }
1480
1481 /**
1482 * Change all tables to InnoDB engine, and executes mysql OPTIMIZE TABLE for each table.
1483 *
1484 * @return bool optimized successfully or not
1485 */
1486 function optimize_tables() {
1487 global $wpdb;
1488 $query = 'SHOW TABLES';
1489 $tables = $wpdb->get_results($wpdb->prepare($query), ARRAY_A);
1490 foreach ($tables as $table) {
1491 if (in_array($table['Engine'], array(
1492 'MyISAM',
1493 'ISAM',
1494 'HEAP',
1495 'MEMORY',
1496 'ARCHIVE'
1497 )))
1498 $table_string .= $table['Name'] . ",";
1499 elseif ($table['Engine'] == 'InnoDB') {
1500 $optimize = $wpdb->query("ALTER TABLE {$table['Name']} ENGINE=InnoDB");
1501 }
1502 }
1503
1504 $table_string = rtrim($table_string);
1505 $optimize = $wpdb->query("OPTIMIZE TABLE $table_string");
1506
1507 return $optimize ? true : false;
1508 }
1509
1510 /**
1511 * Returns mysql and mysql dump command path on OS.
1512 *
1513 * @return array array with system mysql and mysqldump command, blank if does not exist
1514 */
1515 function check_mysql_paths() {
1516 global $wpdb;
1517 $paths = array(
1518 'mysql' => '',
1519 'mysqldump' => ''
1520 );
1521 if (substr(PHP_OS, 0, 3) == 'WIN') {
1522 $mysql_install = $wpdb->get_row("SHOW VARIABLES LIKE 'basedir'");
1523 if ($mysql_install) {
1524 $install_path = str_replace('\\', '/', $mysql_install->Value);
1525 $paths['mysql'] = $install_path . 'bin/mysql.exe';
1526 $paths['mysqldump'] = $install_path . 'bin/mysqldump.exe';
1527 } else {
1528 $paths['mysql'] = 'mysql.exe';
1529 $paths['mysqldump'] = 'mysqldump.exe';
1530 }
1531 } else {
1532 $paths['mysql'] = $this->mmb_exec('which mysql', true);
1533 if (empty($paths['mysql']))
1534 $paths['mysql'] = 'mysql'; // try anyway
1535
1536 $paths['mysqldump'] = $this->mmb_exec('which mysqldump', true);
1537 if (empty($paths['mysqldump']))
1538 $paths['mysqldump'] = 'mysqldump'; // try anyway
1539 }
1540
1541 return $paths;
1542 }
1543
1544 /**
1545 * Check if exec, system, passthru functions exist
1546 *
1547 * @return string|bool exec if exists, then system, then passthru, then false if no one exist
1548 */
1549 function check_sys() {
1550 if ($this->mmb_function_exists('exec'))
1551 return 'exec';
1552
1553 if ($this->mmb_function_exists('system'))
1554 return 'system';
1555
1556 if ($this->mmb_function_exists('passhtru'))
1557 return 'passthru';
1558
1559 return false;
1560 }
1561
1562 /**
1563 * Executes an external system command.
1564 *
1565 * @param string $command external command to execute
1566 * @param bool[optional] $string return as a system output string (default: false)
1567 * @param bool[optional] $rawreturn return as a status of executed command
1568 * @return bool|int|string output depends on parameters $string and $rawreturn, -1 if no one execute function is enabled
1569 */
1570 function mmb_exec($command, $string = false, $rawreturn = false) {
1571 if ($command == '')
1572 return false;
1573
1574 if ($this->mmb_function_exists('exec')) {
1575 $log = @exec($command, $output, $return);
1576 $this->_log("Type: exec");
1577 $this->_log("Command: ".$command);
1578 $this->_log("Return: ".$return);
1579 if ($string)
1580 return $log;
1581 if ($rawreturn)
1582 return $return;
1583
1584 return $return ? false : true;
1585 } elseif ($this->mmb_function_exists('system')) {
1586 $log = @system($command, $return);
1587 $this->_log("Type: system");
1588 $this->_log("Command: ".$command);
1589 $this->_log("Return: ".$return);
1590 if ($string)
1591 return $log;
1592
1593 if ($rawreturn)
1594 return $return;
1595
1596 return $return ? false : true;
1597 } elseif ($this->mmb_function_exists('passthru') && !$string) {
1598 $log = passthru($command, $return);
1599 $this->_log("Type: passthru");
1600 $this->_log("Command: ".$command);
1601 $this->_log("Return: ".$return);
1602 if ($rawreturn)
1603 return $return;
1604
1605 return $return ? false : true;
1606 }
1607
1608 if ($rawreturn)
1609 return -1;
1610
1611 return false;
1612 }
1613
1614 /**
1615 * Returns a path to system command for zip execution.
1616 *
1617 * @return string command for zip execution
1618 */
1619 function get_zip() {
1620 $zip = $this->mmb_exec('which zip', true);
1621 if (!$zip)
1622 $zip = "zip";
1623 return $zip;
1624 }
1625
1626 /**
1627 * Returns a path to system command for unzip execution.
1628 *
1629 * @return string command for unzip execution
1630 */
1631 function get_unzip() {
1632 $unzip = $this->mmb_exec('which unzip', true);
1633 if (!$unzip)
1634 $unzip = "unzip";
1635 return $unzip;
1636 }
1637
1638 /**
1639 * Returns all important information of worker's system status to master.
1640 *
1641 * @return mixed associative array with information of server OS, php version, is backup folder writable, execute function, zip and unzip command, execution time, memory limit and path to error log if exists
1642 */
1643 function check_backup_compat() {
1644 $reqs = array();
1645 if (strpos($_SERVER['DOCUMENT_ROOT'], '/') === 0) {
1646 $reqs['Server OS']['status'] = 'Linux (or compatible)';
1647 $reqs['Server OS']['pass'] = true;
1648 } else {
1649 $reqs['Server OS']['status'] = 'Windows';
1650 $reqs['Server OS']['pass'] = true;
1651 $pass = false;
1652 }
1653 $reqs['PHP Version']['status'] = phpversion();
1654 if ((float) phpversion() >= 5.1) {
1655 $reqs['PHP Version']['pass'] = true;
1656 } else {
1657 $reqs['PHP Version']['pass'] = false;
1658 $pass = false;
1659 }
1660
1661 if (is_writable(WP_CONTENT_DIR)) {
1662 $reqs['Backup Folder']['status'] = "writable";
1663 $reqs['Backup Folder']['pass'] = true;
1664 } else {
1665 $reqs['Backup Folder']['status'] = "not writable";
1666 $reqs['Backup Folder']['pass'] = false;
1667 }
1668
1669 $file_path = MWP_BACKUP_DIR;
1670 $reqs['Backup Folder']['status'] .= ' (' . $file_path . ')';
1671
1672 if ($func = $this->check_sys()) {
1673 $reqs['Execute Function']['status'] = $func;
1674 $reqs['Execute Function']['pass'] = true;
1675 } else {
1676 $reqs['Execute Function']['status'] = "not found";
1677 $reqs['Execute Function']['info'] = "(will try PHP replacement)";
1678 $reqs['Execute Function']['pass'] = false;
1679 }
1680
1681 $reqs['Zip']['status'] = $this->get_zip();
1682 $reqs['Zip']['pass'] = true;
1683 $reqs['Unzip']['status'] = $this->get_unzip();
1684 $reqs['Unzip']['pass'] = true;
1685
1686 $paths = $this->check_mysql_paths();
1687
1688 if (!empty($paths['mysqldump'])) {
1689 $reqs['MySQL Dump']['status'] = $paths['mysqldump'];
1690 $reqs['MySQL Dump']['pass'] = true;
1691 } else {
1692 $reqs['MySQL Dump']['status'] = "not found";
1693 $reqs['MySQL Dump']['info'] = "(will try PHP replacement)";
1694 $reqs['MySQL Dump']['pass'] = false;
1695 }
1696
1697 $exec_time = ini_get('max_execution_time');
1698 $reqs['Execution time']['status'] = $exec_time ? $exec_time . "s" : 'unknown';
1699 $reqs['Execution time']['pass'] = true;
1700
1701 $mem_limit = ini_get('memory_limit');
1702 $reqs['Memory limit']['status'] = $mem_limit ? $mem_limit : 'unknown';
1703 $reqs['Memory limit']['pass'] = true;
1704
1705 $changed = $this->set_memory();
1706 if($changed['execution_time']){
1707 $exec_time = ini_get('max_execution_time');
1708 $reqs['Execution time']['status'] .= $exec_time ? ' (will try '.$exec_time . 's)' : ' (unknown)';
1709 }
1710 if($changed['memory_limit']){
1711 $mem_limit = ini_get('memory_limit');
1712 $reqs['Memory limit']['status'] .= $mem_limit ? ' (will try '.$mem_limit.')' : ' (unknown)';
1713 }
1714
1715 if(defined('MWP_SHOW_LOG') && MWP_SHOW_LOG == true){
1716 $md5 = get_option('mwp_log_md5');
1717 if ($md5 !== false) {
1718 global $mmb_plugin_url;
1719 $md5 = "<a href='$mmb_plugin_url/log_$md5' target='_blank'>$md5</a>";
1720 } else {
1721 $md5 = "not created";
1722 }
1723 $reqs['Backup Log']['status'] = $md5;
1724 $reqs['Backup Log']['pass'] = true;
1725 }
1726
1727 return $reqs;
1728 }
1729
1730 /**
1731 * Uploads backup file from server to email.
1732 * A lot of email service have limitation to 10mb.
1733 *
1734 * @param array $args arguments passed to the function
1735 * [email] -> email address which backup should send to
1736 * [task_name] -> name of backup task
1737 * [file_path] -> absolute path of backup file on local server
1738 * @return bool|array true is successful, array with error message if not
1739 */
1740 function email_backup($args) {
1741 $email = $args['email'];
1742
1743 if (!is_email($email)) {
1744 return array(
1745 'error' => 'Your email (' . $email . ') is not correct'
1746 );
1747 }
1748 $backup_file = $args['file_path'];
1749 $task_name = isset($args['task_name']) ? $args['task_name'] : '';
1750 if (file_exists($backup_file) && $email) {
1751 $attachments = array(
1752 $backup_file
1753 );
1754 $headers = 'From: ManageWP <no-reply@managewp.com>' . "\r\n";
1755 $subject = "ManageWP - " . $task_name . " - " . $this->site_name;
1756 ob_start();
1757 $result = wp_mail($email, $subject, $subject, $headers, $attachments);
1758 ob_end_clean();
1759
1760 }
1761
1762 if (!$result) {
1763 return array(
1764 'error' => 'Email not sent. Maybe your backup is too big for email or email server is not available on your website.'
1765 );
1766 }
1767 return true;
1768 }
1769
1770 /**
1771 * Uploads backup file from server to remote ftp server.
1772 *
1773 * @param array $args arguments passed to the function
1774 * [ftp_username] -> ftp username on remote server
1775 * [ftp_password] -> ftp password on remote server
1776 * [ftp_hostname] -> ftp hostname of remote host
1777 * [ftp_remote_folder] -> folder on remote site which backup file should be upload to
1778 * [ftp_site_folder] -> subfolder with site name in ftp_remote_folder which backup file should be upload to
1779 * [backup_file] -> absolute path of backup file on local server
1780 * @return bool|array true is successful, array with error message if not
1781 */
1782 function ftp_backup($args) {
1783 extract($args);
1784
1785 $port = $ftp_port ? $ftp_port : 21; //default port is 21
1786 if ($ftp_ssl) {
1787 if (function_exists('ftp_ssl_connect')) {
1788 $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1789 } else {
1790 return array(
1791 'error' => 'FTPS disabled: Please enable ftp_ssl_connect in PHP',
1792 'partial' => 1
1793 );
1794 }
1795 } else {
1796 if (function_exists('ftp_connect')) {
1797 $conn_id = ftp_connect($ftp_hostname,$port);
1798 if ($conn_id === false) {
1799 return array(
1800 'error' => 'Failed to connect to ' . $ftp_hostname,
1801 'partial' => 1
1802 );
1803 }
1804 } else {
1805 return array(
1806 'error' => 'FTP disabled: Please enable ftp_connect in PHP',
1807 'partial' => 1
1808 );
1809 }
1810 }
1811 $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1812 if ($login === false) {
1813 return array(
1814 'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
1815 'partial' => 1
1816 );
1817 }
1818
1819 if($ftp_passive){
1820 @ftp_pasv($conn_id,true);
1821 }
1822
1823 @ftp_mkdir($conn_id, $ftp_remote_folder);
1824 if ($ftp_site_folder) {
1825 $ftp_remote_folder .= '/' . $this->site_name;
1826 }
1827 @ftp_mkdir($conn_id, $ftp_remote_folder);
1828
1829 $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
1830 if ($upload === false) { //Try ascii
1831 $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
1832 }
1833 ftp_close($conn_id);
1834
1835 if ($upload === false) {
1836 return array(
1837 'error' => 'Failed to upload file to FTP. Please check your specified path.',
1838 'partial' => 1
1839 );
1840 }
1841
1842 return true;
1843 }
1844
1845 /**
1846 * Deletes backup file from remote ftp server.
1847 *
1848 * @param array $args arguments passed to the function
1849 * [ftp_username] -> ftp username on remote server
1850 * [ftp_password] -> ftp password on remote server
1851 * [ftp_hostname] -> ftp hostname of remote host
1852 * [ftp_remote_folder] -> folder on remote site which backup file should be deleted from
1853 * [ftp_site_folder] -> subfolder with site name in ftp_remote_folder which backup file should be deleted from
1854 * [backup_file] -> absolute path of backup file on local server
1855 * @return void
1856 */
1857 function remove_ftp_backup($args) {
1858 extract($args);
1859
1860 $port = $ftp_port ? $ftp_port : 21; //default port is 21
1861 if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1862 $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1863 } else if (function_exists('ftp_connect')) {
1864 $conn_id = ftp_connect($ftp_hostname,$port);
1865 }
1866
1867 if ($conn_id) {
1868 $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1869 if ($ftp_site_folder)
1870 $ftp_remote_folder .= '/' . $this->site_name;
1871
1872 if($ftp_passive){
1873 @ftp_pasv($conn_id,true);
1874 }
1875
1876 $delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
1877
1878 ftp_close($conn_id);
1879 }
1880 }
1881
1882 /**
1883 * Downloads backup file from server from remote ftp server to root folder on local server.
1884 *
1885 * @param array $args arguments passed to the function
1886 * [ftp_username] -> ftp username on remote server
1887 * [ftp_password] -> ftp password on remote server
1888 * [ftp_hostname] -> ftp hostname of remote host
1889 * [ftp_remote_folder] -> folder on remote site which backup file should be downloaded from
1890 * [ftp_site_folder] -> subfolder with site name in ftp_remote_folder which backup file should be downloaded from
1891 * [backup_file] -> absolute path of backup file on local server
1892 * @return string|array absolute path to downloaded file is successful, array with error message if not
1893 */
1894 function get_ftp_backup($args) {
1895 extract($args);
1896
1897 $port = $ftp_port ? $ftp_port : 21; //default port is 21
1898 if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1899 $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1900
1901 } else if (function_exists('ftp_connect')) {
1902 $conn_id = ftp_connect($ftp_hostname,$port);
1903 if ($conn_id === false) {
1904 return false;
1905 }
1906 }
1907 $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1908 if ($login === false) {
1909 return false;
1910 }
1911
1912 if ($ftp_site_folder)
1913 $ftp_remote_folder .= '/' . $this->site_name;
1914
1915 if($ftp_passive){
1916 @ftp_pasv($conn_id,true);
1917 }
1918
1919 $temp = ABSPATH . 'mwp_temp_backup.zip';
1920 $get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
1921 if ($get === false) {
1922 return false;
1923 }
1924
1925 ftp_close($conn_id);
1926
1927 return $temp;
1928 }
1929
1930 /**
1931 * Uploads backup file from server to Dropbox.
1932 *
1933 * @param array $args arguments passed to the function
1934 * [consumer_key] -> consumer key of ManageWP Dropbox application
1935 * [consumer_secret] -> consumer secret of ManageWP Dropbox application
1936 * [oauth_token] -> oauth token of user on ManageWP Dropbox application
1937 * [oauth_token_secret] -> oauth token secret of user on ManageWP Dropbox application
1938 * [dropbox_destination] -> folder on user's Dropbox account which backup file should be upload to
1939 * [dropbox_site_folder] -> subfolder with site name in dropbox_destination which backup file should be upload to
1940 * [backup_file] -> absolute path of backup file on local server
1941 * @return bool|array true is successful, array with error message if not
1942 */
1943 function dropbox_backup($args) {
1944 extract($args);
1945
1946 global $mmb_plugin_dir;
1947 require_once $mmb_plugin_dir . '/lib/dropbox.php';
1948
1949 $dropbox = new Dropbox($consumer_key, $consumer_secret);
1950 $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
1951
1952 if ($dropbox_site_folder == true)
1953 $dropbox_destination .= '/' . $this->site_name . '/' . basename($backup_file);
1954 else
1955 $dropbox_destination .= '/' . basename($backup_file);
1956
1957 try {
1958 $dropbox->upload($backup_file, $dropbox_destination, true);
1959 } catch (Exception $e) {
1960 $this->_log($e->getMessage());
1961 return array(
1962 'error' => $e->getMessage(),
1963 'partial' => 1
1964 );
1965 }
1966
1967 return true;
1968 }
1969
1970 /**
1971 * Deletes backup file from Dropbox to root folder on local server.
1972 *
1973 * @param array $args arguments passed to the function
1974 * [consumer_key] -> consumer key of ManageWP Dropbox application
1975 * [consumer_secret] -> consumer secret of ManageWP Dropbox application
1976 * [oauth_token] -> oauth token of user on ManageWP Dropbox application
1977 * [oauth_token_secret] -> oauth token secret of user on ManageWP Dropbox application
1978 * [dropbox_destination] -> folder on user's Dropbox account which backup file should be downloaded from
1979 * [dropbox_site_folder] -> subfolder with site name in dropbox_destination which backup file should be downloaded from
1980 * [backup_file] -> absolute path of backup file on local server
1981 * @return void
1982 */
1983 function remove_dropbox_backup($args) {
1984 extract($args);
1985
1986 global $mmb_plugin_dir;
1987 require_once $mmb_plugin_dir . '/lib/dropbox.php';
1988
1989 $dropbox = new Dropbox($consumer_key, $consumer_secret);
1990 $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
1991
1992 if ($dropbox_site_folder == true)
1993 $dropbox_destination .= '/' . $this->site_name;
1994
1995 try {
1996 $dropbox->fileopsDelete($dropbox_destination . '/' . $backup_file);
1997 } catch (Exception $e) {
1998 $this->_log($e->getMessage());
1999 /*return array(
2000 'error' => $e->getMessage(),
2001 'partial' => 1
2002 );*/
2003 }
2004
2005 //return true;
2006 }
2007
2008 /**
2009 * Downloads backup file from Dropbox to root folder on local server.
2010 *
2011 * @param array $args arguments passed to the function
2012 * [consumer_key] -> consumer key of ManageWP Dropbox application
2013 * [consumer_secret] -> consumer secret of ManageWP Dropbox application
2014 * [oauth_token] -> oauth token of user on ManageWP Dropbox application
2015 * [oauth_token_secret] -> oauth token secret of user on ManageWP Dropbox application
2016 * [dropbox_destination] -> folder on user's Dropbox account which backup file should be deleted from
2017 * [dropbox_site_folder] -> subfolder with site name in dropbox_destination which backup file should be deleted from
2018 * [backup_file] -> absolute path of backup file on local server
2019 * @return bool|array absolute path to downloaded file is successful, array with error message if not
2020 */
2021 function get_dropbox_backup($args) {
2022 extract($args);
2023
2024 global $mmb_plugin_dir;
2025 require_once $mmb_plugin_dir . '/lib/dropbox.php';
2026
2027 $dropbox = new Dropbox($consumer_key, $consumer_secret);
2028 $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
2029
2030 if ($dropbox_site_folder == true)
2031 $dropbox_destination .= '/' . $this->site_name;
2032
2033 $temp = ABSPATH . 'mwp_temp_backup.zip';
2034
2035 try {
2036 $file = $dropbox->download($dropbox_destination.'/'.$backup_file);
2037 $handle = @fopen($temp, 'w');
2038 $result = fwrite($handle,$file);
2039 fclose($handle);
2040
2041 if($result)
2042 return $temp;
2043 else
2044 return false;
2045 } catch (Exception $e) {
2046 $this->_log($e->getMessage());
2047 return array(
2048 'error' => $e->getMessage(),
2049 'partial' => 1
2050 );
2051 }
2052 }
2053
2054 /**
2055 * Uploads backup file from server to Amazon S3.
2056 *
2057 * @param array $args arguments passed to the function
2058 * [as3_bucket_region] -> Amazon S3 bucket region
2059 * [as3_bucket] -> Amazon S3 bucket
2060 * [as3_access_key] -> Amazon S3 access key
2061 * [as3_secure_key] -> Amazon S3 secure key
2062 * [as3_directory] -> folder on user's Amazon S3 account which backup file should be upload to
2063 * [as3_site_folder] -> subfolder with site name in as3_directory which backup file should be upload to
2064 * [backup_file] -> absolute path of backup file on local server
2065 * @return bool|array true is successful, array with error message if not
2066 */
2067 function amazons3_backup($args) {
2068 if ($this->mmb_function_exists('curl_init')) {
2069 require_once('lib/s3.php');
2070 extract($args);
2071
2072 if ($as3_site_folder == true)
2073 $as3_directory .= '/' . $this->site_name;
2074
2075 $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
2076 try{
2077 $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
2078 if ($s3->putObjectFile($backup_file, $as3_bucket, $as3_directory . '/' . basename($backup_file), mwpS3::ACL_PRIVATE)) {
2079 return true;
2080 } else {
2081
2082 return array(
2083 'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
2084 'partial' => 1
2085 );
2086 }
2087 } catch (Exception $e) {
2088 $err = $e->getMessage();
2089 if($err){
2090 return array(
2091 'error' => 'Failed to upload to AmazonS3 ('.$err.').'
2092 );
2093 } else {
2094 return array(
2095 'error' => 'Failed to upload to Amazon S3.'
2096 );
2097 }
2098 }
2099
2100 } else {
2101 return array(
2102 'error' => 'You cannot use Amazon S3 on your server. Please enable curl extension first.',
2103 'partial' => 1
2104 );
2105 }
2106 }
2107
2108 /**
2109 * Deletes backup file from Amazon S3.
2110 *
2111 * @param array $args arguments passed to the function
2112 * [as3_bucket_region] -> Amazon S3 bucket region
2113 * [as3_bucket] -> Amazon S3 bucket
2114 * [as3_access_key] -> Amazon S3 access key
2115 * [as3_secure_key] -> Amazon S3 secure key
2116 * [as3_directory] -> folder on user's Amazon S3 account which backup file should be deleted from
2117 * [as3_site_folder] -> subfolder with site name in as3_directory which backup file should be deleted from
2118 * [backup_file] -> absolute path of backup file on local server
2119 * @return void
2120 */
2121 function remove_amazons3_backup($args) {
2122 if ($this->mmb_function_exists('curl_init')) {
2123 require_once('lib/s3.php');
2124 extract($args);
2125 if ($as3_site_folder == true)
2126 $as3_directory .= '/' . $this->site_name;
2127 $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
2128 try {
2129 $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
2130 $s3->deleteObject($as3_bucket, $as3_directory . '/' . $backup_file);
2131 } catch (Exception $e){
2132
2133 }
2134 }
2135 }
2136
2137 /**
2138 * Downloads backup file from Amazon S3 to root folder on local server.
2139 *
2140 * @param array $args arguments passed to the function
2141 * [as3_bucket_region] -> Amazon S3 bucket region
2142 * [as3_bucket] -> Amazon S3 bucket
2143 * [as3_access_key] -> Amazon S3 access key
2144 * [as3_secure_key] -> Amazon S3 secure key
2145 * [as3_directory] -> folder on user's Amazon S3 account which backup file should be downloaded from
2146 * [as3_site_folder] -> subfolder with site name in as3_directory which backup file should be downloaded from
2147 * [backup_file] -> absolute path of backup file on local server
2148 * @return bool|array absolute path to downloaded file is successful, array with error message if not
2149 */
2150 function get_amazons3_backup($args) {
2151 require_once('lib/s3.php');
2152 extract($args);
2153 $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
2154 $temp = '';
2155 try {
2156 $s3 = new mwpS3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
2157 if ($as3_site_folder == true)
2158 $as3_directory .= '/' . $this->site_name;
2159
2160 $temp = ABSPATH . 'mwp_temp_backup.zip';
2161 $s3->getObject($as3_bucket, $as3_directory . '/' . $backup_file, $temp);
2162 } catch (Exception $e) {
2163 return $temp;
2164 }
2165 return $temp;
2166 }
2167
2168 /**
2169 * Uploads backup file from server to Google Drive.
2170 *
2171 * @param array $args arguments passed to the function
2172 * [google_drive_token] -> user's Google drive token in json form
2173 * [google_drive_directory] -> folder on user's Google Drive account which backup file should be upload to
2174 * [google_drive_site_folder] -> subfolder with site name in google_drive_directory which backup file should be upload to
2175 * [backup_file] -> absolute path of backup file on local server
2176 * @return bool|array true is successful, array with error message if not
2177 */
2178 function google_drive_backup($args) {
2179 extract($args);
2180
2181 global $mmb_plugin_dir;
2182 require_once("$mmb_plugin_dir/lib/google-api-client/Google_Client.php");
2183 require_once("$mmb_plugin_dir/lib/google-api-client/contrib/Google_DriveService.php");
2184
2185 $gdrive_client = new Google_Client();
2186 $gdrive_client->setUseObjects(true);
2187 $gdrive_client->setAccessToken($google_drive_token);
2188
2189 $gdrive_service = new Google_DriveService($gdrive_client);
2190
2191 try {
2192 $about = $gdrive_service->about->get();
2193 $root_folder_id = $about->getRootFolderId();
2194 } catch (Exception $e) {
2195 return array(
2196 'error' => $e->getMessage(),
2197 );
2198 }
2199
2200 try {
2201 $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$google_drive_directory' and '$root_folder_id' in parents and trashed = false"));
2202 $files = $list_files->getItems();
2203 } catch (Exception $e) {
2204 return array(
2205 'error' => $e->getMessage(),
2206 );
2207 }
2208 if (isset($files[0])) {
2209 $managewp_folder = $files[0];
2210 }
2211
2212 if (!isset($managewp_folder)) {
2213 try {
2214 $_managewp_folder = new Google_DriveFile();
2215 $_managewp_folder->setTitle($google_drive_directory);
2216 $_managewp_folder->setMimeType('application/vnd.google-apps.folder');
2217
2218 if ($root_folder_id != null) {
2219 $parent = new Google_ParentReference();
2220 $parent->setId($root_folder_id);
2221 $_managewp_folder->setParents(array($parent));
2222 }
2223
2224 $managewp_folder = $gdrive_service->files->insert($_managewp_folder, array());
2225 } catch (Exception $e) {
2226 return array(
2227 'error' => $e->getMessage(),
2228 );
2229 }
2230 }
2231
2232 if ($google_drive_site_folder) {
2233 try {
2234 $subfolder_title = $this->site_name;
2235 $managewp_folder_id = $managewp_folder->getId();
2236 $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$subfolder_title' and '$managewp_folder_id' in parents and trashed = false"));
2237 $files = $list_files->getItems();
2238 } catch (Exception $e) {
2239 return array(
2240 'error' => $e->getMessage(),
2241 );
2242 }
2243 if (isset($files[0])) {
2244 $backup_folder = $files[0];
2245 } else {
2246 try {
2247 $_backup_folder = new Google_DriveFile();
2248 $_backup_folder->setTitle($subfolder_title);
2249 $_backup_folder->setMimeType('application/vnd.google-apps.folder');
2250
2251 if (isset($managewp_folder)) {
2252 $_backup_folder->setParents(array($managewp_folder));
2253 }
2254
2255 $backup_folder = $gdrive_service->files->insert($_backup_folder, array());
2256 } catch (Exception $e) {
2257 return array(
2258 'error' => $e->getMessage(),
2259 );
2260 }
2261 }
2262 } else {
2263 $backup_folder = $managewp_folder;
2264 }
2265
2266 $file_path = explode('/', $backup_file);
2267 $new_file = new Google_DriveFile();
2268 $new_file->setTitle(end($file_path));
2269 $new_file->setDescription('Backup file of site: ' . $this->site_name . '.');
2270
2271 if ($backup_folder != null) {
2272 $new_file->setParents(array($backup_folder));
2273 }
2274
2275 $tries = 1;
2276
2277 while($tries <= 2) {
2278 try {
2279 $data = file_get_contents($backup_file);
2280
2281 $createdFile = $gdrive_service->files->insert($new_file, array(
2282 'data' => $data,
2283 ));
2284
2285 break;
2286 } catch (Exception $e) {
2287 if ($e->getCode() >= 500 && $e->getCode() <= 504 && $mmb_gdrive_upload_tries <= 2) {
2288 sleep(2);
2289 $tries++;
2290 } else {
2291 return array(
2292 'error' => $e->getMessage(),
2293 );
2294 }
2295 }
2296 }
2297
2298 return true;
2299 }
2300
2301 /**
2302 * Deletes backup file from Google Drive.
2303 *
2304 * @param array $args arguments passed to the function
2305 * [google_drive_token] -> user's Google drive token in json form
2306 * [google_drive_directory] -> folder on user's Google Drive account which backup file should be deleted from
2307 * [google_drive_site_folder] -> subfolder with site name in google_drive_directory which backup file should be deleted from
2308 * [backup_file] -> absolute path of backup file on local server
2309 * @return void
2310 */
2311 function remove_google_drive_backup($args) {
2312 extract($args);
2313
2314 global $mmb_plugin_dir;
2315 require_once("$mmb_plugin_dir/lib/google-api-client/Google_Client.php");
2316 require_once("$mmb_plugin_dir/lib/google-api-client/contrib/Google_DriveService.php");
2317
2318 try {
2319 $gdrive_client = new Google_Client();
2320 $gdrive_client->setUseObjects(true);
2321 $gdrive_client->setAccessToken($google_drive_token);
2322 } catch (Exception $e) {
2323 $this->_log($e->getMessage());
2324 /*eturn array(
2325 'error' => $e->getMessage(),
2326 );*/
2327 }
2328
2329 $gdrive_service = new Google_DriveService($gdrive_client);
2330
2331 try {
2332 $about = $gdrive_service->about->get();
2333 $root_folder_id = $about->getRootFolderId();
2334 } catch (Exception $e) {
2335 $this->_log($e->getMessage());
2336 /*return array(
2337 'error' => $e->getMessage(),
2338 );*/
2339 }
2340
2341 try {
2342 $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$google_drive_directory' and '$root_folder_id' in parents and trashed = false"));
2343 $files = $list_files->getItems();
2344 } catch (Exception $e) {
2345 $this->_log($e->getMessage());
2346 /*return array(
2347 'error' => $e->getMessage(),
2348 );*/
2349 }
2350 if (isset($files[0])) {
2351 $managewp_folder = $files[0];
2352 } else {
2353 $this->_log("This file does not exist.");
2354 /*return array(
2355 'error' => "This file does not exist.",
2356 );*/
2357 }
2358
2359 if ($google_drive_site_folder) {
2360 try {
2361 $subfolder_title = $this->site_name;
2362 $managewp_folder_id = $managewp_folder->getId();
2363 $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$subfolder_title' and '$managewp_folder_id' in parents and trashed = false"));
2364 $files = $list_files->getItems();
2365 } catch (Exception $e) {
2366 $this->_log($e->getMessage());
2367 /*return array(
2368 'error' => $e->getMessage(),
2369 );*/
2370 }
2371 if (isset($files[0])) {
2372 $backup_folder = $files[0];
2373 }
2374 } else {
2375 $backup_folder = $managewp_folder;
2376 }
2377
2378 if (isset($backup_folder)) {
2379 try {
2380 $backup_folder_id = $backup_folder->getId();
2381 $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$backup_file' and '$backup_folder_id' in parents and trashed = false"));
2382 $files = $list_files->getItems();;
2383 } catch (Exception $e) {
2384 $this->_log($e->getMessage());
2385 /*return array(
2386 'error' => $e->getMessage(),
2387 );*/
2388 }
2389 if (isset($files[0])) {
2390 try {
2391 $gdrive_service->files->delete($files[0]->getId());
2392 } catch (Exception $e) {
2393 $this->_log($e->getMessage());
2394 /*return array(
2395 'error' => $e->getMessage(),
2396 );*/
2397 }
2398 } else {
2399 $this->_log("This file does not exist.");
2400 /*return array(
2401 'error' => "This file does not exist.",
2402 );*/
2403 }
2404 } else {
2405 $this->_log("This file does not exist.");
2406 /*return array(
2407 'error' => "This file does not exist.",
2408 );*/
2409 }
2410
2411 //return true;
2412 }
2413
2414 /**
2415 * Downloads backup file from Google Drive to root folder on local server.
2416 *
2417 * @param array $args arguments passed to the function
2418 * [google_drive_token] -> user's Google drive token in json form
2419 * [google_drive_directory] -> folder on user's Google Drive account which backup file should be downloaded from
2420 * [google_drive_site_folder] -> subfolder with site name in google_drive_directory which backup file should be downloaded from
2421 * [backup_file] -> absolute path of backup file on local server
2422 * @return bool|array absolute path to downloaded file is successful, array with error message if not
2423 */
2424 function get_google_drive_backup($args) {
2425 extract($args);
2426
2427 global $mmb_plugin_dir;
2428 require_once("$mmb_plugin_dir/lib/google-api-client/Google_Client.php");
2429 require_once("$mmb_plugin_dir/lib/google-api-client/contrib/Google_DriveService.php");
2430
2431 try {
2432 $gdrive_client = new Google_Client();
2433 $gdrive_client->setUseObjects(true);
2434 $gdrive_client->setAccessToken($google_drive_token);
2435 } catch (Exception $e) {
2436 return array(
2437 'error' => $e->getMessage(),
2438 );
2439 }
2440
2441 $gdrive_service = new Google_DriveService($gdrive_client);
2442
2443 try {
2444 $about = $gdrive_service->about->get();
2445 $root_folder_id = $about->getRootFolderId();
2446 } catch (Exception $e) {
2447 return array(
2448 'error' => $e->getMessage(),
2449 );
2450 }
2451
2452 try {
2453 $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$google_drive_directory' and '$root_folder_id' in parents and trashed = false"));
2454 $files = $list_files->getItems();
2455 } catch (Exception $e) {
2456 return array(
2457 'error' => $e->getMessage(),
2458 );
2459 }
2460 if (isset($files[0])) {
2461 $managewp_folder = $files[0];
2462 } else {
2463 return array(
2464 'error' => "This file does not exist.",
2465 );
2466 }
2467
2468 if ($google_drive_site_folder) {
2469 try {
2470 $subfolder_title = $this->site_name;
2471 $managewp_folder_id = $managewp_folder->getId();
2472 $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$subfolder_title' and '$managewp_folder_id' in parents and trashed = false"));
2473 $files = $list_files->getItems();
2474 } catch (Exception $e) {
2475 return array(
2476 'error' => $e->getMessage(),
2477 );
2478 }
2479 if (isset($files[0])) {
2480 $backup_folder = $files[0];
2481 }
2482 } else {
2483 $backup_folder = $managewp_folder;
2484 }
2485
2486 if (isset($backup_folder)) {
2487 try {
2488 $backup_folder_id = $backup_folder->getId();
2489 $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$backup_file' and '$backup_folder_id' in parents and trashed = false"));
2490 $files = $list_files->getItems();
2491 } catch (Exception $e) {
2492 return array(
2493 'error' => $e->getMessage(),
2494 );
2495 }
2496 if (isset($files[0])) {
2497 try {
2498 $download_url = $files[0]->getDownloadUrl();
2499 if ($download_url) {
2500 $request = new Google_HttpRequest($download_url, 'GET', null, null);
2501 $http_request = Google_Client::$io->authenticatedRequest($request);
2502 if ($http_request->getResponseHttpCode() == 200) {
2503 $stream = $http_request->getResponseBody();
2504 $local_destination = ABSPATH . 'mwp_temp_backup.zip';
2505 $handle = @fopen($local_destination, 'w+');
2506 $result = fwrite($handle, $stream);
2507 fclose($handle);
2508 if($result)
2509 return $local_destination;
2510 else
2511 return array(
2512 'error' => "Write permission error.",
2513 );
2514 } else {
2515 return array(
2516 'error' => "This file does not exist.",
2517 );
2518 }
2519 } else {
2520 return array(
2521 'error' => "This file does not exist.",
2522 );
2523 }
2524 } catch (Exception $e) {
2525 return array(
2526 'error' => $e->getMessage(),
2527 );
2528 }
2529 } else {
2530 return array(
2531 'error' => "This file does not exist.",
2532 );
2533 }
2534 } else {
2535 return array(
2536 'error' => "This file does not exist.",
2537 );
2538 }
2539
2540 return false;
2541 }
2542
2543 /**
2544 * Schedules the next execution of some backup task.
2545 *
2546 * @param string $type daily, weekly or monthly
2547 * @param string $schedule format: task_time (if daily), task_time|task_day (if weekly), task_time|task_date (if monthly)
2548 * @return bool|int timestamp if sucessful, false if not
2549 */
2550 function schedule_next($type, $schedule) {
2551 $schedule = explode("|", $schedule);
2552
2553 if (empty($schedule))
2554 return false;
2555 switch ($type) {
2556 case 'daily':
2557 if (isset($schedule[1]) && $schedule[1]) {
2558 $delay_time = $schedule[1] * 60;
2559 }
2560
2561 $current_hour = date("H");
2562 $schedule_hour = $schedule[0];
2563 if ($current_hour >= $schedule_hour)
2564 $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 1, date("Y"));
2565 else
2566 $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
2567 break;
2568
2569 case 'weekly':
2570 if (isset($schedule[2]) && $schedule[2]) {
2571 $delay_time = $schedule[2] * 60;
2572 }
2573 $current_weekday = date('w');
2574 $schedule_weekday = $schedule[1];
2575 $current_hour = date("H");
2576 $schedule_hour = $schedule[0];
2577
2578 if ($current_weekday > $schedule_weekday)
2579 $weekday_offset = 7 - ($week_day - $task_schedule[1]);
2580 else
2581 $weekday_offset = $schedule_weekday - $current_weekday;
2582
2583 if (!$weekday_offset) { //today is scheduled weekday
2584 if ($current_hour >= $schedule_hour)
2585 $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 7, date("Y"));
2586 else
2587 $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
2588 } else {
2589 $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + $weekday_offset, date("Y"));
2590 }
2591 break;
2592
2593 case 'monthly':
2594 if (isset($schedule[2]) && $schedule[2]) {
2595 $delay_time = $schedule[2] * 60;
2596 }
2597 $current_monthday = date('j');
2598 $schedule_monthday = $schedule[1];
2599 $current_hour = date("H");
2600 $schedule_hour = $schedule[0];
2601
2602 if ($current_monthday > $schedule_monthday) {
2603 $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
2604 } else if ($current_monthday < $schedule_monthday) {
2605 $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
2606 } else if ($current_monthday == $schedule_monthday) {
2607 if ($current_hour >= $schedule_hour)
2608 $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
2609 else
2610 $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
2611 break;
2612 }
2613
2614 break;
2615
2616 default:
2617 break;
2618 }
2619
2620 if (isset($delay_time) && $delay_time) {
2621 $time += $delay_time;
2622 }
2623
2624 return $time;
2625 }
2626
2627 /**
2628 * Parse task arguments for info on master.
2629 *
2630 * @return mixed associative array with stats for every backup task or error if backup is manually deleted on server
2631 */
2632 function get_backup_stats() {
2633 $stats = array();
2634 $tasks = $this->tasks;
2635 if (is_array($tasks) && !empty($tasks)) {
2636 foreach ($tasks as $task_name => $info) {
2637 if (is_array($info['task_results']) && !empty($info['task_results'])) {
2638 foreach ($info['task_results'] as $key => $result) {
2639 if (isset($result['server']) && !isset($result['error'])) {
2640 if (isset($result['server']['file_path']) && !$info['task_args']['del_host_file']) {
2641 if (!file_exists($result['server']['file_path'])) {
2642 $info['task_results'][$key]['error'] = 'Backup created but manually removed from server.';
2643 }
2644 }
2645 }
2646 }
2647 }
2648 if (is_array($info['task_results']))
2649 $stats[$task_name] = array_values($info['task_results']);
2650 }
2651 }
2652 return $stats;
2653 }
2654
2655 /**
2656 * Returns all backup tasks with information when the next schedule will be.
2657 *
2658 * @return mixed associative array with timestamp with next schedule for every backup task
2659 */
2660 function get_next_schedules() {
2661 $stats = array();
2662 $tasks = $this->tasks;
2663 if (is_array($tasks) && !empty($tasks)) {
2664 foreach ($tasks as $task_name => $info) {
2665 $stats[$task_name] = isset($info['task_args']['next']) ? $info['task_args']['next'] : array();
2666 }
2667 }
2668 return $stats;
2669 }
2670
2671 /**
2672 * Deletes all old backups from local server.
2673 * It depends on configuration on master (Number of backups to keep).
2674 *
2675 * @param string $task_name name of backup task
2676 * @return bool|void true if there are backups for deletion, void if not
2677 */
2678 function remove_old_backups($task_name) {
2679 //Check for previous failed backups first
2680 $this->cleanup();
2681
2682 //Remove by limit
2683 $backups = $this->tasks;
2684 if ($task_name == 'Backup Now') {
2685 $num = 0;
2686 } else {
2687 $num = 1;
2688 }
2689
2690 if ((count($backups[$task_name]['task_results']) - $num) >= $backups[$task_name]['task_args']['limit']) {
2691 //how many to remove ?
2692 $remove_num = (count($backups[$task_name]['task_results']) - $num - $backups[$task_name]['task_args']['limit']) + 1;
2693 for ($i = 0; $i < $remove_num; $i++) {
2694 //Remove from the server
2695 if (isset($backups[$task_name]['task_results'][$i]['server'])) {
2696 @unlink($backups[$task_name]['task_results'][$i]['server']['file_path']);
2697 }
2698
2699 //Remove from ftp
2700 if (isset($backups[$task_name]['task_results'][$i]['ftp']) && isset($backups[$task_name]['task_args']['account_info']['mwp_ftp'])) {
2701 $ftp_file = $backups[$task_name]['task_results'][$i]['ftp'];
2702 $args = $backups[$task_name]['task_args']['account_info']['mwp_ftp'];
2703 $args['backup_file'] = $ftp_file;
2704 $this->remove_ftp_backup($args);
2705 }
2706
2707 if (isset($backups[$task_name]['task_results'][$i]['amazons3']) && isset($backups[$task_name]['task_args']['account_info']['mwp_amazon_s3'])) {
2708 $amazons3_file = $backups[$task_name]['task_results'][$i]['amazons3'];
2709 $args = $backups[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
2710 $args['backup_file'] = $amazons3_file;
2711 $this->remove_amazons3_backup($args);
2712 }
2713
2714 if (isset($backups[$task_name]['task_results'][$i]['dropbox']) && isset($backups[$task_name]['task_args']['account_info']['mwp_dropbox'])) {
2715 //To do: dropbox remove
2716 $dropbox_file = $backups[$task_name]['task_results'][$i]['dropbox'];
2717 $args = $backups[$task_name]['task_args']['account_info']['mwp_dropbox'];
2718 $args['backup_file'] = $dropbox_file;
2719 $this->remove_dropbox_backup($args);
2720 }
2721
2722 if (isset($backups[$task_name]['task_results'][$i]['google_drive']) && isset($backups[$task_name]['task_args']['account_info']['mwp_google_drive'])) {
2723 $google_drive_file = $backups[$task_name]['task_results'][$i]['google_drive'];
2724 $args = $backups[$task_name]['task_args']['account_info']['mwp_google_drive'];
2725 $args['backup_file'] = $google_drive_file;
2726 $this->remove_google_drive_backup($args);
2727 }
2728
2729 //Remove database backup info
2730 unset($backups[$task_name]['task_results'][$i]);
2731 } //end foreach
2732
2733 if (is_array($backups[$task_name]['task_results']))
2734 $backups[$task_name]['task_results'] = array_values($backups[$task_name]['task_results']);
2735 else
2736 $backups[$task_name]['task_results']=array();
2737
2738 $this->update_tasks($backups);
2739
2740 return true;
2741 }
2742 }
2743
2744 /**
2745 * Deletes specified backup.
2746 *
2747 * @param array $args arguments passed to function
2748 * [task_name] -> name of backup task
2749 * [result_id] -> id of baskup task result, which should be restored
2750 * [google_drive_token] -> json of Google Drive token, if it is remote destination
2751 * @return bool true if successful, false if not
2752 */
2753 function delete_backup($args) {
2754 if (empty($args))
2755 return false;
2756 extract($args);
2757 if (isset($google_drive_token)) {
2758 $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
2759 }
2760
2761 $tasks = $this->tasks;
2762 $task = $tasks[$task_name];
2763 $backups = $task['task_results'];
2764 $backup = $backups[$result_id];
2765
2766 if (isset($backup['server'])) {
2767 @unlink($backup['server']['file_path']);
2768 }
2769
2770 //Remove from ftp
2771 if (isset($backup['ftp'])) {
2772 $ftp_file = $backup['ftp'];
2773 $args = $tasks[$task_name]['task_args']['account_info']['mwp_ftp'];
2774 $args['backup_file'] = $ftp_file;
2775 $this->remove_ftp_backup($args);
2776 }
2777
2778 if (isset($backup['amazons3'])) {
2779 $amazons3_file = $backup['amazons3'];
2780 $args = $tasks[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
2781 $args['backup_file'] = $amazons3_file;
2782 $this->remove_amazons3_backup($args);
2783 }
2784
2785 if (isset($backup['dropbox'])) {
2786 $dropbox_file = $backup['dropbox'];
2787 $args = $tasks[$task_name]['task_args']['account_info']['mwp_dropbox'];
2788 $args['backup_file'] = $dropbox_file;
2789 $this->remove_dropbox_backup($args);
2790 }
2791
2792 if (isset($backup['google_drive'])) {
2793 $google_drive_file = $backup['google_drive'];
2794 $args = $tasks[$task_name]['task_args']['account_info']['mwp_google_drive'];
2795 $args['backup_file'] = $google_drive_file;
2796 $this->remove_google_drive_backup($args);
2797 }
2798
2799 unset($backups[$result_id]);
2800
2801 if (count($backups)) {
2802 $tasks[$task_name]['task_results'] = $backups;
2803 } else {
2804 unset($tasks[$task_name]['task_results']);
2805 }
2806
2807 $this->update_tasks($tasks);
2808 //update_option('mwp_backup_tasks', $tasks);
2809 return true;
2810 }
2811
2812 /**
2813 * Deletes all unneeded files produced by backup process.
2814 *
2815 * @return array array of deleted files
2816 */
2817 function cleanup() {
2818 $tasks = $this->tasks;
2819 $backup_folder = WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups/';
2820 $backup_folder_new = MWP_BACKUP_DIR . '/';
2821 $files = glob($backup_folder . "*");
2822 $new = glob($backup_folder_new . "*");
2823
2824 //Failed db files first
2825 $db_folder = MWP_DB_DIR . '/';
2826 $db_files = glob($db_folder . "*");
2827 if (is_array($db_files) && !empty($db_files)) {
2828 foreach ($db_files as $file) {
2829 @unlink($file);
2830 }
2831 @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
2832 @rmdir(MWP_DB_DIR);
2833 }
2834
2835 //clean_old folder?
2836 if ((isset($files[0]) && basename($files[0]) == 'index.php' && count($files) == 1) || (empty($files))) {
2837 foreach ($files as $file) {
2838 @unlink($file);
2839 }
2840 @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups');
2841 @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker'));
2842 }
2843
2844 foreach ($new as $b) {
2845 $files[] = $b;
2846 }
2847 $deleted = array();
2848
2849 if (is_array($files) && count($files)) {
2850 $results = array();
2851 if (!empty($tasks)) {
2852 foreach ((array) $tasks as $task) {
2853 if (isset($task['task_results']) && count($task['task_results'])) {
2854 foreach ($task['task_results'] as $backup) {
2855 if (isset($backup['server'])) {
2856 $results[] = $backup['server']['file_path'];
2857 }
2858 }
2859 }
2860 }
2861 }
2862
2863 $num_deleted = 0;
2864 foreach ($files as $file) {
2865 if (!in_array($file, $results) && basename($file) != 'index.php') {
2866 @unlink($file);
2867 $deleted[] = basename($file);
2868 $num_deleted++;
2869 }
2870 }
2871 }
2872
2873 return $deleted;
2874 }
2875
2876 /**
2877 * Uploads to remote destination in the second step, invoked from master.
2878 *
2879 * @param array $args arguments passed to function
2880 * [task_name] -> name of backup task
2881 * @return array|void void if success, array with error message if not
2882 */
2883 function remote_backup_now($args) {
2884 $this->set_memory();
2885 if (!empty($args))
2886 extract($args);
2887
2888 $tasks = $this->tasks;
2889 $task = $tasks[$task_name];
2890
2891 if (!empty($task)) {
2892 extract($task['task_args']);
2893 }
2894
2895 $results = $task['task_results'];
2896
2897 if (is_array($results) && count($results)) {
2898 $backup_file = $results[count($results) - 1]['server']['file_path'];
2899 }
2900
2901 if ($backup_file && file_exists($backup_file)) {
2902 //FTP, Amazon S3, Dropbox or Google Drive
2903 if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
2904 $this->update_status($task_name, $this->statuses['ftp']);
2905 $account_info['mwp_ftp']['backup_file'] = $backup_file;
2906 $return = $this->ftp_backup($account_info['mwp_ftp']);
2907 if (!(is_array($return) && isset($return['error']))) {
2908 $this->update_status($task_name, $this->statuses['ftp'], true);
2909 $this->update_status($task_name,$this->statuses['finished'], true);
2910 }
2911 }
2912
2913 if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
2914 $this->update_status($task_name, $this->statuses['s3']);
2915 $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
2916 $return = $this->amazons3_backup($account_info['mwp_amazon_s3']);
2917 if (!(is_array($return) && isset($return['error']))) {
2918 $this->update_status($task_name, $this->statuses['s3'], true);
2919 $this->update_status($task_name,$this->statuses['finished'], true);
2920 }
2921 }
2922
2923 if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
2924 $this->update_status($task_name, $this->statuses['dropbox']);
2925 $account_info['mwp_dropbox']['backup_file'] = $backup_file;
2926 $return = $this->dropbox_backup($account_info['mwp_dropbox']);
2927 if (!(is_array($return) && isset($return['error']))) {
2928 $this->update_status($task_name, $this->statuses['dropbox'], true);
2929 $this->update_status($task_name,$this->statuses['finished'], true);
2930 }
2931 }
2932
2933 if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
2934 $this->update_status($task_name, $this->statuses['email']);
2935 $account_info['mwp_email']['file_path'] = $backup_file;
2936 $return = $this->email_backup($account_info['mwp_email']);
2937 if (!(is_array($return) && isset($return['error']))) {
2938 $this->update_status($task_name, $this->statuses['email'], true);
2939 $this->update_status($task_name,$this->statuses['finished'], true);
2940 }
2941 }
2942
2943 if (isset($account_info['mwp_google_drive']) && !empty($account_info['mwp_google_drive'])) {
2944 $this->update_status($task_name, $this->statuses['google_drive']);
2945 $account_info['mwp_google_drive']['backup_file'] = $backup_file;
2946 $return = $this->google_drive_backup($account_info['mwp_google_drive']);
2947 if (!(is_array($return) && isset($return['error']))) {
2948 $this->update_status($task_name, $this->statuses['google_drive'], true);
2949 $this->update_status($task_name,$this->statuses['finished'], true);
2950 }
2951 }
2952
2953 $tasks = $this->tasks;
2954 @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
2955 if ($return == true && $del_host_file) {
2956 @unlink($backup_file);
2957 unset($tasks[$task_name]['task_results'][count($tasks[$task_name]['task_results']) - 1]['server']);
2958 }
2959 $this->update_tasks($tasks);
2960 } else {
2961 $return = array(
2962 'error' => 'Backup file not found on your server. Please try again.'
2963 );
2964 }
2965
2966 return $return;
2967 }
2968
2969 /**
2970 * Checks if scheduled backup tasks should be executed.
2971 *
2972 * @param array $args arguments passed to function
2973 * [task_name] -> name of backup task
2974 * [task_id] -> id of backup task
2975 * [$site_key] -> hash key of backup task
2976 * [worker_version] -> version of worker
2977 * [mwp_google_drive_refresh_token] -> should be Google Drive token be refreshed, true if it is remote destination of task
2978 * @param string $url url on master where worker validate task
2979 * @return string|array|boolean
2980 */
2981 function validate_task($args, $url) {
2982 if (!class_exists('WP_Http')) {
2983 include_once(ABSPATH . WPINC . '/class-http.php');
2984 }
2985
2986 $worker_upto_3_9_22 = (MMB_WORKER_VERSION <= '3.9.22'); // worker version is less or equals to 3.9.22
2987 $params = array('timeout'=>100);
2988 $params['body'] = $args;
2989 $result = wp_remote_post($url, $params);
2990
2991 if ($worker_upto_3_9_22) {
2992 if (is_array($result) && $result['body'] == 'mwp_delete_task') {
2993 //$tasks = $this->get_backup_settings();
2994 $tasks = $this->tasks;
2995 $this->update_tasks($tasks);
2996 $this->cleanup();
2997 exit;
2998 } elseif(is_array($result) && $result['body'] == 'mwp_pause_task'){
2999 return 'paused';
3000 } elseif(is_array($result) && substr($result['body'], 0, 8) == 'token - '){
3001 return $result['body'];
3002 }
3003 } else {
3004 if (is_array($result) && $result['body']) {
3005 $response = unserialize($result['body']);
3006 if ($response['message'] == 'mwp_delete_task') {
3007 $tasks = $this->tasks;
3008 $this->update_tasks($tasks);
3009 $this->cleanup();
3010 exit;
3011 } elseif ($response['message'] == 'mwp_pause_task') {
3012 return 'paused';
3013 } elseif ($response['message'] == 'mwp_do_task') {
3014 return $response;
3015 }
3016 }
3017 }
3018
3019 return false;
3020 }
3021
3022 /**
3023 * Updates status of backup task.
3024 * Positive number if completed, negative if not.
3025 *
3026 * @param string $task_name name of backup task
3027 * @param int $status status which tasks should be updated to
3028 * (
3029 * 0 - Backup started,
3030 * 1 - DB dump,
3031 * 2 - DB ZIP,
3032 * 3 - Files ZIP,
3033 * 4 - Amazon S3,
3034 * 5 - Dropbox,
3035 * 6 - FTP,
3036 * 7 - Email,
3037 * 8 - Google Drive,
3038 * 100 - Finished
3039 * )
3040 * @param bool $completed completed or not
3041 * @return void
3042 */
3043 function update_status($task_name, $status, $completed = false) {
3044 if ($task_name != 'Backup Now') {
3045 $tasks = $this->tasks;
3046 $index = count($tasks[$task_name]['task_results']) - 1;
3047 if (!is_array($tasks[$task_name]['task_results'][$index]['status'])) {
3048 $tasks[$task_name]['task_results'][$index]['status'] = array();
3049 }
3050 if (!$completed) {
3051 $tasks[$task_name]['task_results'][$index]['status'][] = (int) $status * (-1);
3052 } else {
3053 $status_index = count($tasks[$task_name]['task_results'][$index]['status']) - 1;
3054 $tasks[$task_name]['task_results'][$index]['status'][$status_index] = abs($tasks[$task_name]['task_results'][$index]['status'][$status_index]);
3055 }
3056
3057 $this->update_tasks($tasks);
3058 //update_option('mwp_backup_tasks',$tasks);
3059 }
3060 }
3061
3062 /**
3063 * Update $this->tasks attribute and save it to wp_options with key mwp_backup_tasks.
3064 *
3065 * @param mixed $tasks associative array with all tasks data
3066 * @return void
3067 */
3068 function update_tasks($tasks) {
3069 $this->tasks = $tasks;
3070 update_option('mwp_backup_tasks', $tasks);
3071 }
3072
3073 /**
3074 * Reconnects to database to avoid timeout problem after ZIP files.
3075 *
3076 * @return void
3077 */
3078 function wpdb_reconnect() {
3079 global $wpdb;
3080
3081 if(class_exists('wpdb') && function_exists('wp_set_wpdb_vars')){
3082 @mysql_close($wpdb->dbh);
3083 $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
3084 wp_set_wpdb_vars();
3085 }
3086 }
3087
3088 /**
3089 * Replaces .htaccess file in process of restoring WordPress site.
3090 *
3091 * @param string $url url of current site
3092 * @return void
3093 */
3094 function replace_htaccess($url) {
3095 $file = @file_get_contents(ABSPATH.'.htaccess');
3096 if ($file && strlen($file)) {
3097 $args = parse_url($url);
3098 $string = rtrim($args['path'], "/");
3099 $regex = "/BEGIN WordPress(.*?)RewriteBase(.*?)\n(.*?)RewriteRule \.(.*?)index\.php(.*?)END WordPress/sm";
3100 $replace = "BEGIN WordPress$1RewriteBase " . $string . "/ \n$3RewriteRule . " . $string . "/index.php$5END WordPress";
3101 $file = preg_replace($regex, $replace, $file);
3102 @file_put_contents(ABSPATH.'.htaccess', $file);
3103 }
3104 }
3105
3106 /**
3107 * Removes cron for checking scheduled tasks, if there are not any scheduled task.
3108 *
3109 * @return void
3110 */
3111 function check_cron_remove() {
3112 if(empty($this->tasks) || (count($this->tasks) == 1 && isset($this->tasks['Backup Now'])) ){
3113 wp_clear_scheduled_hook('mwp_backup_tasks');
3114 exit;
3115 }
3116 }
3117
3118 /**
3119 * Readd tasks on new website add.
3120 *
3121 * @param array $params arguments passed to function
3122 * @return array $params without backups
3123 */
3124 public static function readd_tasks($params = array()) {
3125 global $mmb_core;
3126
3127 if( empty($params) || !isset($params['backups']) )
3128 return $params;
3129
3130 $before = array();
3131 $tasks = $params['backups'];
3132 if( !empty($tasks) ){
3133 $mmb_backup = new MMB_Backup();
3134
3135 if( function_exists( 'wp_next_scheduled' ) ){
3136 if ( !wp_next_scheduled('mwp_backup_tasks') ) {
3137 wp_schedule_event( time(), 'tenminutes', 'mwp_backup_tasks' );
3138 }
3139 }
3140
3141 foreach( $tasks as $task ){
3142 $before[$task['task_name']] = array();
3143
3144 if(isset($task['secure'])){
3145 if($decrypted = $mmb_core->_secure_data($task['secure'])){
3146 $decrypted = maybe_unserialize($decrypted);
3147 if(is_array($decrypted)){
3148 foreach($decrypted as $key => $val){
3149 if(!is_numeric($key))
3150 $task[$key] = $val;
3151 }
3152 unset($task['secure']);
3153 } else
3154 $task['secure'] = $decrypted;
3155 }
3156
3157 }
3158 if (isset($task['account_info']) && is_array($task['account_info'])) { //only if sends from master first time(secure data)
3159 $task['args']['account_info'] = $task['account_info'];
3160 }
3161
3162 $before[$task['task_name']]['task_args'] = $task['args'];
3163 $before[$task['task_name']]['task_args']['next'] = $mmb_backup->schedule_next($task['args']['type'], $task['args']['schedule']);
3164 }
3165 }
3166 update_option('mwp_backup_tasks', $before);
3167
3168 unset($params['backups']);
3169 return $params;
3170 }
3171
3172 /**
3173 * Upload to remote destination in the second step for scheduled backup run by cron.
3174 *
3175 * @param string $task_name name of backup task
3176 * @param string $backup_file absolute path of local backup archive
3177 * @param bool $del_host_file should be deleted local backup archive or not
3178 * @return void
3179 */
3180 function remote_upload($task_name, $backup_file, $del_host_file) {
3181 $this->set_memory();
3182
3183 $tasks = $this->tasks;
3184 $task = $tasks[$task_name];
3185
3186 if (!empty($task)) {
3187 extract($task['task_args']);
3188 }
3189
3190 if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
3191 $this->update_status($task_name, $this->statuses['ftp']);
3192 $account_info['mwp_ftp']['backup_file'] = $backup_file;
3193 $ftp_result = $this->ftp_backup($account_info['mwp_ftp']);
3194 if ($ftp_result !== true && $del_host_file) {
3195 @unlink($backup_file);
3196 }
3197 if (!(is_array($ftp_result) && isset($ftp_result['error']))) {
3198 $this->update_status($task_name, $this->statuses['ftp'], true);
3199 $this->update_status($task_name,$this->statuses['finished'], true);
3200 }
3201 }
3202
3203 if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
3204 $this->update_status($task_name, $this->statuses['s3']);
3205 $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
3206 $amazons3_result = $this->amazons3_backup($account_info['mwp_amazon_s3']);
3207 if ($amazons3_result !== true && $del_host_file) {
3208 @unlink($backup_file);
3209 }
3210 if (!(is_array($amazons3_result) && isset($amazons3_result['error']))) {
3211 $this->update_status($task_name, $this->statuses['s3'], true);
3212 $this->update_status($task_name,$this->statuses['finished'], true);
3213 }
3214 }
3215
3216 if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
3217 $this->update_status($task_name, $this->statuses['dropbox']);
3218 $account_info['mwp_dropbox']['backup_file'] = $backup_file;
3219 $dropbox_result = $this->dropbox_backup($account_info['mwp_dropbox']);
3220 if ($dropbox_result !== true && $del_host_file) {
3221 @unlink($backup_file);
3222 }
3223 if (!(is_array($dropbox_result) && isset($dropbox_result['error']))) {
3224 $this->update_status($task_name, $this->statuses['dropbox'], true);
3225 $this->update_status($task_name,$this->statuses['finished'], true);
3226 }
3227 }
3228
3229 if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
3230 $this->update_status($task_name, $this->statuses['email']);
3231 $account_info['mwp_email']['task_name'] = $task_name;
3232 $account_info['mwp_email']['file_path'] = $backup_file;
3233 $email_result = $this->email_backup($account_info['mwp_email']);
3234 if (!(is_array($email_result) && isset($email_result['error']))) {
3235 $this->update_status($task_name, $this->statuses['email'], true);
3236 $this->update_status($task_name,$this->statuses['finished'], true);
3237 }
3238 }
3239
3240 if (isset($account_info['mwp_google_drive']) && !empty($account_info['mwp_google_drive'])) {
3241 $this->update_status($task_name, $this->statuses['google_drive']);
3242 $account_info['mwp_google_drive']['backup_file'] = $backup_file;
3243 $google_drive_result = $this->google_drive_backup($account_info['mwp_google_drive']);
3244 if ($google_drive_result !== true && $del_host_file) {
3245 @unlink($backup_file);
3246 }
3247 if (!(is_array($google_drive_result) && isset($google_drive_result['error']))) {
3248 $this->update_status($task_name, $this->statuses['google_drive'], true);
3249 $this->update_status($task_name,$this->statuses['finished'], true);
3250 }
3251 }
3252
3253 $tasks = $this->tasks;
3254 @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
3255 if ($del_host_file) {
3256 @unlink($backup_file);
3257 unset($tasks[$task_name]['task_results'][count($tasks[$task_name]['task_results']) - 1]['server']);
3258 }
3259 $this->update_tasks($tasks);
3260 }
3261
3262 }
3263
3264 if( function_exists('add_filter') ) {
3265 add_filter( 'mwp_website_add', 'MMB_Backup::readd_tasks' );
3266 }
3267
3268 if(!function_exists('get_all_files_from_dir')) {
3269 /**
3270 * Get all files in directory
3271 *
3272 * @param string $path Relative or absolute path to folder
3273 * @param array $exclude List of excluded files or folders, relative to $path
3274 * @return array List of all files in folder $path, exclude all files in $exclude array
3275 */
3276 function get_all_files_from_dir($path, $exclude = array()) {
3277 if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
3278 global $directory_tree, $ignore_array;
3279 $directory_tree = array();
3280 foreach ($exclude as $file) {
3281 if (!in_array($file, array('.', '..'))) {
3282 if ($file[0] === "/") $path = substr($file, 1);
3283 $ignore_array[] = "$path/$file";
3284 }
3285 }
3286 get_all_files_from_dir_recursive($path);
3287 return $directory_tree;
3288 }
3289 }
3290
3291 if (!function_exists('get_all_files_from_dir_recursive')) {
3292 /**
3293 * Get all files in directory,
3294 * wrapped function which writes in global variable
3295 * and exclued files or folders are read from global variable
3296 *
3297 * @param string $path Relative or absolute path to folder
3298 * @return void
3299 */
3300 function get_all_files_from_dir_recursive($path) {
3301 if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
3302 global $directory_tree, $ignore_array;
3303 $directory_tree_temp = array();
3304 $dh = @opendir($path);
3305
3306 while (false !== ($file = @readdir($dh))) {
3307 if (!in_array($file, array('.', '..'))) {
3308 if (!in_array("$path/$file", $ignore_array)) {
3309 if (!is_dir("$path/$file")) {
3310 $directory_tree[] = "$path/$file";
3311 } else {
3312 get_all_files_from_dir_recursive("$path/$file");
3313 }
3314 }
3315 }
3316 }
3317 @closedir($dh);
3318 }
3319 }
3320 ?>