PluginProbe
ManageWP Worker / 3.9.15
ManageWP Worker v3.9.15
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.15, at backup.class.php

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