PluginProbe
ManageWP Worker / 3.9.14
ManageWP Worker v3.9.14
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.14, at backup.class.php

1,917 lines 70.3 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->wpdb_reconnect();
399 $this->update_status($task_name, $this->statuses['ftp'], true);
400 }
401
402 if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
403 $this->update_status($task_name, $this->statuses['s3']);
404 $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
405 $amazons3_result = $this->amazons3_backup($account_info['mwp_amazon_s3']);
406 if ($amazons3_result !== true && $del_host_file) {
407 @unlink($backup_file);
408 }
409 if (is_array($amazons3_result) && isset($amazons3_result['error'])) {
410 return $amazons3_result;
411 }
412 $this->wpdb_reconnect();
413 $this->update_status($task_name, $this->statuses['s3'], true);
414 }
415
416 if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
417 $this->update_status($task_name, $this->statuses['dropbox']);
418 $account_info['mwp_dropbox']['backup_file'] = $backup_file;
419 $dropbox_result = $this->dropbox_backup($account_info['mwp_dropbox']);
420 if ($dropbox_result !== true && $del_host_file) {
421 @unlink($backup_file);
422 }
423
424 if (is_array($dropbox_result) && isset($dropbox_result['error'])) {
425 return $dropbox_result;
426 }
427 $this->wpdb_reconnect();
428 $this->update_status($task_name, $this->statuses['dropbox'], true);
429 }
430
431 if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
432 $this->update_status($task_name, $this->statuses['email']);
433 $account_info['mwp_email']['task_name'] = $task_name;
434 $account_info['mwp_email']['file_path'] = $backup_file;
435
436 $email_result = $this->email_backup($account_info['mwp_email']);
437 if (is_array($email_result) && isset($email_result['error'])) {
438 return $email_result;
439 }
440 $this->update_status($task_name, $this->statuses['email'], true);
441 }
442
443 if ($del_host_file) {
444 @unlink($backup_file);
445 }
446
447 } //end additional
448
449 //$this->update_status($task_name,$this->statuses['finished'],true);
450 return $backup_url; //Return url to backup file
451 }
452
453 function backup_full($task_name, $backup_file, $exclude = array(), $include = array())
454 {
455 global $zip_errors;
456 $sys = substr(PHP_OS, 0, 3);
457
458 $this->update_status($task_name, $this->statuses['db_dump']);
459 $db_result = $this->backup_db();
460
461 if ($db_result == false) {
462 return array(
463 'error' => 'Failed to backup database.'
464 );
465 } else if (is_array($db_result) && isset($db_result['error'])) {
466 return array(
467 'error' => $db_result['error']
468 );
469 }
470
471 $this->update_status($task_name, $this->statuses['db_dump'], true);
472 $this->update_status($task_name, $this->statuses['db_zip']);
473 $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
474 $comp_level = $disable_comp ? '-0' : '-1';
475
476 $zip = $this->get_zip();
477 //Add database file
478 chdir(MWP_BACKUP_DIR);
479 $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
480 ob_start();
481 $result = $this->mmb_exec($command);
482 ob_get_clean();
483
484
485 if (!$result) {
486 define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
487 require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
488 $archive = new PclZip($backup_file);
489
490 if ($disable_comp) {
491 $result_db = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION);
492 } else {
493 $result_db = $archive->add($db_result, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR);
494 }
495
496 @unlink($db_result);
497 @rmdir(MWP_DB_DIR);
498
499 if (!$result_db) {
500 return array(
501 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
502 );
503 }
504 }
505
506 @unlink($db_result);
507 @rmdir(MWP_DB_DIR);
508
509 $this->update_status($task_name, $this->statuses['db_zip'], true);
510
511
512 //Always remove backup folders
513 $remove = array(
514 trim(basename(WP_CONTENT_DIR)) . "/managewp/backups",
515 trim(basename(WP_CONTENT_DIR)) . "/" . md5('mmb-worker') . "/mwp_backups"
516 );
517
518 //Exclude paths
519 $exclude_data = "-x";
520
521 if (!empty($exclude)) {
522 foreach ($exclude as $data) {
523 if (is_dir(ABSPATH . $data)) {
524 if ($sys == 'WIN')
525 $exclude_data .= " $data/*.*";
526 else
527 $exclude_data .= " '$data/*'";
528 } else {
529 if ($sys == 'WIN')
530 $exclude_data .= " $data";
531 else
532 $exclude_data .= " '$data'";
533 }
534 }
535 }
536
537 foreach ($remove as $data) {
538 if ($sys == 'WIN')
539 $exclude_data .= " $data/*.*";
540 else
541 $exclude_data .= " '$data/*'";
542 }
543
544 //Include paths by default
545 $add = array(
546 trim(WPINC),
547 trim(basename(WP_CONTENT_DIR)),
548 "wp-admin"
549 );
550
551 $include_data = ". -i";
552 foreach ($add as $data) {
553 if ($sys == 'WIN')
554 $include_data .= " $data/*.*";
555 else
556 $include_data .= " '$data/*'";
557 }
558
559 //Additional includes?
560 if (!empty($include)) {
561 foreach ($include as $data) {
562 if ($data) {
563 if ($sys == 'WIN')
564 $include_data .= " $data/*.*";
565 else
566 $include_data .= " '$data/*'";
567 }
568 }
569 }
570
571 $this->update_status($task_name, $this->statuses['files_zip']);
572 chdir(ABSPATH);
573 ob_start();
574 $command = "$zip -q -j $comp_level $backup_file * $exclude_data";
575 $result_f = $this->mmb_exec($command, false, true);
576
577 if (!$result_f || $result_f == 18) { // disregard permissions error, file can't be accessed
578 $command = "$zip -q -r $comp_level $backup_file $include_data $exclude_data";
579 $result_d = $this->mmb_exec($command, false, true);
580 if ($result_d && $result_d != 18) {
581 @unlink($backup_file);
582 if ($result_d > 0 && $result_d < 18)
583 return array(
584 'error' => 'Failed to archive files (' . $zip_errors[$result_d] . ') .'
585 );
586 else
587 return array(
588 'error' => 'Failed to archive files.'
589 );
590 }
591 }
592 ob_get_clean();
593
594 if ($result_f && $result_f != 18) { //Try pclZip
595
596 if (!isset($archive)) {
597 define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
598 require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
599 $archive = new PclZip($backup_file);
600 }
601
602 //Include paths
603 $include_data = array();
604 if (!empty($include)) {
605 foreach ($include as $data) {
606 if ($data && file_exists(ABSPATH . $data))
607 $include_data[] = ABSPATH . $data . '/';
608 }
609 }
610
611 foreach ($add as $data) {
612 if (file_exists(ABSPATH . $data))
613 $include_data[] = ABSPATH . $data . '/';
614 }
615
616 //Include root files
617 if ($handle = opendir(ABSPATH)) {
618 while (false !== ($file = readdir($handle))) {
619 if ($file != "." && $file != ".." && !is_dir($file) && file_exists(ABSPATH . $file)) {
620 $include_data[] = ABSPATH . $file;
621 }
622 }
623 closedir($handle);
624 }
625
626 if ($disable_comp) {
627 $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_NO_COMPRESSION);
628 } else {
629 $result = $archive->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH);
630 }
631 if (!$result) {
632 @unlink($backup_file);
633 return array(
634 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
635 );
636 }
637
638 //Now exclude paths
639 $exclude_data = array();
640 if (!empty($exclude)) {
641 foreach ($exclude as $data) {
642 if (is_dir(ABSPATH . $data))
643 $exclude_data[] = $data . '/';
644 else
645 $exclude_data[] = $data;
646 }
647 }
648
649 foreach ($remove as $rem) {
650 $exclude_data[] = $rem . '/';
651 }
652
653 $result_excl = $archive->delete(PCLZIP_OPT_BY_NAME, $exclude_data);
654 if (!$result_excl) {
655 @unlink($backup_file);
656 return array(
657 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
658 );
659 }
660
661 }
662
663 //Reconnect
664 $this->wpdb_reconnect();
665
666 $this->update_status($task_name, $this->statuses['files_zip'], true);
667 return true;
668 }
669
670
671 function backup_db()
672 {
673 $db_folder = MWP_DB_DIR . '/';
674 if (!file_exists($db_folder)) {
675 if (!mkdir($db_folder, 0755, true))
676 return array(
677 'error' => 'Error creating database backup folder (' . $db_folder . '). Make sure you have corrrect write permissions.'
678 );
679 }
680
681 $file = $db_folder . DB_NAME . '.sql';
682 $result = $this->backup_db_dump($file); // try mysqldump always then fallback to php dump
683 return $result;
684 }
685
686 function backup_db_dump($file)
687 {
688 global $wpdb;
689 $paths = $this->check_mysql_paths();
690 $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
691 $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;
692 ob_start();
693 $result = $this->mmb_exec($command);
694 ob_get_clean();
695
696 if (!$result) { // Fallback to php
697 $result = $this->backup_db_php($file);
698 return $result;
699 }
700
701 if (filesize($file) == 0 || !is_file($file) || !$result) {
702 @unlink($file);
703 return false;
704 } else {
705 return $file;
706 }
707 }
708
709 function backup_db_php($file)
710 {
711 global $wpdb;
712 $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
713 foreach ($tables as $table) {
714 //drop existing table
715 $dump_data = "DROP TABLE IF EXISTS $table[0];";
716 //create table
717 $create_table = $wpdb->get_row("SHOW CREATE TABLE $table[0]", ARRAY_N);
718 $dump_data .= "\n\n" . $create_table[1] . ";\n\n";
719
720 $count = $wpdb->get_var("SELECT count(*) FROM $table[0]");
721 if ($count > 100)
722 $count = ceil($count / 100);
723 else if ($count > 0)
724 $count = 1;
725
726 for ($i = 0; $i < $count; $i++) {
727 $low_limit = $i * 100;
728 $qry = "SELECT * FROM $table[0] LIMIT $low_limit, 100";
729 $rows = $wpdb->get_results($qry, ARRAY_A);
730 if (is_array($rows)) {
731 foreach ($rows as $row) {
732 //insert single row
733 $dump_data .= "INSERT INTO $table[0] VALUES(";
734 $num_values = count($row);
735 $j = 1;
736 foreach ($row as $value) {
737 $value = addslashes($value);
738 $value = preg_replace("/\n/Ui", "\\n", $value);
739 $num_values == $j ? $dump_data .= "'" . $value . "'" : $dump_data .= "'" . $value . "', ";
740 $j++;
741 unset($value);
742 }
743 $dump_data .= ");\n";
744 }
745 }
746 }
747 $dump_data .= "\n\n\n";
748
749 unset($rows);
750 file_put_contents($file, $dump_data, FILE_APPEND);
751 unset($dump_data);
752 }
753
754 if (filesize($file) == 0 || !is_file($file)) {
755 @unlink($file);
756 return array(
757 'error' => 'Database backup failed. Try to enable MySQL dump on your server.'
758 );
759 }
760
761 return $file;
762
763 }
764
765 function restore($args)
766 {
767 global $wpdb;
768 if (empty($args)) {
769 return false;
770 }
771
772 extract($args);
773 @ini_set('memory_limit', '256M');
774 @set_time_limit(600);
775
776 $unlink_file = true; //Delete file after restore
777
778 //Detect source
779 if ($backup_url) {
780 //This is for clone (overwrite)
781 include_once ABSPATH . 'wp-admin/includes/file.php';
782 $backup_file = download_url($backup_url);
783 if (is_wp_error($backup_file)) {
784 return array(
785 'error' => $backup_file->get_error_message()
786 );
787 }
788 $what = 'full';
789 } else {
790 $tasks = $this->tasks;
791 $task = $tasks[$task_name];
792 if (isset($task['task_results'][$result_id]['server'])) {
793 $backup_file = $task['task_results'][$result_id]['server']['file_path'];
794 $unlink_file = false; //Don't delete file if stored on server
795 } elseif (isset($task['task_results'][$result_id]['ftp'])) {
796 $ftp_file = $task['task_results'][$result_id]['ftp'];
797 $args = $task['task_args']['account_info']['mwp_ftp'];
798 $args['backup_file'] = $ftp_file;
799 $backup_file = $this->get_ftp_backup($args);
800 if ($backup_file == false) {
801 return array(
802 'error' => 'Failed to download file from FTP.'
803 );
804 }
805 } elseif (isset($task['task_results'][$result_id]['amazons3'])) {
806 $amazons3_file = $task['task_results'][$result_id]['amazons3'];
807 $args = $task['task_args']['account_info']['mwp_amazon_s3'];
808 $args['backup_file'] = $ftp_file;
809 $backup_file = $this->get_amazons3_backup($args);
810 if ($backup_file == false) {
811 return array(
812 'error' => 'Failed to download file from Amazon S3.'
813 );
814 }
815 }
816
817 $what = $tasks[$task_name]['task_args']['what'];
818 }
819
820 if ($backup_file && file_exists($backup_file)) {
821 if ($overwrite) {
822 //Keep old db credentials before overwrite
823 if (!copy(ABSPATH . 'wp-config.php', ABSPATH . 'mwp-temp-wp-config.php')) {
824 @unlink($backup_file);
825 return array(
826 'error' => 'Error creating wp-config. Please check your write permissions.'
827 );
828 }
829
830 $db_host = DB_HOST;
831 $db_user = DB_USER;
832 $db_password = DB_PASSWORD;
833 $home = rtrim(get_option('home'), "/");
834 $site_url = get_option('site_url');
835
836 $clone_options = array();
837 if (trim($clone_from_url) || trim($mwp_clone)) {
838
839 $clone_options['_worker_nossl_key'] = get_option('_worker_nossl_key');
840 $clone_options['_worker_public_key'] = get_option('_worker_public_key');
841 $clone_options['_action_message_id'] = get_option('_action_message_id');
842
843 }
844
845 $clone_options['mwp_backup_tasks'] = serialize(get_option('mwp_backup_tasks'));
846 $clone_options['mwp_notifications'] = serialize(get_option('mwp_notifications'));
847
848
849 }
850
851
852 chdir(ABSPATH);
853 $unzip = $this->get_unzip();
854 $command = "$unzip -o $backup_file";
855 ob_start();
856 $result = $this->mmb_exec($command);
857 ob_get_clean();
858
859 if (!$result) { //fallback to pclzip
860 define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
861 require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
862 $archive = new PclZip($backup_file);
863 $result = $archive->extract(PCLZIP_OPT_PATH, ABSPATH, PCLZIP_OPT_REPLACE_NEWER);
864 }
865
866 if ($unlink_file) {
867 @unlink($backup_file);
868 }
869
870 if (!$result) {
871 return array(
872 'error' => 'Failed to unzip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
873 );
874 }
875
876 $db_result = $this->restore_db();
877
878 if (!$db_result) {
879 return array(
880 'error' => 'Error restoring database.'
881 );
882 } else if(is_array($db_result) && isset($db_result['error'])){
883 return array(
884 'error' => $db_result['error']
885 );
886 }
887
888 } else {
889 return array(
890 'error' => 'Error restoring. Cannot find backup file.'
891 );
892 }
893
894 //Replace options and content urls
895 if ($overwrite) {
896 //Get New Table prefix
897 $new_table_prefix = trim($this->get_table_prefix());
898 //Retrieve old wp_config
899 @unlink(ABSPATH . 'wp-config.php');
900 //Replace table prefix
901 $lines = file(ABSPATH . 'mwp-temp-wp-config.php');
902
903 foreach ($lines as $line) {
904 if (strstr($line, '$table_prefix')) {
905 $line = '$table_prefix = "' . $new_table_prefix . '";' . PHP_EOL;
906 }
907 file_put_contents(ABSPATH . 'wp-config.php', $line, FILE_APPEND);
908 }
909
910 @unlink(ABSPATH . 'mwp-temp-wp-config.php');
911
912 //Replace options
913 $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = 'home'";
914 $old = $wpdb->get_var($wpdb->prepare($query));
915 $old = rtrim($old, "/");
916 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$home' WHERE option_name = 'home'";
917 $wpdb->query($wpdb->prepare($query));
918 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$home' WHERE option_name = 'siteurl'";
919 $wpdb->query($wpdb->prepare($query));
920 //Replace content urls
921 $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(.*)\"'";
922 $wpdb->query($wpdb->prepare($query));
923
924 if (trim($new_password)) {
925 $new_password = wp_hash_password($new_password);
926 }
927 if (!trim($clone_from_url) && !trim($mwp_clone)) {
928 if ($new_user && $new_password) {
929 $query = "UPDATE " . $new_table_prefix . "users SET user_login = '$new_user', user_pass = '$new_password' WHERE user_login = '$old_user'";
930 $wpdb->query($wpdb->prepare($query));
931 }
932 } else {
933 if ($clone_from_url) {
934 if ($new_user && $new_password) {
935 $query = "UPDATE " . $new_table_prefix . "users SET user_pass = '$new_password' WHERE user_login = '$new_user'";
936 $wpdb->query($wpdb->prepare($query));
937 }
938 }
939
940 if ($mwp_clone) {
941 if ($admin_email) {
942 //Clean Install
943 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$admin_email' WHERE option_name = 'admin_email'";
944 $wpdb->query($wpdb->prepare($query));
945 $query = "SELECT * FROM " . $new_table_prefix . "users LIMIT 1";
946 $temp_user = $wpdb->get_row($query);
947 if (!empty($temp_user)) {
948 $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'";
949 $wpdb->query($wpdb->prepare($query));
950 }
951
952 }
953 }
954 }
955
956 if (is_array($clone_options) && !empty($clone_options)) {
957 foreach ($clone_options as $key => $option) {
958 if (!empty($key)) {
959 $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = '$key'";
960 $res = $wpdb->get_var($query);
961 if ($res == false) {
962 $query = "INSERT INTO " . $new_table_prefix . "options (option_value,option_name) VALUES('$option','$key')";
963 $wpdb->query($wpdb->prepare($query));
964 } else {
965 $query = "UPDATE " . $new_table_prefix . "options SET option_value = '$option' WHERE option_name = '$key'";
966 $wpdb->query($wpdb->prepare($query));
967 }
968 }
969 }
970 }
971 }
972
973 return true;
974 }
975
976 function restore_db()
977 {
978 global $wpdb;
979 $paths = $this->check_mysql_paths();
980 $file_path = ABSPATH . 'mwp_db';
981 $file_name = glob($file_path . '/*.sql');
982 $file_name = $file_name[0];
983
984 if(!$file_name){
985 return array('error' => 'Cannot access database file.');
986 }
987
988 $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
989 $command = $brace . $paths['mysql'] . $brace . ' --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" ' . DB_NAME . ' < ' . $brace . $file_name . $brace;
990
991 ob_start();
992 $result = $this->mmb_exec($command);
993 ob_get_clean();
994 if (!$result) {
995 //try php
996 $this->restore_db_php($file_name);
997 }
998
999
1000 @unlink($file_name);
1001 return true;
1002 }
1003
1004 function restore_db_php($file_name)
1005 {
1006 global $wpdb;
1007 $current_query = '';
1008 // Read in entire file
1009 $lines = file($file_name);
1010 // Loop through each line
1011 foreach ($lines as $line) {
1012 // Skip it if it's a comment
1013 if (substr($line, 0, 2) == '--' || $line == '')
1014 continue;
1015
1016 // Add this line to the current query
1017 $current_query .= $line;
1018 // If it has a semicolon at the end, it's the end of the query
1019 if (substr(trim($line), -1, 1) == ';') {
1020 // Perform the query
1021 $result = $wpdb->query($current_query);
1022 if ($result === false)
1023 return false;
1024 // Reset temp variable to empty
1025 $current_query = '';
1026 }
1027 }
1028
1029 @unlink($file_name);
1030 return true;
1031 }
1032
1033 function get_table_prefix()
1034 {
1035 $lines = file(ABSPATH . 'wp-config.php');
1036 foreach ($lines as $line) {
1037 if (strstr($line, '$table_prefix')) {
1038 $pattern = "/(\'|\")[^(\'|\")]*/";
1039 preg_match($pattern, $line, $matches);
1040 $prefix = substr($matches[0], 1);
1041 return $prefix;
1042 break;
1043 }
1044 }
1045 return 'wp_'; //default
1046 }
1047
1048 function optimize_tables()
1049 {
1050 global $wpdb;
1051 $query = 'SHOW TABLE STATUS FROM ' . DB_NAME;
1052 $tables = $wpdb->get_results($wpdb->prepare($query), ARRAY_A);
1053 foreach ($tables as $table) {
1054 if (in_array($table['Engine'], array(
1055 'MyISAM',
1056 'ISAM',
1057 'HEAP',
1058 'MEMORY',
1059 'ARCHIVE'
1060 )))
1061 $table_string .= $table['Name'] . ",";
1062 elseif ($table['Engine'] == 'InnoDB') {
1063 $optimize = $wpdb->query("ALTER TABLE {$table['Name']} ENGINE=InnoDB");
1064 }
1065 }
1066
1067 $table_string = rtrim($table_string);
1068 $optimize = $wpdb->query("OPTIMIZE TABLE $table_string");
1069
1070 return $optimize ? true : false;
1071 }
1072
1073 ### Function: Auto Detect MYSQL and MYSQL Dump Paths
1074 function check_mysql_paths()
1075 {
1076 global $wpdb;
1077 $paths = array(
1078 'mysql' => '',
1079 'mysqldump' => ''
1080 );
1081 if (substr(PHP_OS, 0, 3) == 'WIN') {
1082 $mysql_install = $wpdb->get_row("SHOW VARIABLES LIKE 'basedir'");
1083 if ($mysql_install) {
1084 $install_path = str_replace('\\', '/', $mysql_install->Value);
1085 $paths['mysql'] = $install_path . 'bin/mysql.exe';
1086 $paths['mysqldump'] = $install_path . 'bin/mysqldump.exe';
1087 } else {
1088 $paths['mysql'] = 'mysql.exe';
1089 $paths['mysqldump'] = 'mysqldump.exe';
1090 }
1091 } else {
1092 $paths['mysql'] = $this->mmb_exec('which mysql', true);
1093 if (empty($paths['mysql']))
1094 $paths['mysql'] = 'mysql'; // try anyway
1095
1096 $paths['mysqldump'] = $this->mmb_exec('which mysqldump', true);
1097 if (empty($paths['mysqldump']))
1098 $paths['mysqldump'] = 'mysqldump'; // try anyway
1099
1100 }
1101
1102
1103 return $paths;
1104 }
1105
1106 //Check if exec, system, passthru functions exist
1107 function check_sys()
1108 {
1109 if ($this->mmb_function_exists('exec'))
1110 return 'exec';
1111
1112 if ($this->mmb_function_exists('system'))
1113 return 'system';
1114
1115 if ($this->mmb_function_exists('passhtru'))
1116 return 'passthru';
1117
1118 return false;
1119
1120 }
1121
1122 function mmb_exec($command, $string = false, $rawreturn = false)
1123 {
1124 if ($command == '')
1125 return false;
1126
1127 if ($this->mmb_function_exists('exec')) {
1128 $log = @exec($command, $output, $return);
1129
1130 if ($string)
1131 return $log;
1132 if ($rawreturn)
1133 return $return;
1134
1135 return $return ? false : true;
1136 } elseif ($this->mmb_function_exists('system')) {
1137 $log = @system($command, $return);
1138
1139 if ($string)
1140 return $log;
1141
1142 if ($rawreturn)
1143 return $return;
1144
1145 return $return ? false : true;
1146 } elseif ($this->mmb_function_exists('passthru') && !$string) {
1147 $log = passthru($command, $return);
1148
1149 if ($rawreturn)
1150 return $return;
1151
1152 return $return ? false : true;
1153 }
1154
1155 if ($rawreturn)
1156 return -1;
1157
1158 return false;
1159 }
1160
1161 function get_zip()
1162 {
1163 $zip = $this->mmb_exec('which zip', true);
1164 if (!$zip)
1165 $zip = "zip";
1166 return $zip;
1167 }
1168
1169 function get_unzip()
1170 {
1171 $unzip = $this->mmb_exec('which unzip', true);
1172 if (!$unzip)
1173 $unzip = "unzip";
1174 return $unzip;
1175 }
1176
1177 function check_backup_compat()
1178 {
1179 $reqs = array();
1180 if (strpos($_SERVER['DOCUMENT_ROOT'], '/') === 0) {
1181 $reqs['Server OS']['status'] = 'Linux (or compatible)';
1182 $reqs['Server OS']['pass'] = true;
1183 } else {
1184 $reqs['Server OS']['status'] = 'Windows';
1185 $reqs['Server OS']['pass'] = true;
1186 $pass = false;
1187 }
1188 $reqs['PHP Version']['status'] = phpversion();
1189 if ((float) phpversion() >= 5.1) {
1190 $reqs['PHP Version']['pass'] = true;
1191 } else {
1192 $reqs['PHP Version']['pass'] = false;
1193 $pass = false;
1194 }
1195
1196
1197 if (is_writable(WP_CONTENT_DIR)) {
1198 $reqs['Backup Folder']['status'] = "writable";
1199 $reqs['Backup Folder']['pass'] = true;
1200 } else {
1201 $reqs['Backup Folder']['status'] = "not writable";
1202 $reqs['Backup Folder']['pass'] = false;
1203 }
1204
1205
1206 $file_path = MWP_BACKUP_DIR;
1207 $reqs['Backup Folder']['status'] .= ' (' . $file_path . ')';
1208
1209 if ($func = $this->check_sys()) {
1210 $reqs['Execute Function']['status'] = $func;
1211 $reqs['Execute Function']['pass'] = true;
1212 } else {
1213 $reqs['Execute Function']['status'] = "not found";
1214 $reqs['Execute Function']['info'] = "(will try PHP replacement)";
1215 $reqs['Execute Function']['pass'] = false;
1216 }
1217 $reqs['Zip']['status'] = $this->get_zip();
1218
1219 $reqs['Zip']['pass'] = true;
1220
1221
1222
1223 $reqs['Unzip']['status'] = $this->get_unzip();
1224
1225 $reqs['Unzip']['pass'] = true;
1226
1227 $paths = $this->check_mysql_paths();
1228
1229 if (!empty($paths['mysqldump'])) {
1230 $reqs['MySQL Dump']['status'] = $paths['mysqldump'];
1231 $reqs['MySQL Dump']['pass'] = true;
1232 } else {
1233 $reqs['MySQL Dump']['status'] = "not found";
1234 $reqs['MySQL Dump']['info'] = "(will try PHP replacement)";
1235 $reqs['MySQL Dump']['pass'] = false;
1236 }
1237
1238 $exec_time = ini_get('max_execution_time');
1239 $reqs['Execution time']['status'] = $exec_time ? $exec_time . "s" : 'unknown';
1240 $reqs['Execution time']['pass'] = true;
1241
1242 $mem_limit = ini_get('memory_limit');
1243 $reqs['Memory limit']['status'] = $mem_limit ? $mem_limit : 'unknown';
1244 $reqs['Memory limit']['pass'] = true;
1245
1246
1247 return $reqs;
1248 }
1249
1250 function email_backup($args)
1251 {
1252 $email = $args['email'];
1253
1254 if (!is_email($email)) {
1255 return array(
1256 'error' => 'Your email (' . $email . ') is not correct'
1257 );
1258 }
1259 $backup_file = $args['file_path'];
1260 $task_name = isset($args['task_name']) ? $args['task_name'] : '';
1261 if (file_exists($backup_file) && $email) {
1262 $attachments = array(
1263 $backup_file
1264 );
1265 $headers = 'From: ManageWP <no-reply@managewp.com>' . "\r\n";
1266 $subject = "ManageWP - " . $task_name . " - " . $this->site_name;
1267 ob_start();
1268 $result = wp_mail($email, $subject, $subject, $headers, $attachments);
1269 ob_end_clean();
1270
1271 }
1272
1273 if (!$result) {
1274 return array(
1275 'error' => 'Email not sent. Maybe your backup is too big for email or email server is not available on your website.'
1276 );
1277 }
1278 return true;
1279
1280 }
1281
1282 function ftp_backup($args)
1283 {
1284 extract($args);
1285 //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder, $ftp_site_folder
1286 $port = $ftp_port ? $ftp_port : 21; //default port is 21
1287 if ($ftp_ssl) {
1288 if (function_exists('ftp_ssl_connect')) {
1289 $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1290 } else {
1291 return array(
1292 'error' => 'Your server doesn\'t support SFTP',
1293 'partial' => 1
1294 );
1295 }
1296 } else {
1297 if (function_exists('ftp_connect')) {
1298 $conn_id = ftp_connect($ftp_hostname,$port);
1299 if ($conn_id === false) {
1300 return array(
1301 'error' => 'Failed to connect to ' . $ftp_hostname,
1302 'partial' => 1
1303 );
1304 }
1305 } else {
1306 return array(
1307 'error' => 'Your server doesn\'t support FTP',
1308 'partial' => 1
1309 );
1310 }
1311 }
1312 $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1313 if ($login === false) {
1314 return array(
1315 'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
1316 'partial' => 1
1317 );
1318 }
1319
1320 if($ftp_passive){
1321 @ftp_pasv($conn_id,true);
1322 }
1323
1324 @ftp_mkdir($conn_id, $ftp_remote_folder);
1325 if ($ftp_site_folder) {
1326 $ftp_remote_folder .= '/' . $this->site_name;
1327 }
1328 @ftp_mkdir($conn_id, $ftp_remote_folder);
1329
1330 $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
1331
1332 if ($upload === false) { //Try ascii
1333 $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
1334 }
1335 ftp_close($conn_id);
1336
1337 if ($upload === false) {
1338 return array(
1339 'error' => 'Failed to upload file to FTP. Please check your specified path.',
1340 'partial' => 1
1341 );
1342 }
1343
1344 return true;
1345 }
1346
1347 function remove_ftp_backup($args)
1348 {
1349 extract($args);
1350 //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
1351 $port = $ftp_port ? $ftp_port : 21; //default port is 21
1352 if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1353 $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1354 } else if (function_exists('ftp_connect')) {
1355 $conn_id = ftp_connect($ftp_hostname,$port);
1356 }
1357
1358 if ($conn_id) {
1359 $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1360 if ($ftp_site_folder)
1361 $ftp_remote_folder .= '/' . $this->site_name;
1362
1363 if($ftp_passive){
1364 @ftp_pasv($conn_id,true);
1365 }
1366
1367 $delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
1368
1369 ftp_close($conn_id);
1370 }
1371
1372 }
1373
1374 function get_ftp_backup($args)
1375 {
1376 extract($args);
1377 //Args: $ftp_username, $ftp_password, $ftp_hostname, $backup_file, $ftp_remote_folder
1378 $port = $ftp_port ? $ftp_port : 21; //default port is 21
1379 if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
1380 $conn_id = ftp_ssl_connect($ftp_hostname,$port);
1381
1382 } else if (function_exists('ftp_connect')) {
1383 $conn_id = ftp_connect($ftp_hostname,$port);
1384 if ($conn_id === false) {
1385 return false;
1386 }
1387 }
1388 $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
1389 if ($login === false) {
1390 return false;
1391 } else {
1392 }
1393
1394 if ($ftp_site_folder)
1395 $ftp_remote_folder .= '/' . $this->site_name;
1396
1397 if($ftp_passive){
1398 @ftp_pasv($conn_id,true);
1399 }
1400
1401 $temp = ABSPATH . 'mwp_temp_backup.zip';
1402 $get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
1403 if ($get === false) {
1404 return false;
1405 } else {
1406 }
1407 ftp_close($conn_id);
1408
1409 return $temp;
1410 }
1411
1412 function dropbox_backup($args)
1413 {
1414 require_once('lib/dropbox.php');
1415 extract($args);
1416
1417 //$email, $password, $backup_file, $destination, $dropbox_site_folder
1418
1419 $size = ceil(filesize($backup_file) / 1024);
1420 if ($size > 300000) {
1421 return array(
1422 'error' => 'Cannot upload file to Dropbox. Dropbox has upload limit of 300Mb per file.',
1423 'partial' => 1
1424 );
1425 }
1426
1427 if ($dropbox_site_folder == true)
1428 $dropbox_destination .= '/' . $this->site_name;
1429
1430 try {
1431 $uploader = new DropboxUploader($dropbox_username, $dropbox_password);
1432 $uploader->upload($backup_file, $dropbox_destination);
1433 }
1434 catch (Exception $e) {
1435 return array(
1436 'error' => $e->getMessage(),
1437 'partial' => 1
1438 );
1439 }
1440
1441 return true;
1442
1443 }
1444
1445 function amazons3_backup($args)
1446 {
1447 if ($this->mmb_function_exists('curl_init')) {
1448 require_once('lib/s3.php');
1449 extract($args);
1450
1451 if ($as3_site_folder == true)
1452 $as3_directory .= '/' . $this->site_name;
1453
1454 $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1455
1456 $s3 = new S3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
1457
1458 $s3->putBucket($as3_bucket, S3::ACL_PUBLIC_READ);
1459
1460 if ($s3->putObjectFile($backup_file, $as3_bucket, $as3_directory . '/' . basename($backup_file), S3::ACL_PRIVATE)) {
1461 return true;
1462 } else {
1463 return array(
1464 'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
1465 'partial' => 1
1466 );
1467 }
1468 } else {
1469 return array(
1470 'error' => 'You cannot use Amazon S3 on your server. Please enable curl first.',
1471 'partial' => 1
1472 );
1473 }
1474 }
1475
1476 function remove_amazons3_backup($args)
1477 {
1478 require_once('lib/s3.php');
1479 extract($args);
1480 if ($as3_site_folder == true)
1481 $as3_directory .= '/' . $this->site_name;
1482 $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1483 $s3 = new S3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
1484 $s3->deleteObject($as3_bucket, $as3_directory . '/' . $backup_file);
1485 }
1486
1487 function get_amazons3_backup($args)
1488 {
1489 require_once('lib/s3.php');
1490 extract($args);
1491 $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
1492 $s3 = new S3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
1493 if ($as3_site_folder == true)
1494 $as3_directory .= '/' . $this->site_name;
1495
1496 $s3->getObject($as3_bucket, $as3_directory . '/' . $backup_file, $temp);
1497 $temp = ABSPATH . 'mwp_temp_backup.zip';
1498 return $temp;
1499 }
1500
1501 function schedule_next($type, $schedule)
1502 {
1503 $schedule = explode("|", $schedule);
1504 if (empty($schedule))
1505 return false;
1506 switch ($type) {
1507
1508 case 'daily':
1509
1510 if ($schedule[1]) {
1511 $delay_time = $schedule[1] * 60;
1512 }
1513
1514 $current_hour = date("H");
1515 $schedule_hour = $schedule[0];
1516 if ($current_hour >= $schedule_hour)
1517 $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 1, date("Y"));
1518 else
1519 $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
1520 break;
1521
1522
1523 case 'weekly':
1524 if ($schedule[2]) {
1525 $delay_time = $schedule[2] * 60;
1526 }
1527 $current_weekday = date('w');
1528 $schedule_weekday = $schedule[1];
1529 $current_hour = date("H");
1530 $schedule_hour = $schedule[0];
1531
1532 if ($current_weekday > $schedule_weekday)
1533 $weekday_offset = 7 - ($week_day - $task_schedule[1]);
1534 else
1535 $weekday_offset = $schedule_weekday - $current_weekday;
1536
1537
1538 if (!$weekday_offset) { //today is scheduled weekday
1539 if ($current_hour >= $schedule_hour)
1540 $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 7, date("Y"));
1541 else
1542 $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
1543 } else {
1544 $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + $weekday_offset, date("Y"));
1545 }
1546
1547 break;
1548
1549 case 'monthly':
1550 if ($schedule[2]) {
1551 $delay_time = $schedule[2] * 60;
1552 }
1553 $current_monthday = date('j');
1554 $schedule_monthday = $schedule[1];
1555 $current_hour = date("H");
1556 $schedule_hour = $schedule[0];
1557
1558 if ($current_monthday > $schedule_monthday) {
1559 $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
1560 } else if ($current_monthday < $schedule_monthday) {
1561 $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
1562 } else if ($current_monthday == $schedule_monthday) {
1563 if ($current_hour >= $schedule_hour)
1564 $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
1565 else
1566 $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
1567 break;
1568 }
1569
1570 break;
1571 default:
1572 break;
1573 }
1574
1575 if ($delay_time) {
1576 $time += $delay_time;
1577 }
1578
1579
1580 return $time;
1581
1582 }
1583
1584 //Parse task arguments for info on master
1585 function get_backup_stats()
1586 {
1587 $stats = array();
1588 $tasks = $this->tasks;
1589 if (is_array($tasks) && !empty($tasks)) {
1590 foreach ($tasks as $task_name => $info) {
1591 if (is_array($info['task_results']) && !empty($info['task_results'])) {
1592 foreach ($info['task_results'] as $key => $result) {
1593 if (isset($result['server']) && !isset($result['error'])) {
1594 if (!file_exists($result['server']['file_path'])) {
1595 $info['task_results'][$key]['error'] = 'Backup created but manually removed from server.';
1596 }
1597 }
1598 }
1599 }
1600
1601 $stats[$task_name] = array_values($info['task_results']);
1602
1603 }
1604 }
1605 return $stats;
1606 }
1607
1608 function get_next_schedules()
1609 {
1610 $stats = array();
1611 $tasks = $this->tasks;
1612 if (is_array($tasks) && !empty($tasks)) {
1613 foreach ($tasks as $task_name => $info) {
1614 $stats[$task_name] = $info['task_args']['next'];
1615 }
1616 }
1617 return $stats;
1618 }
1619
1620 function remove_old_backups($task_name)
1621 {
1622 //Check for previous failed backups first
1623 $this->cleanup();
1624
1625 //Remove by limit
1626 $backups = $this->tasks;
1627 if ($task_name == 'Backup Now') {
1628 $num = 0;
1629 } else {
1630 $num = 1;
1631 }
1632
1633
1634 if ((count($backups[$task_name]['task_results']) - $num) >= $backups[$task_name]['task_args']['limit']) {
1635 //how many to remove ?
1636 $remove_num = (count($backups[$task_name]['task_results']) - $num - $backups[$task_name]['task_args']['limit']) + 1;
1637 for ($i = 0; $i < $remove_num; $i++) {
1638 //Remove from the server
1639 if (isset($backups[$task_name]['task_results'][$i]['server'])) {
1640 @unlink($backups[$task_name]['task_results'][$i]['server']['file_path']);
1641 }
1642
1643 //Remove from ftp
1644 if (isset($backups[$task_name]['task_results'][$i]['ftp'])) {
1645 $ftp_file = $backups[$task_name]['task_results'][$i]['ftp'];
1646 $args = $backups[$task_name]['task_args']['account_info']['mwp_ftp'];
1647 $args['backup_file'] = $ftp_file;
1648 $this->remove_ftp_backup($args);
1649 }
1650
1651 if (isset($backups[$task_name]['task_results'][$i]['amazons3'])) {
1652 $amazons3_file = $backups[$task_name]['task_results'][$i]['amazons3'];
1653 $args = $backups[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
1654 $args['backup_file'] = $amazons3_file;
1655 $this->remove_amazons3_backup($args);
1656 }
1657
1658 if (isset($backups[$task_name]['task_results'][$i]['dropbox'])) {
1659 //To do: dropbox remove
1660 }
1661
1662 //Remove database backup info
1663 unset($backups[$task_name]['task_results'][$i]);
1664
1665 } //end foreach
1666
1667 $backups[$task_name]['task_results'] = array_values($backups[$task_name]['task_results']);
1668 $this->update_tasks($backups);
1669 //update_option('mwp_backup_tasks', $backups);
1670 }
1671 }
1672
1673 /**
1674 * Delete specified backup
1675 * Args: $task_name, $result_id
1676 */
1677
1678 function delete_backup($args)
1679 {
1680 if (empty($args))
1681 return false;
1682 extract($args);
1683
1684 $tasks = $this->tasks;
1685 $task = $tasks[$task_name];
1686 $backups = $task['task_results'];
1687 $backup = $backups[$result_id];
1688
1689 if (isset($backup['server'])) {
1690 @unlink($backup['server']['file_path']);
1691 }
1692
1693 //Remove from ftp
1694 if (isset($backup['ftp'])) {
1695 $ftp_file = $backup['ftp'];
1696 $args = $tasks[$task_name]['task_args']['account_info']['mwp_ftp'];
1697 $args['backup_file'] = $ftp_file;
1698 $this->remove_ftp_backup($args);
1699 }
1700
1701 if (isset($backup['amazons3'])) {
1702 $amazons3_file = $backup['amazons3'];
1703 $args = $tasks[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
1704 $args['backup_file'] = $amazons3_file;
1705 $this->remove_amazons3_backup($args);
1706 }
1707
1708 if (isset($backup['dropbox'])) {
1709 }
1710
1711 unset($backups[$result_id]);
1712
1713 if (count($backups)) {
1714 $tasks[$task_name]['task_results'] = $backups;
1715 } else {
1716 unset($tasks[$task_name]['task_results']);
1717 }
1718
1719 $this->update_tasks($tasks);
1720 //update_option('mwp_backup_tasks', $tasks);
1721 return true;
1722
1723 }
1724
1725 function cleanup()
1726 {
1727 $tasks = $this->tasks;
1728 $backup_folder = WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups/';
1729 $backup_folder_new = MWP_BACKUP_DIR . '/';
1730 $files = glob($backup_folder . "*");
1731 $new = glob($backup_folder_new . "*");
1732
1733 //Failed db files first
1734 $db_folder = MWP_DB_DIR . '/';
1735 $db_files = glob($db_folder . "*");
1736 if (is_array($db_files) && !empty($db_files)) {
1737 foreach ($db_files as $file) {
1738 @unlink($file);
1739 }
1740 @rmdir(MWP_DB_DIR);
1741 }
1742
1743
1744 //clean_old folder?
1745 if ((basename($files[0]) == 'index.php' && count($files) == 1) || (empty($files))) {
1746 foreach ($files as $file) {
1747 @unlink($file);
1748 }
1749 @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups');
1750 @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker'));
1751 }
1752
1753
1754 foreach ($new as $b) {
1755 $files[] = $b;
1756 }
1757 $deleted = array();
1758
1759 if (is_array($files) && count($files)) {
1760 $results = array();
1761 if (!empty($tasks)) {
1762 foreach ((array) $tasks as $task) {
1763 if (isset($task['task_results']) && count($task['task_results'])) {
1764 foreach ($task['task_results'] as $backup) {
1765 if (isset($backup['server'])) {
1766 $results[] = $backup['server']['file_path'];
1767 }
1768 }
1769 }
1770 }
1771 }
1772
1773 $num_deleted = 0;
1774 foreach ($files as $file) {
1775 if (!in_array($file, $results) && basename($file) != 'index.php') {
1776 @unlink($file);
1777 $deleted[] = basename($file);
1778 $num_deleted++;
1779 }
1780 }
1781 }
1782
1783
1784
1785 return $deleted;
1786 }
1787
1788
1789 function remote_backup_now($args)
1790 {
1791 if (!empty($args))
1792 extract($args);
1793
1794 $tasks = $this->tasks;
1795 $task = $tasks['Backup Now'];
1796
1797 if (!empty($task)) {
1798 extract($task['task_args']);
1799 }
1800
1801 $results = $task['task_results'];
1802
1803 if (is_array($results) && count($results)) {
1804 $backup_file = $results[count($results) - 1]['server']['file_path'];
1805 }
1806
1807 if ($backup_file && file_exists($backup_file)) {
1808 //FTP, Amazon S3 or Dropbox
1809 if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
1810 $account_info['mwp_ftp']['backup_file'] = $backup_file;
1811 $return = $this->ftp_backup($account_info['mwp_ftp']);
1812 }
1813
1814 if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
1815 $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
1816 $return = $this->amazons3_backup($account_info['mwp_amazon_s3']);
1817 }
1818
1819 if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
1820 $account_info['mwp_dropbox']['backup_file'] = $backup_file;
1821 $return = $this->dropbox_backup($account_info['mwp_dropbox']);
1822 }
1823
1824 if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
1825 $account_info['mwp_email']['file_path'] = $backup_file;
1826 $account_info['mwp_email']['task_name'] = 'Backup Now';
1827 $return = $this->email_backup($account_info['mwp_email']);
1828 }
1829
1830
1831 if ($return == true && $del_host_file) {
1832 @unlink($backup_file);
1833 unset($tasks['Backup Now']['task_results'][count($results) - 1]['server']);
1834 $this->update_tasks($tasks);
1835 //update_option('mwp_backup_tasks', $tasks);
1836 }
1837
1838
1839
1840 } else {
1841 $return = array(
1842 'error' => 'Backup file not found on your server. Please try again.'
1843 );
1844 }
1845
1846 return $return;
1847
1848 }
1849
1850 function validate_task($args, $url)
1851 {
1852 if (!class_exists('WP_Http')) {
1853 include_once(ABSPATH . WPINC . '/class-http.php');
1854 }
1855 $params = array();
1856 $params['body'] = $args;
1857 $result = wp_remote_post($url, $params);
1858 if (is_array($result) && $result['body'] == 'mwp_delete_task') {
1859 //$tasks = $this->get_backup_settings();
1860 $tasks = $this->tasks;
1861 unset($tasks[$args['task_name']]);
1862 $this->update_tasks($tasks);
1863 $this->cleanup();
1864 exit;
1865 }
1866 }
1867
1868 function update_status($task_name, $status, $completed = false)
1869 {
1870 /* Statuses:
1871 0 - Backup started
1872 1 - DB dump
1873 2 - DB ZIP
1874 3 - Files ZIP
1875 4 - Amazon S3
1876 5 - Dropbox
1877 6 - FTP
1878 7 - Email
1879 100 - Finished
1880 */
1881 if ($task_name != 'Backup Now') {
1882 $tasks = $this->tasks;
1883 $index = count($tasks[$task_name]['task_results']) - 1;
1884 if (!is_array($tasks[$task_name]['task_results'][$index]['status'])) {
1885 $tasks[$task_name]['task_results'][$index]['status'] = array();
1886 }
1887 if (!$completed) {
1888 $tasks[$task_name]['task_results'][$index]['status'][] = (int) $status * (-1);
1889 } else {
1890 $status_index = count($tasks[$task_name]['task_results'][$index]['status']) - 1;
1891 $tasks[$task_name]['task_results'][$index]['status'][$status_index] = abs($tasks[$task_name]['task_results'][$index]['status'][$status_index]);
1892 }
1893
1894 $this->update_tasks($tasks);
1895 //update_option('mwp_backup_tasks',$tasks);
1896 }
1897 }
1898
1899 function update_tasks($tasks)
1900 {
1901 $this->tasks = $tasks;
1902 update_option('mwp_backup_tasks', $tasks);
1903 }
1904
1905 function wpdb_reconnect(){
1906 global $wpdb;
1907 //Reconnect to avoid timeout problem after ZIP files
1908 if(class_exists('wpdb') && function_exists('wp_set_wpdb_vars')){
1909 @mysql_close($wpdb->dbh);
1910 $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
1911 wp_set_wpdb_vars();
1912 }
1913 }
1914
1915 }
1916
1917 ?>