PluginProbe
ManageWP Worker / 3.9.13
ManageWP Worker v3.9.13
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.13, at backup.class.php

1,872 lines 68.7 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 define('MWP_BACKUP_DIR', WP_CONTENT_DIR . '/managewp/backups');
13 define('MWP_DB_DIR', MWP_BACKUP_DIR . '/mwp_db');
14
15 $zip_errors = array(
16 'No error',
17 'No error',
18 'Unexpected end of zip file',
19 'A generic error in the zipfile format was detected.',
20 'zip was unable to allocate itself memory',
21 'A severe error in the zipfile format was detected',
22 'Entry too large to be split with zipsplit',
23 'Invalid comment format',
24 'zip -T failed or out of memory',
25 'The user aborted zip prematurely',
26 'zip encountered an error while using a temp file',
27 'Read or seek error',
28 'zip has nothing to do',
29 'Missing or empty zip file',
30 'Error writing to a file',
31 'zip was unable to create a file to write to',
32 'bad command line parameters',
33 'no error',
34 'zip could not open a specified file to read'
35 );
36 $unzip_errors = array(
37 'No error',
38 'One or more warning errors were encountered, but processing completed successfully anyway',
39 'A generic error in the zipfile format was detected',
40 'A severe error in the zipfile format was detected.',
41 'unzip was unable to allocate itself memory.',
42 'unzip was unable to allocate memory, or encountered an encryption error',
43 'unzip was unable to allocate memory during decompression to disk',
44 'unzip was unable allocate memory during in-memory decompression',
45 'unused',
46 'The specified zipfiles were not found',
47 'Bad command line parameters',
48 'No matching files were found',
49 50 => 'The disk is (or was) full during extraction',
50 51 => 'The end of the ZIP archive was encountered prematurely.',
51 80 => 'The user aborted unzip prematurely.',
52 81 => 'Testing or extraction of one or more files failed due to unsupported compression methods or unsupported decryption.',
53 82 => 'No files were found due to bad decryption password(s)'
54 );
55
56
57 class MMB_Backup extends MMB_Core
58 {
59 var $site_name;
60 var $statuses;
61 var $tasks;
62 var $s3;
63 var $ftp;
64 var $dropbox;
65 function __construct()
66 {
67 parent::__construct();
68 $this->site_name = str_replace(array(
69 "_",
70 "/"
71 ), array(
72 "",
73 "-"
74 ), rtrim($this->remove_http(get_bloginfo('url')), "/"));
75 $this->statuses = array(
76 'db_dump' => 1,
77 'db_zip' => 2,
78 'files_zip' => 3,
79 's3' => 4,
80 'dropbox' => 5,
81 'ftp' => 6,
82 'email' => 7,
83 'finished' => 100
84 );
85 $this->tasks = get_option('mwp_backup_tasks');
86 }
87
88 function get_backup_settings()
89 {
90 $backup_settings = get_option('mwp_backup_tasks');
91 if (!empty($backup_settings))
92 return $backup_settings;
93 else
94 return false;
95 }
96
97 function set_backup_task($params)
98 {
99 //$params => [$task_name, $args, $error]
100 if (!empty($params)) {
101 extract($params);
102
103 //$before = $this->get_backup_settings();
104 $before = $this->tasks;
105 if (!$before || empty($before))
106 $before = array();
107
108 if (isset($args['remove'])) {
109 unset($before[$task_name]);
110 $return = array(
111 'removed' => true
112 );
113 } else {
114 if (is_array($params['account_info'])) { //only if sends from master first time(secure data)
115 $args['account_info'] = $account_info;
116 }
117
118 $before[$task_name]['task_args'] = $args;
119 if (strlen($args['schedule']))
120 $before[$task_name]['task_args']['next'] = $this->schedule_next($args['type'], $args['schedule']);
121
122 $return = $before[$task_name];
123 }
124
125 //Update with error
126 if ($error) {
127 if (is_array($error)) {
128 $before[$task_name]['task_results'][count($before[$task_name]['task_results']) - 1]['error'] = $error['error'];
129 } else {
130 $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['error'] = $error;
131 }
132 }
133
134 if ($time) { //set next result time before backup
135 if (is_array($before[$task_name]['task_results'])) {
136 $before[$task_name]['task_results'] = array_values($before[$task_name]['task_results']);
137 }
138 $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['time'] = $time;
139 }
140
141 $this->update_tasks($before);
142 //update_option('mwp_backup_tasks', $before);
143
144 if ($task_name == 'Backup Now') {
145 $result = $this->backup($args, $task_name);
146 $backup_settings = $this->tasks;
147
148 if (is_array($result) && array_key_exists('error', $result)) {
149 $return = $result;
150 } else {
151 $return = $backup_settings[$task_name];
152 }
153 }
154 return $return;
155 }
156 return false;
157 }
158
159 //Cron check
160 function check_backup_tasks()
161 {
162 //$settings = $this->get_backup_settings();
163 $settings = $this->tasks;
164 if (is_array($settings) && !empty($settings)) {
165 foreach ($settings as $task_name => $setting) {
166 if ($setting['task_args']['next'] && $setting['task_args']['next'] < time()) {
167 //if ($setting['task_args']['next'] && $_GET['force_backup']) {
168 if ($setting['task_args']['url'] && $setting['task_args']['task_id'] && $setting['task_args']['site_key']) {
169 //Check orphan task
170 $check_data = array(
171 'task_name' => $task_name,
172 'task_id' => $setting['task_args']['task_id'],
173 'site_key' => $setting['task_args']['site_key']
174 );
175
176 $this->validate_task($check_data, $setting['task_args']['url']);
177 }
178
179 //Update task with next schedule
180 $this->set_backup_task(array(
181 'task_name' => $task_name,
182 'args' => $settings[$task_name]['task_args'],
183 'time' => time()
184 ));
185
186 $result = $this->backup($setting['task_args'], $task_name);
187 $error = '';
188 if (is_array($result) && array_key_exists('error', $result)) {
189 $error = $result;
190 $this->set_backup_task(array(
191 'task_name' => $task_name,
192 'args' => $settings[$task_name]['task_args'],
193 'error' => $error
194 ));
195 } else {
196 $error = '';
197 }
198 break; //Only one backup per cron
199 }
200 }
201 }
202
203 }
204
205
206
207 /*
208 * If Task Name not set then it's manual backup
209 * Backup args:
210 * type -> db, full
211 * what -> daily, weekly, monthly
212 * account_info -> ftp, amazons3, dropbox
213 * exclude-> array of paths to exclude from backup
214 */
215
216 function backup($args, $task_name = false)
217 {
218 if (!$args || empty($args))
219 return false;
220
221 extract($args); //extract settings
222
223 //Try increase memory limit and execution time
224 @ini_set('memory_limit', '256M');
225 @set_time_limit(600); //ten minutes
226
227 //Remove old backup(s)
228 $this->remove_old_backups($task_name);
229
230 $new_file_path = MWP_BACKUP_DIR;
231
232 if (!file_exists($new_file_path)) {
233 if (!mkdir($new_file_path, 0755, true))
234 return array(
235 'error' => 'Permission denied, make sure you have write permission to wp-content folder.'
236 );
237 }
238
239 @file_put_contents($new_file_path . '/index.php', ''); //safe
240
241 //Delete possible broken previous backups - don't need it anymore (works only for previous worker versions)
242 foreach (glob($new_file_path . "/*.zip") as $filename) {
243 $short = basename($filename);
244 preg_match('/^wp\-content(.*)/Ui', $short, $matches);
245 if ($matches)
246 @unlink($filename);
247 }
248
249 //Prepare .zip file name
250 $hash = md5(time());
251 $label = $type ? $type : 'manual';
252 $backup_file = $new_file_path . '/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
253 $backup_url = WP_CONTENT_URL . '/managewp/backups/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
254
255 //Optimize tables?
256 if (isset($optimize_tables) && !empty($optimize_tables)) {
257 $this->optimize_tables();
258 }
259
260 //What to backup - db or full?
261 if (trim($what) == 'db') {
262 //Take database backup
263 $this->update_status($task_name, $this->statuses['db_dump']);
264 $db_result = $this->backup_db();
265 if ($db_result == false) {
266 return array(
267 'error' => 'Failed to backup database.'
268 );
269 } else if (is_array($db_result) && isset($db_result['error'])) {
270 return array(
271 'error' => $db_result['error']
272 );
273 } else {
274 $this->update_status($task_name, $this->statuses['db_dump'], true);
275 $this->update_status($task_name, $this->statuses['db_zip']);
276
277 $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
278 $comp_level = $disable_comp ? '-0' : '-1';
279
280 chdir(MWP_BACKUP_DIR);
281 $zip = $this->get_zip();
282 $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
283 ob_start();
284 $result = $this->mmb_exec($command);
285 ob_get_clean();
286 if (!$result) { // fallback to pclzip
287 define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
288 require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
289 $archive = new PclZip($backup_file);
290 if ($disable_comp) {
291 $result = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION);
292 } else {
293 $result = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR);
294 }
295 @unlink($db_result);
296 @rmdir(MWP_DB_DIR);
297 if (!$result) {
298 return array(
299 'error' => 'Failed to zip database (pclZip - ' . $archive->error_code . '): .' . $archive->error_string
300 );
301 }
302 }
303
304 @unlink($db_result);
305 @rmdir(MWP_DB_DIR);
306 if (!$result) {
307 return array(
308 'error' => 'Failed to zip database.'
309 );
310 }
311 $this->update_status($task_name, $this->statuses['db_zip'], true);
312 }
313 } elseif (trim($what) == 'full') {
314 $content_backup = $this->backup_full($task_name, $backup_file, $exclude, $include);
315 if (is_array($content_backup) && array_key_exists('error', $content_backup)) {
316 return array(
317 'error' => $content_backup['error']
318 );
319 }
320 }
321
322 //Update backup info
323 if ($task_name) {
324 //backup task (scheduled)
325 $backup_settings = $this->tasks;
326 $paths = array();
327 $size = ceil(filesize($backup_file) / 1024);
328
329 if ($size > 1000) {
330 $paths['size'] = ceil($size / 1024) . "Mb";
331 } else {
332 $paths['size'] = $size . 'kb';
333 }
334
335 if ($task_name != 'Backup Now') {
336 if (!$backup_settings[$task_name]['task_args']['del_host_file']) {
337 $paths['server'] = array(
338 'file_path' => $backup_file,
339 'file_url' => $backup_url
340 );
341 }
342 } else {
343 $paths['server'] = array(
344 'file_path' => $backup_file,
345 'file_url' => $backup_url
346 );
347 }
348
349 if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_ftp'])) {
350 $paths['ftp'] = basename($backup_url);
351 }
352
353 if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_amazon_s3'])) {
354 $paths['amazons3'] = basename($backup_url);
355 }
356
357 if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_dropbox'])) {
358 $paths['dropbox'] = basename($backup_url);
359 }
360
361 if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_email'])) {
362 $paths['email'] = basename($backup_url);
363 }
364
365 $temp = $backup_settings[$task_name]['task_results'];
366 $temp = array_values($temp);
367 $paths['time'] = time();
368
369 if ($task_name != 'Backup Now') {
370 $paths['status'] = $temp[count($temp) - 1]['status'];
371 $temp[count($temp) - 1] = $paths;
372
373 } else {
374 $temp[count($temp)] = $paths;
375 }
376
377 $backup_settings[$task_name]['task_results'] = $temp;
378 $this->update_tasks($backup_settings);
379 //update_option('mwp_backup_tasks', $backup_settings);
380 }
381
382
383 //Additional: Email, ftp, amazon_s3, dropbox...
384
385 if ($task_name != 'Backup Now') {
386 if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
387 $this->update_status($task_name, $this->statuses['ftp']);
388 $account_info['mwp_ftp']['backup_file'] = $backup_file;
389 $ftp_result = $this->ftp_backup($account_info['mwp_ftp']);
390
391 if ($ftp_result !== true && $del_host_file) {
392 @unlink($backup_file);
393 }
394
395 if (is_array($ftp_result) && isset($ftp_result['error'])) {
396 return $ftp_result;
397 }
398 $this->update_status($task_name, $this->statuses['ftp'], true);
399 }
400
401 if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
402 $this->update_status($task_name, $this->statuses['s3']);
403 $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
404 $amazons3_result = $this->amazons3_backup($account_info['mwp_amazon_s3']);
405 if ($amazons3_result !== true && $del_host_file) {
406 @unlink($backup_file);
407 }
408 if (is_array($amazons3_result) && isset($amazons3_result['error'])) {
409 return $amazons3_result;
410 }
411 $this->update_status($task_name, $this->statuses['s3'], true);
412 }
413
414 if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
415 $this->update_status($task_name, $this->statuses['dropbox']);
416 $account_info['mwp_dropbox']['backup_file'] = $backup_file;
417 $dropbox_result = $this->dropbox_backup($account_info['mwp_dropbox']);
418 if ($dropbox_result !== true && $del_host_file) {
419 @unlink($backup_file);
420 }
421
422 if (is_array($dropbox_result) && isset($dropbox_result['error'])) {
423 return $dropbox_result;
424 }
425
426 $this->update_status($task_name, $this->statuses['dropbox'], true);
427 }
428
429 if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
430 $this->update_status($task_name, $this->statuses['email']);
431 $account_info['mwp_email']['task_name'] = $task_name;
432 $account_info['mwp_email']['file_path'] = $backup_file;
433
434 $email_result = $this->email_backup($account_info['mwp_email']);
435 if (is_array($email_result) && isset($email_result['error'])) {
436 return $email_result;
437 }
438 $this->update_status($task_name, $this->statuses['email'], true);
439 }
440
441 if ($del_host_file) {
442 @unlink($backup_file);
443 }
444
445 } //end additional
446
447 //$this->update_status($task_name,$this->statuses['finished'],true);
448 return $backup_url; //Return url to backup file
449 }
450
451 function backup_full($task_name, $backup_file, $exclude = array(), $include = array())
452 {
453 global $zip_errors;
454 $sys = substr(PHP_OS, 0, 3);
455
456 $this->update_status($task_name, $this->statuses['db_dump']);
457 $db_result = $this->backup_db();
458
459 if ($db_result == false) {
460 return array(
461 'error' => 'Failed to backup database.'
462 );
463 } else if (is_array($db_result) && isset($db_result['error'])) {
464 return array(
465 'error' => $db_result['error']
466 );
467 }
468
469 $this->update_status($task_name, $this->statuses['db_dump'], true);
470 $this->update_status($task_name, $this->statuses['db_zip']);
471 $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
472 $comp_level = $disable_comp ? '-0' : '-1';
473
474 $zip = $this->get_zip();
475 //Add database file
476 chdir(MWP_BACKUP_DIR);
477 $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
478 ob_start();
479 $result = $this->mmb_exec($command);
480 ob_get_clean();
481
482
483 if (!$result) {
484 define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
485 require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
486 $archive = new PclZip($backup_file);
487
488 if ($disable_comp) {
489 $result_db = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION);
490 } else {
491 $result_db = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR);
492 }
493
494 @unlink($db_result);
495 @rmdir(MWP_DB_DIR);
496
497 if (!$result_db) {
498 return array(
499 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
500 );
501 }
502 }
503
504 @unlink($db_result);
505 @rmdir(MWP_DB_DIR);
506
507 $this->update_status($task_name, $this->statuses['db_zip'], true);
508
509
510 //Always remove backup folders
511 $remove = array(
512 trim(basename(WP_CONTENT_DIR)) . "/managewp/backups",
513 trim(basename(WP_CONTENT_DIR)) . "/" . md5('mmb-worker') . "/mwp_backups"
514 );
515
516 //Exclude paths
517 $exclude_data = "-x";
518
519 if (!empty($exclude)) {
520 foreach ($exclude as $data) {
521 if (is_dir(ABSPATH . $data)) {
522 if ($sys == 'WIN')
523 $exclude_data .= " $data/*.*";
524 else
525 $exclude_data .= " '$data/*'";
526 } else {
527 if ($sys == 'WIN')
528 $exclude_data .= " $data";
529 else
530 $exclude_data .= " '$data'";
531 }
532 }
533 }
534
535 foreach ($remove as $data) {
536 if ($sys == 'WIN')
537 $exclude_data .= " $data/*.*";
538 else
539 $exclude_data .= " '$data/*'";
540 }
541
542 //Include paths by default
543 $add = array(
544 trim(WPINC),
545 trim(basename(WP_CONTENT_DIR)),
546 "wp-admin"
547 );
548
549 $include_data = ". -i";
550 foreach ($add as $data) {
551 if ($sys == 'WIN')
552 $include_data .= " $data/*.*";
553 else
554 $include_data .= " '$data/*'";
555 }
556
557 //Additional includes?
558 if (!empty($include)) {
559 foreach ($include as $data) {
560 if ($data) {
561 if ($sys == 'WIN')
562 $include_data .= " $data/*.*";
563 else
564 $include_data .= " '$data/*'";
565 }
566 }
567 }
568
569 $this->update_status($task_name, $this->statuses['files_zip']);
570 chdir(ABSPATH);
571 ob_start();
572 $command = "$zip -q -j $comp_level $backup_file * $exclude_data";
573 $result_f = $this->mmb_exec($command, false, true);
574
575 if (!$result_f || $result_f == 18) { // disregard permissions error, file can't be accessed
576 $command = "$zip -q -r $comp_level $backup_file $include_data $exclude_data";
577 $result_d = $this->mmb_exec($command, false, true);
578 if ($result_d && $result_d != 18) {
579 @unlink($backup_file);
580 if ($result_d > 0 && $result_d < 18)
581 return array(
582 'error' => 'Failed to archive files (' . $zip_errors[$result_d] . ') .'
583 );
584 else
585 return array(
586 'error' => 'Failed to archive files.'
587 );
588 }
589 }
590 ob_get_clean();
591
592 if ($result_f && $result_f != 18) { //Try pclZip
593
594 if (!isset($archive)) {
595 define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
596 require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
597 $archive = new PclZip($backup_file);
598 }
599
600 //Include paths
601 $include_data = array();
602 if (!empty($include)) {
603 foreach ($include as $data) {
604 if ($data && file_exists(ABSPATH . $data))
605 $include_data[] = ABSPATH . $data . '/';
606 }
607 }
608
609 foreach ($add as $data) {
610 if (file_exists(ABSPATH . $data))
611 $include_data[] = ABSPATH . $data . '/';
612 }
613
614 //Include root files
615 if ($handle = opendir(ABSPATH)) {
616 while (false !== ($file = readdir($handle))) {
617 if ($file != "." && $file != ".." && !is_dir($file) && file_exists(ABSPATH . $file)) {
618 $include_data[] = ABSPATH . $file;
619 }
620 }
621 closedir($handle);
622 }
623
624 if ($disable_comp) {
625 $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_NO_COMPRESSION);
626 } else {
627 $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH);
628 }
629 if (!$result) {
630 @unlink($backup_file);
631 return array(
632 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
633 );
634 }
635
636 //Now exclude paths
637 $exclude_data = array();
638 if (!empty($exclude)) {
639 foreach ($exclude as $data) {
640 if (is_dir(ABSPATH . $data))
641 $exclude_data[] = $data . '/';
642 else
643 $exclude_data[] = $data;
644 }
645 }
646
647 foreach ($remove as $rem) {
648 $exclude_data[] = $rem . '/';
649 }
650
651 $result_excl = $archive->delete(PCLZIP_OPT_BY_NAME, $exclude_data);
652 if (!$result_excl) {
653 @unlink($backup_file);
654 return array(
655 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
656 );
657 }
658
659 }
660
661 $this->update_status($task_name, $this->statuses['files_zip'], true);
662 return true;
663 }
664
665
666 function backup_db()
667 {
668 $db_folder = MWP_DB_DIR . '/';
669 if (!file_exists($db_folder)) {
670 if (!mkdir($db_folder, 0755, true))
671 return array(
672 'error' => 'Error creating database backup folder (' . $db_folder . '). Make sure you have corrrect write permissions.'
673 );
674 }
675
676 $file = $db_folder . DB_NAME . '.sql';
677 $result = $this->backup_db_dump($file); // try mysqldump always then fallback to php dump
678 return $result;
679 }
680
681 function backup_db_dump($file)
682 {
683 global $wpdb;
684 $paths = $this->check_mysql_paths();
685 $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
686 $command = $brace . $paths['mysqldump'] . $brace . ' --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" --add-drop-table --skip-lock-tables "' . DB_NAME . '" > ' . $brace . $file . $brace;
687 ob_start();
688 $result = $this->mmb_exec($command);
689 ob_get_clean();
690
691 if (!$result) { // Fallback to php
692 $result = $this->backup_db_php($file);
693 return $result;
694 }
695
696 if (filesize($file) == 0 || !is_file($file) || !$result) {
697 @unlink($file);
698 return false;
699 } else {
700 return $file;
701 }
702 }
703
704 function backup_db_php($file)
705 {
706 global $wpdb;
707 $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
708 foreach ($tables as $table) {
709 //drop existing table
710 $dump_data = "DROP TABLE IF EXISTS $table[0];";
711 //create table
712 $create_table = $wpdb->get_row("SHOW CREATE TABLE $table[0]", ARRAY_N);
713 $dump_data .= "\n\n" . $create_table[1] . ";\n\n";
714
715 $count = $wpdb->get_var("SELECT count(*) FROM $table[0]");
716 if ($count > 100)
717 $count = ceil($count / 100) - 1;
718 else
719 $count = 1;
720 for ($i = 0; $i < $count; $i++) {
721 $low_limit = $i * 100;
722 $qry = "SELECT * FROM $table[0] LIMIT $low_limit, 100";
723 $rows = $wpdb->get_results($qry, ARRAY_A);
724 if (is_array($rows)) {
725 foreach ($rows as $row) {
726 //insert single row
727 $dump_data .= "INSERT INTO $table[0] VALUES(";
728 $num_values = count($row);
729 $j = 1;
730 foreach ($row as $value) {
731 $value = addslashes($value);
732 $value = preg_replace("/\n/Ui", "\\n", $value);
733 $num_values == $j ? $dump_data .= "'" . $value . "'" : $dump_data .= "'" . $value . "', ";
734 $j++;
735 unset($value);
736 }
737 $dump_data .= ");\n";
738 }
739 }
740 }
741 $dump_data .= "\n\n\n";
742
743 unset($rows);
744 file_put_contents($file, $dump_data, FILE_APPEND);
745 unset($dump_data);
746 }
747
748 if (filesize($file) == 0 || !is_file($file)) {
749 @unlink($file);
750 return array(
751 'error' => 'Database backup failed. Try to enable MySQL dump on your server.'
752 );
753 }
754
755 return $file;
756
757 }
758
759 function restore($args)
760 {
761 global $wpdb;
762 if (empty($args)) {
763 return false;
764 }
765
766 extract($args);
767 @ini_set('memory_limit', '256M');
768 @set_time_limit(600);
769
770 $unlink_file = true; //Delete file after restore
771
772 //Detect source
773 if ($backup_url) {
774 //This is for clone (overwrite)
775 include_once ABSPATH . 'wp-admin/includes/file.php';
776 $backup_file = download_url($backup_url);
777 if (is_wp_error($backup_file)) {
778 return array(
779 'error' => $backup_file->get_error_message()
780 );
781 }
782 $what = 'full';
783 } else {
784 $tasks = $this->tasks;
785 $task = $tasks[$task_name];
786 if (isset($task['task_results'][$result_id]['server'])) {
787 $backup_file = $task['task_results'][$result_id]['server']['file_path'];
788 $unlink_file = false; //Don't delete file if stored on server
789 } elseif (isset($task['task_results'][$result_id]['ftp'])) {
790 $ftp_file = $task['task_results'][$result_id]['ftp'];
791 $args = $task['task_args']['account_info']['mwp_ftp'];
792 $args['backup_file'] = $ftp_file;
793 $backup_file = $this->get_ftp_backup($args);
794 if ($backup_file == false) {
795 return array(
796 'error' => 'Failed to download file from FTP.'
797 );
798 }
799 } elseif (isset($task['task_results'][$result_id]['amazons3'])) {
800 $amazons3_file = $task['task_results'][$result_id]['amazons3'];
801 $args = $task['task_args']['account_info']['mwp_amazon_s3'];
802 $args['backup_file'] = $ftp_file;
803 $backup_file = $this->get_amazons3_backup($args);
804 if ($backup_file == false) {
805 return array(
806 'error' => 'Failed to download file from Amazon S3.'
807 );
808 }
809 }
810
811 $what = $tasks[$task_name]['task_args']['what'];
812 }
813
814 if ($backup_file && file_exists($backup_file)) {
815 if ($overwrite) {
816 //Keep old db credentials before overwrite
817 if (!copy(ABSPATH . 'wp-config.php', ABSPATH . 'mwp-temp-wp-config.php')) {
818 @unlink($backup_file);
819 return array(
820 'error' => 'Error creating wp-config. Please check your write permissions.'
821 );
822 }
823
824 $db_host = DB_HOST;
825 $db_user = DB_USER;
826 $db_password = DB_PASSWORD;
827 $home = rtrim(get_option('home'), "/");
828 $site_url = get_option('site_url');
829
830 if (trim($clone_from_url) || trim($mwp_clone)) {
831 $clone_options = array();
832 $clone_options['_worker_nossl_key'] = get_option('_worker_nossl_key');
833 $clone_options['_worker_public_key'] = get_option('_worker_public_key');
834 $clone_options['_action_message_id'] = get_option('_action_message_id');
835 }
836
837
838 }
839
840
841 chdir(ABSPATH);
842 $unzip = $this->get_unzip();
843 $command = "$unzip -o $backup_file";
844 ob_start();
845 $result = $this->mmb_exec($command);
846 ob_get_clean();
847
848 if (!$result) { //fallback to pclzip
849 define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
850 require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
851 $archive = new PclZip($backup_file);
852 $result = $archive->extract(PCLZIP_OPT_PATH, ABSPATH, PCLZIP_OPT_REPLACE_NEWER);
853 }
854
855 if ($unlink_file) {
856 @unlink($backup_file);
857 }
858
859 if (!$result) {
860 return array(
861 'error' => 'Failed to unzip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
862 );
863 }
864
865 $db_result = $this->restore_db();
866
867 if (!$db_result) {
868 return array(
869 'error' => 'Error restoring database.'
870 );
871 }
872
873 } else {
874 return array(
875 'error' => 'Error restoring. Cannot find backup file.'
876 );
877 }
878
879 //Replace options and content urls
880 if ($overwrite) {
881 //Get New Table prefix
882 $new_table_prefix = trim($this->get_table_prefix());
883 //Retrieve old wp_config
884 @unlink(ABSPATH . 'wp-config.php');
885 //Replace table prefix
886 $lines = file(ABSPATH . 'mwp-temp-wp-config.php');
887
888 foreach ($lines as $line) {
889 if (strstr($line, '$table_prefix')) {
890 $line = '$table_prefix = "' . $new_table_prefix . '";' . PHP_EOL;
891 }
892 file_put_contents(ABSPATH . 'wp-config.php', $line, FILE_APPEND);
893 }
894
895 @unlink(ABSPATH . 'mwp-temp-wp-config.php');
896
897 //Replace options
898 $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = 'home'";
899 $old = $wpdb->get_var($wpdb->prepare($query));
900 $old = rtrim($old, "/");
901 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$home' WHERE option_name = 'home'";
902 $wpdb->query($wpdb->prepare($query));
903 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$home' WHERE option_name = 'siteurl'";
904 $wpdb->query($wpdb->prepare($query));
905 //Replace content urls
906 $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(.*)\"'";
907 $wpdb->query($wpdb->prepare($query));
908
909 if (trim($new_password)) {
910 $new_password = wp_hash_password($new_password);
911 }
912 if (!trim($clone_from_url) && !trim($mwp_clone)) {
913 if ($new_user && $new_password) {
914 $query = "UPDATE " . $new_table_prefix . "users SET user_login = '$new_user', user_pass = '$new_password' WHERE user_login = '$old_user'";
915 $wpdb->query($wpdb->prepare($query));
916 }
917 } else {
918 if ($clone_from_url) {
919 if ($new_user && $new_password) {
920 $query = "UPDATE " . $new_table_prefix . "users SET user_pass = '$new_password' WHERE user_login = '$new_user'";
921 $wpdb->query($wpdb->prepare($query));
922 }
923 }
924
925 if ($mwp_clone) {
926 if ($admin_email) {
927 //Clean Install
928 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$admin_email' WHERE option_name = 'admin_email'";
929 $wpdb->query($wpdb->prepare($query));
930 $query = "SELECT * FROM " . $new_table_prefix . "users LIMIT 1";
931 $temp_user = $wpdb->get_row($query);
932 if (!empty($temp_user)) {
933 $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'";
934 $wpdb->query($wpdb->prepare($query));
935 }
936 }
937 }
938 }
939
940 if (is_array($clone_options)) {
941 foreach ($clone_options as $key => $option) {
942 if (!empty($key)) {
943 $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = '$key'";
944 $res = $wpdb->get_var($query);
945 if ($res == false) {
946 $query = "INSERT INTO " . $new_table_prefix . "options (option_value,option_name) VALUES('$option','$key')";
947 $wpdb->query($wpdb->prepare($query));
948 } else {
949 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$option' WHERE option_name = '$key'";
950 $wpdb->query($wpdb->prepare($query));
951 }
952 }
953 }
954 }
955 }
956
957 return true;
958 }
959
960 function restore_db()
961 {
962 global $wpdb;
963 $paths = $this->check_mysql_paths();
964 $file_path = ABSPATH . 'mwp_db';
965 $file_name = glob($file_path . '/*.sql');
966 $file_name = $file_name[0];
967 $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
968 $command = $brace . $paths['mysql'] . $brace . ' --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" ' . DB_NAME . ' < ' . $brace . $file_name . $brace;
969
970 ob_start();
971 $result = $this->mmb_exec($command);
972 ob_get_clean();
973 if (!$result) {
974 //try php
975 $this->restore_db_php($file_name);
976 }
977
978
979 @unlink($file_name);
980 return true;
981 }
982
983 function restore_db_php($file_name)
984 {
985 global $wpdb;
986 $current_query = '';
987 // Read in entire file
988 $lines = file($file_name);
989 // Loop through each line
990 foreach ($lines as $line) {
991 // Skip it if it's a comment
992 if (substr($line, 0, 2) == '--' || $line == '')
993 continue;
994
995 // Add this line to the current query
996 $current_query .= $line;
997 // If it has a semicolon at the end, it's the end of the query
998 if (substr(trim($line), -1, 1) == ';') {
999 // Perform the query
1000 $result = $wpdb->query($current_query);
1001 if ($result === false)
1002 return false;
1003 // Reset temp variable to empty
1004 $current_query = '';
1005 }
1006 }
1007
1008 @unlink($file_name);
1009 return true;
1010 }
1011
1012 function get_table_prefix()
1013 {
1014 $lines = file(ABSPATH . 'wp-config.php');
1015 foreach ($lines as $line) {
1016 if (strstr($line, '$table_prefix')) {
1017 $pattern = "/(\'|\")[^(\'|\")]*/";
1018 preg_match($pattern, $line, $matches);
1019 $prefix = substr($matches[0], 1);
1020 return $prefix;
1021 break;
1022 }
1023 }
1024 return 'wp_'; //default
1025 }
1026
1027 function optimize_tables()
1028 {
1029 global $wpdb;
1030 $query = 'SHOW TABLE STATUS FROM ' . DB_NAME;
1031 $tables = $wpdb->get_results($wpdb->prepare($query), ARRAY_A);
1032 foreach ($tables as $table) {
1033 if (in_array($table['Engine'], array(
1034 'MyISAM',
1035 'ISAM',
1036 'HEAP',
1037 'MEMORY',
1038 'ARCHIVE'
1039 )))
1040 $table_string .= $table['Name'] . ",";
1041 elseif ($table['Engine'] == 'InnoDB') {
1042 $optimize = $wpdb->query("ALTER TABLE {$table['Name']} ENGINE=InnoDB");
1043 }
1044 }
1045
1046 $table_string = rtrim($table_string);
1047 $optimize = $wpdb->query("OPTIMIZE TABLE $table_string");
1048
1049 return $optimize ? true : false;
1050 }
1051
1052 ### Function: Auto Detect MYSQL and MYSQL Dump Paths
1053 function check_mysql_paths()
1054 {
1055 global $wpdb;
1056 $paths = array(
1057 'mysql' => '',
1058 'mysqldump' => ''
1059 );
1060 if (substr(PHP_OS, 0, 3) == 'WIN') {
1061 $mysql_install = $wpdb->get_row("SHOW VARIABLES LIKE 'basedir'");
1062 if ($mysql_install) {
1063 $install_path = str_replace('\\', '/', $mysql_install->Value);
1064 $paths['mysql'] = $install_path . 'bin/mysql.exe';
1065 $paths['mysqldump'] = $install_path . 'bin/mysqldump.exe';
1066 } else {
1067 $paths['mysql'] = 'mysql.exe';
1068 $paths['mysqldump'] = 'mysqldump.exe';
1069 }
1070 } else {
1071 $paths['mysql'] = $this->mmb_exec('which mysql', true);
1072 if (empty($paths['mysql']))
1073 $paths['mysql'] = 'mysql'; // try anyway
1074
1075 $paths['mysqldump'] = $this->mmb_exec('which mysqldump', true);
1076 if (empty($paths['mysqldump']))
1077 $paths['mysqldump'] = 'mysqldump'; // try anyway
1078
1079 }
1080
1081
1082 return $paths;
1083 }
1084
1085 //Check if exec, system, passthru functions exist
1086 function check_sys()
1087 {
1088 if ($this->mmb_function_exists('exec'))
1089 return 'exec';
1090
1091 if ($this->mmb_function_exists('system'))
1092 return 'system';
1093
1094 if ($this->mmb_function_exists('passhtru'))
1095 return 'passthru';
1096
1097 return false;
1098
1099 }
1100
1101 function mmb_exec($command, $string = false, $rawreturn = false)
1102 {
1103 if ($command == '')
1104 return false;
1105
1106 if ($this->mmb_function_exists('exec')) {
1107 $log = @exec($command, $output, $return);
1108
1109 if ($string)
1110 return $log;
1111 if ($rawreturn)
1112 return $return;
1113
1114 return $return ? false : true;
1115 } elseif ($this->mmb_function_exists('system')) {
1116 $log = @system($command, $return);
1117
1118 if ($string)
1119 return $log;
1120
1121 if ($rawreturn)
1122 return $return;
1123
1124 return $return ? false : true;
1125 } elseif ($this->mmb_function_exists('passthru') && !$string) {
1126 $log = passthru($command, $return);
1127
1128 if ($rawreturn)
1129 return $return;
1130
1131 return $return ? false : true;
1132 }
1133
1134 if ($rawreturn)
1135 return -1;
1136
1137 return false;
1138 }
1139
1140 function get_zip()
1141 {
1142 $zip = $this->mmb_exec('which zip', true);
1143 if (!$zip)
1144 $zip = "zip";
1145 return $zip;
1146 }
1147
1148 function get_unzip()
1149 {
1150 $unzip = $this->mmb_exec('which unzip', true);
1151 if (!$unzip)
1152 $unzip = "unzip";
1153 return $unzip;
1154 }
1155
1156 function check_backup_compat()
1157 {
1158 $reqs = array();
1159 if (strpos($_SERVER['DOCUMENT_ROOT'], '/') === 0) {
1160 $reqs['Server OS']['status'] = 'Linux (or compatible)';
1161 $reqs['Server OS']['pass'] = true;
1162 } else {
1163 $reqs['Server OS']['status'] = 'Windows';
1164 $reqs['Server OS']['pass'] = true;
1165 $pass = false;
1166 }
1167 $reqs['PHP Version']['status'] = phpversion();
1168 if ((float) phpversion() >= 5.1) {
1169 $reqs['PHP Version']['pass'] = true;
1170 } else {
1171 $reqs['PHP Version']['pass'] = false;
1172 $pass = false;
1173 }
1174
1175
1176 if (is_writable(WP_CONTENT_DIR)) {
1177 $reqs['Backup Folder']['status'] = "writable";
1178 $reqs['Backup Folder']['pass'] = true;
1179 } else {
1180 $reqs['Backup Folder']['status'] = "not writable";
1181 $reqs['Backup Folder']['pass'] = false;
1182 }
1183
1184
1185 $file_path = MWP_BACKUP_DIR;
1186 $reqs['Backup Folder']['status'] .= ' (' . $file_path . ')';
1187
1188 if ($func = $this->check_sys()) {
1189 $reqs['Execute Function']['status'] = $func;
1190 $reqs['Execute Function']['pass'] = true;
1191 } else {
1192 $reqs['Execute Function']['status'] = "not found";
1193 $reqs['Execute Function']['info'] = "(will try PHP replacement)";
1194 $reqs['Execute Function']['pass'] = false;
1195 }
1196 $reqs['Zip']['status'] = $this->get_zip();
1197
1198 $reqs['Zip']['pass'] = true;
1199
1200
1201
1202 $reqs['Unzip']['status'] = $this->get_unzip();
1203
1204 $reqs['Unzip']['pass'] = true;
1205
1206 $paths = $this->check_mysql_paths();
1207
1208 if (!empty($paths['mysqldump'])) {
1209 $reqs['MySQL Dump']['status'] = $paths['mysqldump'];
1210 $reqs['MySQL Dump']['pass'] = true;
1211 } else {
1212 $reqs['MySQL Dump']['status'] = "not found";
1213 $reqs['MySQL Dump']['info'] = "(will try PHP replacement)";
1214 $reqs['MySQL Dump']['pass'] = false;
1215 }
1216
1217 $exec_time = ini_get('max_execution_time');
1218 $reqs['Execution time']['status'] = $exec_time ? $exec_time . "s" : 'unknown';
1219 $reqs['Execution time']['pass'] = true;
1220
1221 $mem_limit = ini_get('memory_limit');
1222 $reqs['Memory limit']['status'] = $mem_limit ? $mem_limit : 'unknown';
1223 $reqs['Memory limit']['pass'] = true;
1224
1225
1226 return $reqs;
1227 }
1228
1229 function email_backup($args)
1230 {
1231 $email = $args['email'];
1232
1233 if (!is_email($email)) {
1234 return array(
1235 'error' => 'Your email (' . $email . ') is not correct'
1236 );
1237 }
1238 $backup_file = $args['file_path'];
1239 $task_name = isset($args['task_name']) ? $args['task_name'] : '';
1240 if (file_exists($backup_file) && $email) {
1241 $attachments = array(
1242 $backup_file
1243 );
1244 $headers = 'From: ManageWP <no-reply@managewp.com>' . "\r\n";
1245 $subject = "ManageWP - " . $task_name . " - " . $this->site_name;
1246 ob_start();
1247 $result = wp_mail($email, $subject, $subject, $headers, $attachments);
1248 ob_end_clean();
1249
1250 }
1251
1252 if (!$result) {
1253 return array(
1254 'error' => 'Email not sent. Maybe your backup is too big for email or email server is not available on your website.'
1255 );
1256 }
1257 return true;
1258
1259 }
1260
1261 function ftp_backup($args)
1262 {
1263 extract($args);
1264 //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder, $ftp_site_folder
1265 if ($ftp_ssl) {
1266 if (function_exists('ftp_ssl_connect')) {
1267 $conn_id = ftp_ssl_connect($ftp_hostname);
1268 } else {
1269 return array(
1270 'error' => 'Your server doesn\'t support SFTP',
1271 'partial' => 1
1272 );
1273 }
1274 } else {
1275 if (function_exists('ftp_connect')) {
1276 $conn_id = ftp_connect($ftp_hostname);
1277 if ($conn_id === false) {
1278 return array(
1279 'error' => 'Failed to connect to ' . $ftp_hostname,
1280 'partial' => 1
1281 );
1282 }
1283 } else {
1284 return array(
1285 'error' => 'Your server doesn\'t support FTP',
1286 'partial' => 1
1287 );
1288 }
1289 }
1290 $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1291 if ($login === false) {
1292 return array(
1293 'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
1294 'partial' => 1
1295 );
1296 }
1297
1298 @ftp_mkdir($conn_id, $ftp_remote_folder);
1299 if ($ftp_site_folder) {
1300 $ftp_remote_folder .= '/' . $this->site_name;
1301 }
1302 @ftp_mkdir($conn_id, $ftp_remote_folder);
1303
1304 $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
1305
1306 if ($upload === false) { //Try ascii
1307 $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
1308 }
1309 ftp_close($conn_id);
1310
1311 if ($upload === false) {
1312 return array(
1313 'error' => 'Failed to upload file to FTP. Please check your specified path.',
1314 'partial' => 1
1315 );
1316 }
1317
1318 return true;
1319 }
1320
1321 function remove_ftp_backup($args)
1322 {
1323 extract($args);
1324 //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
1325 if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1326 $conn_id = ftp_ssl_connect($ftp_hostname);
1327 } else if (function_exists('ftp_connect')) {
1328 $conn_id = ftp_connect($ftp_hostname);
1329 }
1330
1331 if ($conn_id) {
1332 $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1333 if ($ftp_site_folder)
1334 $ftp_remote_folder .= '/' . $this->site_name;
1335
1336 $delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
1337
1338 ftp_close($conn_id);
1339 }
1340
1341 }
1342
1343 function get_ftp_backup($args)
1344 {
1345 extract($args);
1346 //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
1347 if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1348 $conn_id = ftp_ssl_connect($ftp_hostname);
1349
1350 } else if (function_exists('ftp_connect')) {
1351 $conn_id = ftp_connect($ftp_hostname);
1352 if ($conn_id === false) {
1353 return false;
1354 }
1355 } else {
1356 }
1357 $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1358 if ($login === false) {
1359 return false;
1360 } else {
1361 }
1362
1363 if ($ftp_site_folder)
1364 $ftp_remote_folder .= '/' . $this->site_name;
1365
1366 $temp = ABSPATH . 'mwp_temp_backup.zip';
1367 $get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
1368 if ($get === false) {
1369 return false;
1370 } else {
1371 }
1372 ftp_close($conn_id);
1373
1374 return $temp;
1375 }
1376
1377 function dropbox_backup($args)
1378 {
1379 require_once('lib/dropbox.php');
1380 extract($args);
1381
1382 //$email, $password, $backup_file, $destination, $dropbox_site_folder
1383
1384 $size = ceil(filesize($backup_file) / 1024);
1385 if ($size > 300000) {
1386 return array(
1387 'error' => 'Cannot upload file to Dropbox. Dropbox has upload limit of 300Mb per file.',
1388 'partial' => 1
1389 );
1390 }
1391
1392 if ($dropbox_site_folder == true)
1393 $dropbox_destination .= '/' . $this->site_name;
1394
1395 try {
1396 $uploader = new DropboxUploader($dropbox_username, $dropbox_password);
1397 $uploader->upload($backup_file, $dropbox_destination);
1398 }
1399 catch (Exception $e) {
1400 return array(
1401 'error' => $e->getMessage(),
1402 'partial' => 1
1403 );
1404 }
1405
1406 return true;
1407
1408 }
1409
1410 function amazons3_backup($args)
1411 {
1412 if ($this->mmb_function_exists('curl_init')) {
1413 require_once('lib/s3.php');
1414 extract($args);
1415
1416 if ($as3_site_folder == true)
1417 $as3_directory .= '/' . $this->site_name;
1418
1419 $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1420
1421 $s3 = new S3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
1422
1423 $s3->putBucket($as3_bucket, S3::ACL_PUBLIC_READ);
1424
1425 if ($s3->putObjectFile($backup_file, $as3_bucket, $as3_directory . '/' . basename($backup_file), S3::ACL_PRIVATE)) {
1426 return true;
1427 } else {
1428 return array(
1429 'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
1430 'partial' => 1
1431 );
1432 }
1433 } else {
1434 return array(
1435 'error' => 'You cannot use Amazon S3 on your server. Please enable curl first.',
1436 'partial' => 1
1437 );
1438 }
1439 }
1440
1441 function remove_amazons3_backup($args)
1442 {
1443 require_once('lib/s3.php');
1444 extract($args);
1445 if ($as3_site_folder == true)
1446 $as3_directory .= '/' . $this->site_name;
1447 $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1448 $s3 = new S3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
1449 $s3->deleteObject($as3_bucket, $as3_directory . '/' . $backup_file);
1450 }
1451
1452 function get_amazons3_backup($args)
1453 {
1454 require_once('lib/s3.php');
1455 extract($args);
1456 $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1457 $s3 = new S3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
1458 if ($as3_site_folder == true)
1459 $as3_directory .= '/' . $this->site_name;
1460
1461 $s3->getObject($as3_bucket, $as3_directory . '/' . $backup_file, $temp);
1462 $temp = ABSPATH . 'mwp_temp_backup.zip';
1463 return $temp;
1464 }
1465
1466 function schedule_next($type, $schedule)
1467 {
1468 $schedule = explode("|", $schedule);
1469 if (empty($schedule))
1470 return false;
1471 switch ($type) {
1472
1473 case 'daily':
1474
1475 if ($schedule[1]) {
1476 $delay_time = $schedule[1] * 60;
1477 }
1478
1479 $current_hour = date("H");
1480 $schedule_hour = $schedule[0];
1481 if ($current_hour >= $schedule_hour)
1482 $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 1, date("Y"));
1483 else
1484 $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
1485 break;
1486
1487
1488 case 'weekly':
1489 if ($schedule[2]) {
1490 $delay_time = $schedule[2] * 60;
1491 }
1492 $current_weekday = date('w');
1493 $schedule_weekday = $schedule[1];
1494 $current_hour = date("H");
1495 $schedule_hour = $schedule[0];
1496
1497 if ($current_weekday > $schedule_weekday)
1498 $weekday_offset = 7 - ($week_day - $task_schedule[1]);
1499 else
1500 $weekday_offset = $schedule_weekday - $current_weekday;
1501
1502
1503 if (!$weekday_offset) { //today is scheduled weekday
1504 if ($current_hour >= $schedule_hour)
1505 $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 7, date("Y"));
1506 else
1507 $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
1508 } else {
1509 $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + $weekday_offset, date("Y"));
1510 }
1511
1512 break;
1513
1514 case 'monthly':
1515 if ($schedule[2]) {
1516 $delay_time = $schedule[2] * 60;
1517 }
1518 $current_monthday = date('j');
1519 $schedule_monthday = $schedule[1];
1520 $current_hour = date("H");
1521 $schedule_hour = $schedule[0];
1522
1523 if ($current_monthday > $schedule_monthday) {
1524 $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
1525 } else if ($current_monthday < $schedule_monthday) {
1526 $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
1527 } else if ($current_monthday == $schedule_monthday) {
1528 if ($current_hour >= $schedule_hour)
1529 $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
1530 else
1531 $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
1532 break;
1533 }
1534
1535 break;
1536 default:
1537 break;
1538 }
1539
1540 if ($delay_time) {
1541 $time += $delay_time;
1542 }
1543
1544
1545 return $time;
1546
1547 }
1548
1549 //Parse task arguments for info on master
1550 function get_backup_stats()
1551 {
1552 $stats = array();
1553 $tasks = $this->tasks;
1554 if (is_array($tasks) && !empty($tasks)) {
1555 foreach ($tasks as $task_name => $info) {
1556 if (is_array($info['task_results']) && !empty($info['task_results'])) {
1557 foreach ($info['task_results'] as $key => $result) {
1558 if (isset($result['server']) && !isset($result['error'])) {
1559 if (!file_exists($result['server']['file_path'])) {
1560 $info['task_results'][$key]['error'] = 'Backup created but manually removed from server.';
1561 }
1562 }
1563 }
1564 }
1565
1566 $stats[$task_name] = array_values($info['task_results']);
1567
1568 }
1569 }
1570 return $stats;
1571 }
1572
1573 function get_next_schedules()
1574 {
1575 $stats = array();
1576 $tasks = $this->tasks;
1577 if (is_array($tasks) && !empty($tasks)) {
1578 foreach ($tasks as $task_name => $info) {
1579 $stats[$task_name] = $info['task_args']['next'];
1580 }
1581 }
1582 return $stats;
1583 }
1584
1585 function remove_old_backups($task_name)
1586 {
1587 //Check for previous failed backups first
1588 $this->cleanup();
1589
1590 //Remove by limit
1591 $backups = $this->tasks;
1592 if ($task_name == 'Backup Now') {
1593 $num = 0;
1594 } else {
1595 $num = 1;
1596 }
1597
1598
1599 if ((count($backups[$task_name]['task_results']) - $num) >= $backups[$task_name]['task_args']['limit']) {
1600 //how many to remove ?
1601 $remove_num = (count($backups[$task_name]['task_results']) - $num - $backups[$task_name]['task_args']['limit']) + 1;
1602 for ($i = 0; $i < $remove_num; $i++) {
1603 //Remove from the server
1604 if (isset($backups[$task_name]['task_results'][$i]['server'])) {
1605 @unlink($backups[$task_name]['task_results'][$i]['server']['file_path']);
1606 }
1607
1608 //Remove from ftp
1609 if (isset($backups[$task_name]['task_results'][$i]['ftp'])) {
1610 $ftp_file = $backups[$task_name]['task_results'][$i]['ftp'];
1611 $args = $backups[$task_name]['task_args']['account_info']['mwp_ftp'];
1612 $args['backup_file'] = $ftp_file;
1613 $this->remove_ftp_backup($args);
1614 }
1615
1616 if (isset($backups[$task_name]['task_results'][$i]['amazons3'])) {
1617 $amazons3_file = $backups[$task_name]['task_results'][$i]['amazons3'];
1618 $args = $backups[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
1619 $args['backup_file'] = $amazons3_file;
1620 $this->remove_amazons3_backup($args);
1621 }
1622
1623 if (isset($backups[$task_name]['task_results'][$i]['dropbox'])) {
1624 //To do: dropbox remove
1625 }
1626
1627 //Remove database backup info
1628 unset($backups[$task_name]['task_results'][$i]);
1629
1630 } //end foreach
1631
1632 $backups[$task_name]['task_results'] = array_values($backups[$task_name]['task_results']);
1633 $this->update_tasks($backups);
1634 //update_option('mwp_backup_tasks', $backups);
1635 }
1636 }
1637
1638 /**
1639 * Delete specified backup
1640 * Args: $task_name, $result_id
1641 */
1642
1643 function delete_backup($args)
1644 {
1645 if (empty($args))
1646 return false;
1647 extract($args);
1648
1649 $tasks = $this->tasks;
1650 $task = $tasks[$task_name];
1651 $backups = $task['task_results'];
1652 $backup = $backups[$result_id];
1653
1654 if (isset($backup['server'])) {
1655 @unlink($backup['server']['file_path']);
1656 }
1657
1658 //Remove from ftp
1659 if (isset($backup['ftp'])) {
1660 $ftp_file = $backup['ftp'];
1661 $args = $tasks[$task_name]['task_args']['account_info']['mwp_ftp'];
1662 $args['backup_file'] = $ftp_file;
1663 $this->remove_ftp_backup($args);
1664 }
1665
1666 if (isset($backup['amazons3'])) {
1667 $amazons3_file = $backup['amazons3'];
1668 $args = $tasks[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
1669 $args['backup_file'] = $amazons3_file;
1670 $this->remove_amazons3_backup($args);
1671 }
1672
1673 if (isset($backup['dropbox'])) {
1674 }
1675
1676 unset($backups[$result_id]);
1677
1678 if (count($backups)) {
1679 $tasks[$task_name]['task_results'] = $backups;
1680 } else {
1681 unset($tasks[$task_name]['task_results']);
1682 }
1683
1684 $this->update_tasks($tasks);
1685 //update_option('mwp_backup_tasks', $tasks);
1686 return true;
1687
1688 }
1689
1690 function cleanup()
1691 {
1692 $tasks = $this->tasks;
1693 $backup_folder = WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups/';
1694 $backup_folder_new = MWP_BACKUP_DIR . '/';
1695 $files = glob($backup_folder . "*");
1696 $new = glob($backup_folder_new . "*");
1697
1698 //Failed db files first
1699 $db_folder = MWP_DB_DIR . '/';
1700 $db_files = glob($db_folder . "*");
1701 if (is_array($db_files) && !empty($db_files)) {
1702 foreach ($db_files as $file) {
1703 @unlink($file);
1704 }
1705 @rmdir(MWP_DB_DIR);
1706 }
1707
1708
1709 //clean_old folder?
1710 if ((basename($files[0]) == 'index.php' && count($files) == 1) || (empty($files))) {
1711 foreach ($files as $file) {
1712 @unlink($file);
1713 }
1714 @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups');
1715 @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker'));
1716 }
1717
1718
1719 foreach ($new as $b) {
1720 $files[] = $b;
1721 }
1722 $deleted = array();
1723
1724 if (is_array($files) && count($files)) {
1725 $results = array();
1726 if (!empty($tasks)) {
1727 foreach ((array) $tasks as $task) {
1728 if (isset($task['task_results']) && count($task['task_results'])) {
1729 foreach ($task['task_results'] as $backup) {
1730 if (isset($backup['server'])) {
1731 $results[] = $backup['server']['file_path'];
1732 }
1733 }
1734 }
1735 }
1736 }
1737
1738 $num_deleted = 0;
1739 foreach ($files as $file) {
1740 if (!in_array($file, $results) && basename($file) != 'index.php') {
1741 @unlink($file);
1742 $deleted[] = basename($file);
1743 $num_deleted++;
1744 }
1745 }
1746 }
1747
1748
1749
1750 return $deleted;
1751 }
1752
1753
1754 function remote_backup_now($args)
1755 {
1756 if (!empty($args))
1757 extract($args);
1758
1759 $tasks = $this->tasks;
1760 $task = $tasks['Backup Now'];
1761
1762 if (!empty($task)) {
1763 extract($task['task_args']);
1764 }
1765
1766 $results = $task['task_results'];
1767
1768 if (is_array($results) && count($results)) {
1769 $backup_file = $results[count($results) - 1]['server']['file_path'];
1770 }
1771
1772 if ($backup_file && file_exists($backup_file)) {
1773 //FTP, Amazon S3 or Dropbox
1774 if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
1775 $account_info['mwp_ftp']['backup_file'] = $backup_file;
1776 $return = $this->ftp_backup($account_info['mwp_ftp']);
1777 }
1778
1779 if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
1780 $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
1781 $return = $this->amazons3_backup($account_info['mwp_amazon_s3']);
1782 }
1783
1784 if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
1785 $account_info['mwp_dropbox']['backup_file'] = $backup_file;
1786 $return = $this->dropbox_backup($account_info['mwp_dropbox']);
1787 }
1788
1789 if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
1790 $account_info['mwp_email']['file_path'] = $backup_file;
1791 $account_info['mwp_email']['task_name'] = 'Backup Now';
1792 $return = $this->email_backup($account_info['mwp_email']);
1793 }
1794
1795
1796 if ($return == true && $del_host_file) {
1797 @unlink($backup_file);
1798 unset($tasks['Backup Now']['task_results'][count($results) - 1]['server']);
1799 $this->update_tasks($tasks);
1800 //update_option('mwp_backup_tasks', $tasks);
1801 }
1802
1803
1804
1805 } else {
1806 $return = array(
1807 'error' => 'Backup file not found on your server. Please try again.'
1808 );
1809 }
1810
1811 return $return;
1812
1813 }
1814
1815 function validate_task($args, $url)
1816 {
1817 if (!class_exists('WP_Http')) {
1818 include_once(ABSPATH . WPINC . '/class-http.php');
1819 }
1820 $params = array();
1821 $params['body'] = $args;
1822 $result = wp_remote_post($url, $params);
1823 if (is_array($result) && $result['body'] == 'mwp_delete_task') {
1824 //$tasks = $this->get_backup_settings();
1825 $tasks = $this->tasks;
1826 unset($tasks[$args['task_name']]);
1827 $this->update_tasks($tasks);
1828 $this->cleanup();
1829 exit;
1830 }
1831 }
1832
1833 function update_status($task_name, $status, $completed = false)
1834 {
1835 /* Statuses:
1836 0 - Backup started
1837 1 - DB dump
1838 2 - DB ZIP
1839 3 - Files ZIP
1840 4 - Amazon S3
1841 5 - Dropbox
1842 6 - FTP
1843 7 - Email
1844 100 - Finished
1845 */
1846 if ($task_name != 'Backup Now') {
1847 $tasks = $this->tasks;
1848 $index = count($tasks[$task_name]['task_results']) - 1;
1849 if (!is_array($tasks[$task_name]['task_results'][$index]['status'])) {
1850 $tasks[$task_name]['task_results'][$index]['status'] = array();
1851 }
1852 if (!$completed) {
1853 $tasks[$task_name]['task_results'][$index]['status'][] = (int) $status * (-1);
1854 } else {
1855 $status_index = count($tasks[$task_name]['task_results'][$index]['status']) - 1;
1856 $tasks[$task_name]['task_results'][$index]['status'][$status_index] = abs($tasks[$task_name]['task_results'][$index]['status'][$status_index]);
1857 }
1858
1859 $this->update_tasks($tasks);
1860 //update_option('mwp_backup_tasks',$tasks);
1861 }
1862 }
1863
1864 function update_tasks($tasks)
1865 {
1866 $this->tasks = $tasks;
1867 update_option('mwp_backup_tasks', $tasks);
1868 }
1869
1870 }
1871
1872 ?>