Version Description
- 11/19/2012 =
- Moved screenshot into assets, reducing plugin download size
Download this release
Release Info
Developer | DavidAnderson |
Plugin | UpdraftPlus WordPress Backup Plugin |
Version | 0.8.51 |
Comparing to | |
See all releases |
Code changes from version 0.9.1 to 0.8.51
- readme.txt +8 -15
- updraftplus.php +51 -182
readme.txt
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
-
=== UpdraftPlus ===
|
2 |
Contributors: David Anderson
|
3 |
Tags: backup, restore, database, cloud, amazon, s3, Amazon S3, google drive, google, gdrive, ftp, cloud, updraft, back up
|
4 |
Requires at least: 3.2
|
5 |
-
Tested up to: 3.
|
6 |
Stable tag: 0.8.51
|
7 |
Donate link: http://david.dw-perspective.org.uk/donate
|
8 |
License: GPLv2 or later
|
9 |
|
10 |
-
== Upgrade Notice ==
|
11 |
-
Screenshots now moved into assets directory. Also, try the trunk for 0.9 with new code for re-trying of failed uploads.
|
12 |
-
|
13 |
== Description ==
|
14 |
|
15 |
-
UpdraftPlus simplifies backups and restoration.
|
|
|
|
|
|
|
16 |
|
17 |
== Installation ==
|
18 |
|
@@ -33,11 +33,7 @@ You can check the changelog for changes; but the original Updraft, before I fork
|
|
33 |
|
34 |
That's very good of you, thank you. You are looking for WordShell, <a href="http://wordshell.net">http://wordshell.net</a>.
|
35 |
|
36 |
-
=
|
37 |
-
|
38 |
-
From version 0.9.0, UpdraftPlus features a resumption feature - if you wait 5 minutes and visit a page on your site, then it should re-try not-yet-uploaded files. If that fails, then turn on debugging and paste the debug log (log in via FTP, and look in wp-content/updraft) into the support forum.
|
39 |
-
|
40 |
-
= I want to restore, but have failed to do so from the WP Admin console =
|
41 |
|
42 |
That's no problem. If you have your backed files, then you simply need to unzip them into the right places. UpdraftPlus does not back up the WordPress core - you can just get a fresh copy of that from www.wordpress.org. After installing that, then unzip the zip files for your uploads, themes and plugins back into the wp-content directory. Then re-install the database (e.g. by running it through PHPMyAdmin). Please don't ask me how to carry out these steps - they are basic operations which you can hire any of hundreds of thousands of people to show you how to do.
|
43 |
|
@@ -54,7 +50,7 @@ Unless you disable any of these, it will back up your database (all tables which
|
|
54 |
It does not back up WordPress core (since you can always get another copy of this from wordpress.org), and does not back up any extra files which you have added outside of the WordPress content directory (files which, by their nature, are unknown to WordPress). By default the WordPress content directory is "wp-content" in your WordPress root. It will not back up database tables which do not have the WordPress prefix (i.e. database tables from other applications but sharing a database with WordPress).
|
55 |
|
56 |
= Any known bugs ? =
|
57 |
-
The major one is that backups of very large sites (lots of uploaded media) can fail due to timing out. If your site is very large, then be doubly-sure to test when setting up that your backups are not empty.
|
58 |
|
59 |
= I encrypted my database - how do I decrypt it? =
|
60 |
|
@@ -70,9 +66,6 @@ Contact me! This is a complex plugin and the only way I can ensure it's robust i
|
|
70 |
|
71 |
== Changelog ==
|
72 |
|
73 |
-
= 0.9.1 - 11/19/2012 =
|
74 |
-
* Failed uploads can now be resumed, giving really big blogs a better opportunity to eventually succeed uploading
|
75 |
-
|
76 |
= 0.8.51 - 11/19/2012 =
|
77 |
* Moved screenshot into assets, reducing plugin download size
|
78 |
|
1 |
+
=== UpdraftPlus Backup ===
|
2 |
Contributors: David Anderson
|
3 |
Tags: backup, restore, database, cloud, amazon, s3, Amazon S3, google drive, google, gdrive, ftp, cloud, updraft, back up
|
4 |
Requires at least: 3.2
|
5 |
+
Tested up to: 3.4.2
|
6 |
Stable tag: 0.8.51
|
7 |
Donate link: http://david.dw-perspective.org.uk/donate
|
8 |
License: GPLv2 or later
|
9 |
|
|
|
|
|
|
|
10 |
== Description ==
|
11 |
|
12 |
+
UpdraftPlus simplifies backups (and restoration). Backup into the cloud (S3, Google Drive, FTP, and email) and restore with a single click. Backups of files and database can have separate schedules.
|
13 |
+
|
14 |
+
== Upgrade Notice ==
|
15 |
+
Now backs up all directories found in the WP content directory (not just plugins/themes/uploads)
|
16 |
|
17 |
== Installation ==
|
18 |
|
33 |
|
34 |
That's very good of you, thank you. You are looking for WordShell, <a href="http://wordshell.net">http://wordshell.net</a>.
|
35 |
|
36 |
+
= I want to restore, but cannot do so from the WP Admin console =
|
|
|
|
|
|
|
|
|
37 |
|
38 |
That's no problem. If you have your backed files, then you simply need to unzip them into the right places. UpdraftPlus does not back up the WordPress core - you can just get a fresh copy of that from www.wordpress.org. After installing that, then unzip the zip files for your uploads, themes and plugins back into the wp-content directory. Then re-install the database (e.g. by running it through PHPMyAdmin). Please don't ask me how to carry out these steps - they are basic operations which you can hire any of hundreds of thousands of people to show you how to do.
|
39 |
|
50 |
It does not back up WordPress core (since you can always get another copy of this from wordpress.org), and does not back up any extra files which you have added outside of the WordPress content directory (files which, by their nature, are unknown to WordPress). By default the WordPress content directory is "wp-content" in your WordPress root. It will not back up database tables which do not have the WordPress prefix (i.e. database tables from other applications but sharing a database with WordPress).
|
51 |
|
52 |
= Any known bugs ? =
|
53 |
+
The major one is that backups of very large sites (lots of uploaded media) can fail due to timing out. If your site is very large, then be doubly-sure to test when setting up that your backups are not empty.
|
54 |
|
55 |
= I encrypted my database - how do I decrypt it? =
|
56 |
|
66 |
|
67 |
== Changelog ==
|
68 |
|
|
|
|
|
|
|
69 |
= 0.8.51 - 11/19/2012 =
|
70 |
* Moved screenshot into assets, reducing plugin download size
|
71 |
|
updraftplus.php
CHANGED
@@ -4,27 +4,24 @@ Plugin Name: UpdraftPlus - Backup/Restore
|
|
4 |
Plugin URI: http://wordpress.org/extend/plugins/updraftplus
|
5 |
Description: Uploads, themes, plugins, and your DB can be automatically backed up to Amazon S3, Google Drive, FTP, or emailed, on separate schedules.
|
6 |
Author: David Anderson.
|
7 |
-
Version: 0.
|
8 |
Donate link: http://david.dw-perspective.org.uk/donate
|
9 |
Author URI: http://wordshell.net
|
10 |
*/
|
11 |
|
12 |
//TODO (some of these items mine, some from original Updraft awaiting review):
|
13 |
//Add DropBox support
|
14 |
-
//Struggles with large uploads - runs out of time before finishing. Break into chunks? Resume download on later run? (Add a new scheduled event to check on progress? Separate the upload from the creation?).
|
15 |
//improve error reporting. s3 and dir backup have decent reporting now, but not sure i know what to do from here
|
16 |
//list backups that aren't tracked (helps with double backup problem)
|
17 |
//investigate $php_errormsg further
|
18 |
//pretty up return messages in admin area
|
19 |
//check s3/ftp download
|
20 |
|
21 |
-
//Rip out the "last backup" bit, and/or put in a display of the last log
|
22 |
-
|
23 |
/* More TODO:
|
24 |
DONE, TESTING: Are all directories in wp-content covered? No; only plugins, themes, content. We should check for others and allow the user the chance to choose which ones he wants
|
25 |
Use only one entry in WP options database
|
26 |
Encrypt filesystem, if memory allows (and have option for abort if not); split up into multiple zips when needed
|
27 |
-
// Does not delete old custom directories upon a restore?
|
28 |
*/
|
29 |
|
30 |
/* Portions copyright 2010 Paul Kehrer
|
@@ -59,7 +56,7 @@ define('UPDRAFT_DEFAULT_OTHERS_EXCLUDE','upgrade,cache,updraft,index.php');
|
|
59 |
|
60 |
class UpdraftPlus {
|
61 |
|
62 |
-
var $version = '0.
|
63 |
|
64 |
var $dbhandle;
|
65 |
var $errors = array();
|
@@ -77,10 +74,7 @@ class UpdraftPlus {
|
|
77 |
add_action('updraft_backup_database', array($this,'backup_database'));
|
78 |
# backup_all is used by the manual "Backup Now" button
|
79 |
add_action('updraft_backup_all', array($this,'backup_all'));
|
80 |
-
# this is our runs-after-backup event, whose purpose is to see if it succeeded or failed, and resume/mom-up etc.
|
81 |
-
add_action('updraft_backup_resume', array($this,'backup_resume'));
|
82 |
add_action('wp_ajax_updraft_download_backup', array($this, 'updraft_download_backup'));
|
83 |
-
# http://codex.wordpress.org/Plugin_API/Filter_Reference/cron_schedules
|
84 |
add_filter('cron_schedules', array($this,'modify_cron_schedules'));
|
85 |
add_filter('plugin_action_links', array($this, 'plugin_action_links'), 10, 2);
|
86 |
add_action('init', array($this, 'googledrive_backup_auth'));
|
@@ -463,68 +457,11 @@ class UpdraftPlus {
|
|
463 |
|
464 |
# Logs the given line, adding date stamp and newline
|
465 |
function log($line) {
|
466 |
-
if ($this->logfile_handle)
|
467 |
-
|
468 |
-
|
469 |
-
function backup_resume($resumption_no) {
|
470 |
-
// This is scheduled for 5 minutes after a backup job starts
|
471 |
-
$bnonce = get_transient('updraftplus_backup_job_nonce');
|
472 |
-
if (!$bnonce) return;
|
473 |
-
$this->nonce = $bnonce;
|
474 |
-
$this->logfile_open($bnonce);
|
475 |
-
$this->log("Resume backup ($resumption_no): begin run (will check for any remaining jobs)");
|
476 |
-
$btime = get_transient('updraftplus_backup_job_time');
|
477 |
-
if (!$btime) {
|
478 |
-
$this->log("Did not find stored time setting - aborting");
|
479 |
-
return;
|
480 |
-
}
|
481 |
-
$this->log("Resuming backup: resumption=$resumption_no, nonce=$bnonce, begun at=$btime");
|
482 |
-
// Schedule again, to run in 5 minutes again, in case we again fail
|
483 |
-
$resume_delay = 300;
|
484 |
-
// A different argument than before is needed otherwise the event is ignored
|
485 |
-
$next_resumption = $resumption_no+1;
|
486 |
-
if ($next_resumption < 10) {
|
487 |
-
wp_schedule_single_event(time()+$resume_delay, 'updraft_backup_resume' ,array($next_resumption));
|
488 |
-
} else {
|
489 |
-
$this->log("This is our tenth attempt - will not try again");
|
490 |
}
|
491 |
-
$this->backup_time = $btime;
|
492 |
-
|
493 |
-
// Returns an array, most recent first, of backup sets
|
494 |
-
$backup_history = $this->get_backup_history();
|
495 |
-
if (!isset($backup_history[$btime])) $this->log("Error: Could not find a record in the database of a backup with this timestamp");
|
496 |
-
|
497 |
-
$our_files=$backup_history[$btime];
|
498 |
-
$undone_files = array();
|
499 |
-
foreach ($our_files as $key => $file) {
|
500 |
-
$hash=md5($file);
|
501 |
-
$fullpath = trailingslashit(get_option('updraft_dir')).$file;
|
502 |
-
if (get_transient('updraft_'.$hash) === "yes") {
|
503 |
-
$this->log("$file: $key: This file has been successfully uploaded in the last 3 hours");
|
504 |
-
} elseif (is_file($fullpath)) {
|
505 |
-
$this->log("$file: $key: This file has NOT been successfully uploaded in the last 3 hours: will retry");
|
506 |
-
$undone_files[$key] = $file;
|
507 |
-
} else {
|
508 |
-
$this-log("$file: Note: This file was not marked as successfully uploaded, but does not exist on the local filesystem");
|
509 |
-
$this->uploaded_file($file);
|
510 |
-
}
|
511 |
-
}
|
512 |
-
|
513 |
-
if (count($undone_files) == 0) {
|
514 |
-
$this->log("There were no files that needed uploading; backup job is finished");
|
515 |
-
return;
|
516 |
-
}
|
517 |
-
|
518 |
-
$this->log("Requesting backup of the files that were not successfully uploaded");
|
519 |
-
$this->cloud_backup($undone_files);
|
520 |
-
$this->cloud_backup_finish($undone_files);
|
521 |
-
|
522 |
-
$this->log("Resume backup ($resumption_no): finish run");
|
523 |
-
|
524 |
-
$this->backup_finish($next_resumption);
|
525 |
-
|
526 |
}
|
527 |
-
|
528 |
function backup_all() {
|
529 |
$this->backup(true,true);
|
530 |
}
|
@@ -538,32 +475,18 @@ class UpdraftPlus {
|
|
538 |
# Note that nothing will happen if the file backup had the same schedule
|
539 |
$this->backup(false,true);
|
540 |
}
|
|
|
|
|
|
|
541 |
|
542 |
-
|
|
|
|
|
543 |
//set log file name and open log file
|
544 |
$updraft_dir = $this->backups_dir_location();
|
545 |
-
$this->logfile_name = $updraft_dir. "/log
|
546 |
// Use append mode in case it already exists
|
547 |
$this->logfile_handle = fopen($this->logfile_name, 'a');
|
548 |
-
}
|
549 |
-
|
550 |
-
//scheduled wp-cron events can have a race condition here if page loads are coming fast enough, but there's nothing we can do about it. TODO: I reckon there is. Store a transient based on the backup schedule. Then as the backup proceeds, check for its existence; if it has changed, then another task has begun, so abort.
|
551 |
-
function backup($backup_files, $backup_database) {
|
552 |
-
|
553 |
-
//generate backup information
|
554 |
-
$this->backup_time_nonce();
|
555 |
-
// If we don't finish in 3 hours, then we won't finish
|
556 |
-
// This transient indicates the identity of the current backup job (which can be used to find the files and logfile)
|
557 |
-
set_transient("updraftplus_backup_job_nonce",$this->nonce,3600*3);
|
558 |
-
set_transient("updraftplus_backup_job_time",$this->backup_time,3600*3);
|
559 |
-
$this->logfile_open($this->nonce);
|
560 |
-
|
561 |
-
// Schedule the even to run later, which checks on success and can resume the backup
|
562 |
-
// We save the time to a variable because it is needed for un-scheduling
|
563 |
-
// $resume_delay = (get_option('updraft_debug_mode')) ? 60 : 300;
|
564 |
-
$resume_delay = 300;
|
565 |
-
wp_schedule_single_event(time()+$resume_delay, 'updraft_backup_resume', array(1));
|
566 |
-
$this->log("In case we run out of time, scheduled a resumption at: $resume_delay seconds from now");
|
567 |
|
568 |
// Log some information that may be helpful
|
569 |
global $wp_version;
|
@@ -572,7 +495,10 @@ class UpdraftPlus {
|
|
572 |
# If the files and database schedules are the same, and if this the file one, then we rope in database too.
|
573 |
# On the other hand, if the schedules were the same and this was the database run, then there is nothing to do.
|
574 |
if (get_option('updraft_interval') == get_option('updraft_interval_database') || get_option('updraft_interval_database','xyz') == 'xyz' ) {
|
575 |
-
|
|
|
|
|
|
|
576 |
}
|
577 |
|
578 |
$this->log("Processed schedules. Tasks now: Backup files: $backup_files Backup DB: $backup_database");
|
@@ -600,88 +526,45 @@ class UpdraftPlus {
|
|
600 |
$backup_contains = ($backup_files) ? "Files and database" : "Database only (no files)";
|
601 |
}
|
602 |
|
603 |
-
set_transient("updraftplus_backupcontains", $backup_contains, 3600*3);
|
604 |
-
|
605 |
//save this to our history so we can track backups for the retain feature
|
606 |
$this->log("Saving backup history");
|
607 |
-
// This is done before cloud despatch, because we want a record of what *should* be in the backup. Whether it actually makes it there or not is not yet known.
|
608 |
$this->save_backup_history($backup_array);
|
609 |
|
610 |
//cloud operations (S3,Google Drive,FTP,email,nothing)
|
611 |
-
//this also calls the retain
|
612 |
if(is_array($backup_array) && count($backup_array) >0) {
|
613 |
$this->log("Beginning dispatch of backup to remote");
|
614 |
$this->cloud_backup($backup_array);
|
615 |
}
|
616 |
-
|
|
|
|
|
|
|
|
|
617 |
//save the last backup info, including errors, if any
|
618 |
$this->log("Saving last backup information into WordPress db");
|
619 |
$this->save_last_backup($backup_array);
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
function backup_finish($cancel_event) {
|
632 |
-
|
633 |
-
// In fact, leaving the hook to run (if debug is set) is harmless, as the resume job should only do tasks that were left unfinished, which at this stage is none.
|
634 |
-
if (empty($this->errors)) {
|
635 |
-
$this->log("There were no errors in the uploads, so the 'resume' event is being unscheduled");
|
636 |
-
wp_clear_scheduled_hook('updraft_backup_resume', array($cancel_event));
|
637 |
-
delete_transient("updraftplus_backup_job_nonce");
|
638 |
-
delete_transient("updraftplus_backup_job_time");
|
639 |
-
} else {
|
640 |
-
$this->log("There were errors in the uploads, so the 'resume' event is remaining unscheduled");
|
641 |
}
|
642 |
-
|
|
|
643 |
@fclose($this->logfile_handle);
|
644 |
-
|
645 |
-
if (!get_option('updraft_debug_mode')) @unlink($this->logfile_name);
|
646 |
-
|
647 |
-
}
|
648 |
-
|
649 |
-
function cloud_backup_finish($backup_array) {
|
650 |
-
|
651 |
-
//delete local files if the pref is set
|
652 |
-
foreach($backup_array as $file) { $this->delete_local($file); }
|
653 |
-
|
654 |
-
// Send the results email if requested
|
655 |
-
if(get_option('updraft_email') != "" && get_option('updraft_service') != 'email') $this->send_results_email();
|
656 |
-
|
657 |
}
|
658 |
-
|
659 |
-
|
660 |
-
function send_results_email() {
|
661 |
-
|
662 |
-
$sendmail_to = get_option('updraft_email');
|
663 |
-
|
664 |
-
$this->log("Sending email report to: ".$sendmail_to);
|
665 |
-
|
666 |
-
$append_log = (get_option('updraft_debug_mode') && $this->logfile_name != "") ? "\r\nLog contents:\r\n".file_get_contents($this->logfile_name) : "" ;
|
667 |
-
|
668 |
-
wp_mail($sendmail_to,'Backed up: '.get_bloginfo('name').' (UpdraftPlus) '.date('Y-m-d H:i',time()),'Site: '.site_url()."\r\nUpdraftPlus WordPress backup is complete.\r\nBackup contains: ".get_transient("updraftplus_backupcontains")."\r\n\r\n".$this->wordshell_random_advert(0)."\r\n".$append_log);
|
669 |
-
|
670 |
-
}
|
671 |
-
|
672 |
function save_last_backup($backup_array) {
|
673 |
$success = (empty($this->errors))?1:0;
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
update_option('updraft_last_backup', $last_backup);
|
678 |
-
}
|
679 |
-
|
680 |
-
// This should be called whenever a file is successfully uploaded
|
681 |
-
function uploaded_file($file) {
|
682 |
-
# We take an MD5 hash because set_transient wants a name of 45 characters or less
|
683 |
-
$hash = md5($file);
|
684 |
-
set_transient("updraft_".$hash, "yes", 3600*3);
|
685 |
}
|
686 |
|
687 |
function cloud_backup($backup_array) {
|
@@ -689,17 +572,17 @@ class UpdraftPlus {
|
|
689 |
case 's3':
|
690 |
@set_time_limit(900);
|
691 |
$this->log("Cloud backup: S3");
|
692 |
-
if (count($backup_array) >0) $this->s3_backup($backup_array);
|
693 |
break;
|
694 |
case 'googledrive':
|
695 |
@set_time_limit(900);
|
696 |
$this->log("Cloud backup: Google Drive");
|
697 |
-
if (count($backup_array) >0) $this->googledrive_backup($backup_array);
|
698 |
break;
|
699 |
case 'ftp':
|
700 |
@set_time_limit(900);
|
701 |
$this->log("Cloud backup: FTP");
|
702 |
-
if (count($backup_array) >0) $this->ftp_backup($backup_array);
|
703 |
break;
|
704 |
case 'email':
|
705 |
@set_time_limit(900);
|
@@ -708,7 +591,6 @@ class UpdraftPlus {
|
|
708 |
foreach($backup_array as $type=>$file) {
|
709 |
$fullpath = trailingslashit(get_option('updraft_dir')).$file;
|
710 |
wp_mail(get_option('updraft_email'),"WordPress Backup ".date('Y-m-d H:i',$this->backup_time),"Backup is of the $type. Be wary; email backups may fail because of file size limitations on mail servers.",null,array($fullpath));
|
711 |
-
$this->uploaded_file($file);
|
712 |
}
|
713 |
//we don't break here so it goes and executes all the default behavior below as well. this gives us retain behavior for email
|
714 |
default:
|
@@ -835,7 +717,9 @@ class UpdraftPlus {
|
|
835 |
}
|
836 |
|
837 |
function s3_backup($backup_array) {
|
838 |
-
if(!class_exists('S3'))
|
|
|
|
|
839 |
$s3 = new S3(get_option('updraft_s3_login'), get_option('updraft_s3_pass'));
|
840 |
$bucket_name = untrailingslashit(get_option('updraft_s3_remote_path'));
|
841 |
$bucket_path = "";
|
@@ -851,9 +735,6 @@ class UpdraftPlus {
|
|
851 |
if (!$s3->putObjectFile($fullpath, $bucket_name, $bucket_path.$file)) {
|
852 |
$this->log("S3 upload: failed");
|
853 |
$this->error("S3 Error: Failed to upload $fullpath. Error was ".$php_errormsg);
|
854 |
-
} else {
|
855 |
-
$this->log("S3 upload: success");
|
856 |
-
$this->uploaded_file($file);
|
857 |
}
|
858 |
}
|
859 |
$this->prune_retained_backups('s3',$s3,$orig_bucket_name);
|
@@ -872,9 +753,7 @@ class UpdraftPlus {
|
|
872 |
$timer_start = microtime( true );
|
873 |
if ( $id = $this->googledrive_upload_file( $file_path, $file_name, get_option('updraft_googledrive_remotepath'), $access ) ) {
|
874 |
$this->log('OK: Archive ' . $file_name . ' uploaded to Google Drive in ' . ( round(microtime( true ) - $timer_start,2) ) . ' seconds' );
|
875 |
-
$this->uploaded_file($file);
|
876 |
} else {
|
877 |
-
$this->error("$file_name: Failed to upload to Google Drive" );
|
878 |
$this->log("ERROR: $file_name: Failed to upload to Google Drive" );
|
879 |
}
|
880 |
}
|
@@ -897,13 +776,7 @@ class UpdraftPlus {
|
|
897 |
$ftp_remote_path = trailingslashit(get_option('updraft_ftp_remote_path'));
|
898 |
foreach($backup_array as $file) {
|
899 |
$fullpath = trailingslashit(get_option('updraft_dir')).$file;
|
900 |
-
|
901 |
-
$this->log("ERROR: $file_name: Successfully uploaded via FTP");
|
902 |
-
$this->uploaded_file($file);
|
903 |
-
} else {
|
904 |
-
$this->error("$file_name: Failed to upload to FTP" );
|
905 |
-
$this->log("ERROR: $file_name: Failed to upload to FTP" );
|
906 |
-
}
|
907 |
}
|
908 |
$this->prune_retained_backups("ftp",$ftp,$ftp_remote_path);
|
909 |
}
|
@@ -931,7 +804,7 @@ class UpdraftPlus {
|
|
931 |
|
932 |
$updraft_dir = $this->backups_dir_location();
|
933 |
if(!is_writable($updraft_dir)) {
|
934 |
-
$this->error('Backup directory is not writable
|
935 |
}
|
936 |
//get the blog name and rip out all non-alphanumeric chars other than _
|
937 |
$blog_name = str_replace(' ','_',get_bloginfo());
|
@@ -1046,7 +919,7 @@ class UpdraftPlus {
|
|
1046 |
}
|
1047 |
|
1048 |
function save_backup_history($backup_array) {
|
1049 |
-
//
|
1050 |
if(is_array($backup_array)) {
|
1051 |
$backup_history = get_option('updraft_backup_history');
|
1052 |
$backup_history = (is_array($backup_history)) ? $backup_history : array();
|
@@ -1825,11 +1698,7 @@ ENDHERE;
|
|
1825 |
}
|
1826 |
|
1827 |
if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup') {
|
1828 |
-
|
1829 |
-
echo "<!-- updraft schedule: failed -->";
|
1830 |
-
} else {
|
1831 |
-
echo "<!-- updraft schedule: ok -->";
|
1832 |
-
}
|
1833 |
}
|
1834 |
if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_all') {
|
1835 |
$this->backup(true,true);
|
@@ -1855,7 +1724,7 @@ ENDHERE;
|
|
1855 |
echo "<div style=\"color:blue\">Old directories successfully deleted.</div>";
|
1856 |
}
|
1857 |
if(!$this->memory_check(96)) {?>
|
1858 |
-
<div style="color:orange">Your PHP memory limit is too low. Updraft attempted to raise it but was unsuccessful. This plugin may not work properly with a memory limit of less than 96 Mb
|
1859 |
<?php
|
1860 |
}
|
1861 |
if(!$this->execution_time_check(300)) {?>
|
@@ -1910,7 +1779,7 @@ ENDHERE;
|
|
1910 |
$backup_disabled = "";
|
1911 |
} else {
|
1912 |
$backup_disabled = 'disabled="disabled"';
|
1913 |
-
$dir_info = '<span style="color:red">Backup directory specified is <b>not</b> writable
|
1914 |
}
|
1915 |
?>
|
1916 |
<th>Now:</th>
|
4 |
Plugin URI: http://wordpress.org/extend/plugins/updraftplus
|
5 |
Description: Uploads, themes, plugins, and your DB can be automatically backed up to Amazon S3, Google Drive, FTP, or emailed, on separate schedules.
|
6 |
Author: David Anderson.
|
7 |
+
Version: 0.8.51
|
8 |
Donate link: http://david.dw-perspective.org.uk/donate
|
9 |
Author URI: http://wordshell.net
|
10 |
*/
|
11 |
|
12 |
//TODO (some of these items mine, some from original Updraft awaiting review):
|
13 |
//Add DropBox support
|
14 |
+
//Struggles with large uploads - runs out of time before finishing. Break into chunks? Resume download on later run? (Add a new scheduled event to check on progress? Separate the upload from the creation?). Add in some logging (in a .php file that exists first).
|
15 |
//improve error reporting. s3 and dir backup have decent reporting now, but not sure i know what to do from here
|
16 |
//list backups that aren't tracked (helps with double backup problem)
|
17 |
//investigate $php_errormsg further
|
18 |
//pretty up return messages in admin area
|
19 |
//check s3/ftp download
|
20 |
|
|
|
|
|
21 |
/* More TODO:
|
22 |
DONE, TESTING: Are all directories in wp-content covered? No; only plugins, themes, content. We should check for others and allow the user the chance to choose which ones he wants
|
23 |
Use only one entry in WP options database
|
24 |
Encrypt filesystem, if memory allows (and have option for abort if not); split up into multiple zips when needed
|
|
|
25 |
*/
|
26 |
|
27 |
/* Portions copyright 2010 Paul Kehrer
|
56 |
|
57 |
class UpdraftPlus {
|
58 |
|
59 |
+
var $version = '0.8.51';
|
60 |
|
61 |
var $dbhandle;
|
62 |
var $errors = array();
|
74 |
add_action('updraft_backup_database', array($this,'backup_database'));
|
75 |
# backup_all is used by the manual "Backup Now" button
|
76 |
add_action('updraft_backup_all', array($this,'backup_all'));
|
|
|
|
|
77 |
add_action('wp_ajax_updraft_download_backup', array($this, 'updraft_download_backup'));
|
|
|
78 |
add_filter('cron_schedules', array($this,'modify_cron_schedules'));
|
79 |
add_filter('plugin_action_links', array($this, 'plugin_action_links'), 10, 2);
|
80 |
add_action('init', array($this, 'googledrive_backup_auth'));
|
457 |
|
458 |
# Logs the given line, adding date stamp and newline
|
459 |
function log($line) {
|
460 |
+
if ($this->logfile_handle) {
|
461 |
+
fwrite($this->logfile_handle,date('r')." ".$line."\n");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
462 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
463 |
}
|
464 |
+
|
465 |
function backup_all() {
|
466 |
$this->backup(true,true);
|
467 |
}
|
475 |
# Note that nothing will happen if the file backup had the same schedule
|
476 |
$this->backup(false,true);
|
477 |
}
|
478 |
+
|
479 |
+
//scheduled wp-cron events can have a race condition here if page loads are coming fast enough, but there's nothing we can do about it.
|
480 |
+
function backup($backup_files, $backup_database) {
|
481 |
|
482 |
+
//generate backup information
|
483 |
+
$this->backup_time_nonce();
|
484 |
+
|
485 |
//set log file name and open log file
|
486 |
$updraft_dir = $this->backups_dir_location();
|
487 |
+
$this->logfile_name = $updraft_dir. "/log." . $this->nonce . ".txt";
|
488 |
// Use append mode in case it already exists
|
489 |
$this->logfile_handle = fopen($this->logfile_name, 'a');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
490 |
|
491 |
// Log some information that may be helpful
|
492 |
global $wp_version;
|
495 |
# If the files and database schedules are the same, and if this the file one, then we rope in database too.
|
496 |
# On the other hand, if the schedules were the same and this was the database run, then there is nothing to do.
|
497 |
if (get_option('updraft_interval') == get_option('updraft_interval_database') || get_option('updraft_interval_database','xyz') == 'xyz' ) {
|
498 |
+
if ($backup_files == true)
|
499 |
+
{ $backup_database = true; }
|
500 |
+
else
|
501 |
+
{ $backup_database = false; }
|
502 |
}
|
503 |
|
504 |
$this->log("Processed schedules. Tasks now: Backup files: $backup_files Backup DB: $backup_database");
|
526 |
$backup_contains = ($backup_files) ? "Files and database" : "Database only (no files)";
|
527 |
}
|
528 |
|
|
|
|
|
529 |
//save this to our history so we can track backups for the retain feature
|
530 |
$this->log("Saving backup history");
|
|
|
531 |
$this->save_backup_history($backup_array);
|
532 |
|
533 |
//cloud operations (S3,Google Drive,FTP,email,nothing)
|
534 |
+
//this also calls the retain feature at the end (done in this method to reuse existing cloud connections)
|
535 |
if(is_array($backup_array) && count($backup_array) >0) {
|
536 |
$this->log("Beginning dispatch of backup to remote");
|
537 |
$this->cloud_backup($backup_array);
|
538 |
}
|
539 |
+
//delete local files if the pref is set
|
540 |
+
foreach($backup_array as $file) {
|
541 |
+
$this->delete_local($file);
|
542 |
+
}
|
543 |
+
|
544 |
//save the last backup info, including errors, if any
|
545 |
$this->log("Saving last backup information into WordPress db");
|
546 |
$this->save_last_backup($backup_array);
|
547 |
+
|
548 |
+
if(get_option('updraft_email') != "" && get_option('updraft_service') != 'email') {
|
549 |
+
$sendmail_to = get_option('updraft_email');
|
550 |
+
$this->log("Sending email report to: ".$sendmail_to);
|
551 |
+
$append_log = "";
|
552 |
+
if(get_option('updraft_debug_mode') && $this->logfile_name != "") {
|
553 |
+
$append_log .= "\r\nLog contents:\r\n".file_get_contents($this->logfile_name);
|
554 |
+
}
|
555 |
+
wp_mail($sendmail_to,'Backed up: '.get_bloginfo('name').' (UpdraftPlus) '.date('Y-m-d H:i',time()),'Site: '.site_url()."\r\nUpdraftPlus WordPress backup is complete.\r\nBackup contains: $backup_contains\r\n\r\n".$this->wordshell_random_advert(0)."\r\n".$append_log);
|
556 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
557 |
}
|
558 |
+
|
559 |
+
// Close log file
|
560 |
@fclose($this->logfile_handle);
|
561 |
+
if (!get_option('updraft_debug_mode')) { @unlink($this->logfile_name); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
562 |
}
|
563 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
564 |
function save_last_backup($backup_array) {
|
565 |
$success = (empty($this->errors))?1:0;
|
566 |
+
$last_backup = array('backup_time'=>$this->backup_time,'backup_array'=>$backup_array,'success'=>$success,'errors'=>$this->errors);
|
567 |
+
update_option('updraft_last_backup',$last_backup);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
568 |
}
|
569 |
|
570 |
function cloud_backup($backup_array) {
|
572 |
case 's3':
|
573 |
@set_time_limit(900);
|
574 |
$this->log("Cloud backup: S3");
|
575 |
+
if (count($backup_array) >0) { $this->s3_backup($backup_array); }
|
576 |
break;
|
577 |
case 'googledrive':
|
578 |
@set_time_limit(900);
|
579 |
$this->log("Cloud backup: Google Drive");
|
580 |
+
if (count($backup_array) >0) { $this->googledrive_backup($backup_array); }
|
581 |
break;
|
582 |
case 'ftp':
|
583 |
@set_time_limit(900);
|
584 |
$this->log("Cloud backup: FTP");
|
585 |
+
if (count($backup_array) >0) { $this->ftp_backup($backup_array); }
|
586 |
break;
|
587 |
case 'email':
|
588 |
@set_time_limit(900);
|
591 |
foreach($backup_array as $type=>$file) {
|
592 |
$fullpath = trailingslashit(get_option('updraft_dir')).$file;
|
593 |
wp_mail(get_option('updraft_email'),"WordPress Backup ".date('Y-m-d H:i',$this->backup_time),"Backup is of the $type. Be wary; email backups may fail because of file size limitations on mail servers.",null,array($fullpath));
|
|
|
594 |
}
|
595 |
//we don't break here so it goes and executes all the default behavior below as well. this gives us retain behavior for email
|
596 |
default:
|
717 |
}
|
718 |
|
719 |
function s3_backup($backup_array) {
|
720 |
+
if(!class_exists('S3')) {
|
721 |
+
require_once(dirname(__FILE__).'/includes/S3.php');
|
722 |
+
}
|
723 |
$s3 = new S3(get_option('updraft_s3_login'), get_option('updraft_s3_pass'));
|
724 |
$bucket_name = untrailingslashit(get_option('updraft_s3_remote_path'));
|
725 |
$bucket_path = "";
|
735 |
if (!$s3->putObjectFile($fullpath, $bucket_name, $bucket_path.$file)) {
|
736 |
$this->log("S3 upload: failed");
|
737 |
$this->error("S3 Error: Failed to upload $fullpath. Error was ".$php_errormsg);
|
|
|
|
|
|
|
738 |
}
|
739 |
}
|
740 |
$this->prune_retained_backups('s3',$s3,$orig_bucket_name);
|
753 |
$timer_start = microtime( true );
|
754 |
if ( $id = $this->googledrive_upload_file( $file_path, $file_name, get_option('updraft_googledrive_remotepath'), $access ) ) {
|
755 |
$this->log('OK: Archive ' . $file_name . ' uploaded to Google Drive in ' . ( round(microtime( true ) - $timer_start,2) ) . ' seconds' );
|
|
|
756 |
} else {
|
|
|
757 |
$this->log("ERROR: $file_name: Failed to upload to Google Drive" );
|
758 |
}
|
759 |
}
|
776 |
$ftp_remote_path = trailingslashit(get_option('updraft_ftp_remote_path'));
|
777 |
foreach($backup_array as $file) {
|
778 |
$fullpath = trailingslashit(get_option('updraft_dir')).$file;
|
779 |
+
$ftp->put($fullpath,$ftp_remote_path.$file,FTP_BINARY);
|
|
|
|
|
|
|
|
|
|
|
|
|
780 |
}
|
781 |
$this->prune_retained_backups("ftp",$ftp,$ftp_remote_path);
|
782 |
}
|
804 |
|
805 |
$updraft_dir = $this->backups_dir_location();
|
806 |
if(!is_writable($updraft_dir)) {
|
807 |
+
$this->error('Backup directory is not writable.','fatal');
|
808 |
}
|
809 |
//get the blog name and rip out all non-alphanumeric chars other than _
|
810 |
$blog_name = str_replace(' ','_',get_bloginfo());
|
919 |
}
|
920 |
|
921 |
function save_backup_history($backup_array) {
|
922 |
+
//this stores full paths right now. should probably concatenate with ABSPATH to make it easier to move sites
|
923 |
if(is_array($backup_array)) {
|
924 |
$backup_history = get_option('updraft_backup_history');
|
925 |
$backup_history = (is_array($backup_history)) ? $backup_history : array();
|
1698 |
}
|
1699 |
|
1700 |
if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup') {
|
1701 |
+
wp_schedule_single_event(time()+5, 'updraft_backup_all');
|
|
|
|
|
|
|
|
|
1702 |
}
|
1703 |
if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_all') {
|
1704 |
$this->backup(true,true);
|
1724 |
echo "<div style=\"color:blue\">Old directories successfully deleted.</div>";
|
1725 |
}
|
1726 |
if(!$this->memory_check(96)) {?>
|
1727 |
+
<div style="color:orange">Your PHP memory limit is too low. Updraft attempted to raise it but was unsuccessful. This plugin may not work properly with a memory limit of less than 96 Mb. Current limit is: <?php echo $this->memory_check_current(); ?> Mb</div>
|
1728 |
<?php
|
1729 |
}
|
1730 |
if(!$this->execution_time_check(300)) {?>
|
1779 |
$backup_disabled = "";
|
1780 |
} else {
|
1781 |
$backup_disabled = 'disabled="disabled"';
|
1782 |
+
$dir_info = '<span style="color:red">Backup directory specified is <b>not</b> writable. <span style="font-size:110%;font-weight:bold"><a href="options-general.php?page=updraftplus&action=updraft_create_backup_dir">Click here</a></span> to attempt to create the directory and set the permissions. If that is unsuccessful check the permissions on your server or change it to another directory that is writable by your web server process.</span>';
|
1783 |
}
|
1784 |
?>
|
1785 |
<th>Now:</th>
|