Version Description
- 01/23/2013 =
- Internal reorganisation, enabling UpdraftPlus Premium
Download this release
Release Info
Developer | DavidAnderson |
Plugin | UpdraftPlus WordPress Backup Plugin |
Version | 1.3.2 |
Comparing to | |
See all releases |
Code changes from version 1.3.6 to 1.3.2
- includes/Dropbox/OAuth/Storage/Encrypter.php +1 -1
- includes/updraft-restorer.php +4 -4
- methods/dropbox.php +2 -3
- readme.txt +2 -7
- updraftplus.php +230 -158
includes/Dropbox/OAuth/Storage/Encrypter.php
CHANGED
@@ -16,7 +16,7 @@ class Dropbox_Encrypter
|
|
16 |
const CIPHER = MCRYPT_RIJNDAEL_128;
|
17 |
const MODE = MCRYPT_MODE_CBC;
|
18 |
const KEY_SIZE = 32;
|
19 |
-
const IV_SIZE =
|
20 |
const IV_SOURCE = MCRYPT_DEV_URANDOM;
|
21 |
|
22 |
/**
|
16 |
const CIPHER = MCRYPT_RIJNDAEL_128;
|
17 |
const MODE = MCRYPT_MODE_CBC;
|
18 |
const KEY_SIZE = 32;
|
19 |
+
const IV_SIZE = 32;
|
20 |
const IV_SOURCE = MCRYPT_DEV_URANDOM;
|
21 |
|
22 |
/**
|
includes/updraft-restorer.php
CHANGED
@@ -14,13 +14,13 @@ class Updraft_Restorer extends WP_Upgrader {
|
|
14 |
|
15 |
function restore_backup($backup_file, $type) {
|
16 |
|
17 |
-
if ($type
|
18 |
|
19 |
global $wp_filesystem;
|
20 |
$this->init();
|
21 |
$this->backup_strings();
|
22 |
|
23 |
-
$res = $this->fs_connect(array(ABSPATH, WP_CONTENT_DIR) );
|
24 |
if(!$res) exit;
|
25 |
|
26 |
$wp_dir = trailingslashit($wp_filesystem->abspath());
|
@@ -80,10 +80,10 @@ class Updraft_Restorer extends WP_Upgrader {
|
|
80 |
|
81 |
switch($type) {
|
82 |
case 'uploads':
|
83 |
-
|
84 |
break;
|
85 |
default:
|
86 |
-
|
87 |
}
|
88 |
}
|
89 |
|
14 |
|
15 |
function restore_backup($backup_file, $type) {
|
16 |
|
17 |
+
if ($type == 'nonce') return;
|
18 |
|
19 |
global $wp_filesystem;
|
20 |
$this->init();
|
21 |
$this->backup_strings();
|
22 |
|
23 |
+
$res = $this->fs_connect( array(ABSPATH, WP_CONTENT_DIR) );
|
24 |
if(!$res) exit;
|
25 |
|
26 |
$wp_dir = trailingslashit($wp_filesystem->abspath());
|
80 |
|
81 |
switch($type) {
|
82 |
case 'uploads':
|
83 |
+
$wp_filesystem->chmod($wp_dir . "wp-content/$type", 0777, true);
|
84 |
break;
|
85 |
default:
|
86 |
+
$wp_filesystem->chmod($wp_dir . "wp-content/$type", FS_CHMOD_DIR);
|
87 |
}
|
88 |
}
|
89 |
|
methods/dropbox.php
CHANGED
@@ -346,9 +346,8 @@ class UpdraftPlus_BackupModule_dropbox {
|
|
346 |
require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/OAuth/Consumer/Curl.php');
|
347 |
// require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/OAuth/Consumer/WordPress.php');
|
348 |
|
349 |
-
|
350 |
-
$
|
351 |
-
$key = UpdraftPlus_Options::get_updraft_option(base64_decode('dXBkcmFmdF9kcm9wYm94X3NlY3JldA=='));
|
352 |
|
353 |
// Set the callback URL
|
354 |
$callback = admin_url('options-general.php?page=updraftplus&action=updraftmethod-dropbox-auth');
|
346 |
require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/OAuth/Consumer/Curl.php');
|
347 |
// require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/OAuth/Consumer/WordPress.php');
|
348 |
|
349 |
+
$sec = UpdraftPlus_Options::get_updraft_option('updraft_dropbox_appkey');
|
350 |
+
$key = UpdraftPlus_Options::get_updraft_option('updraft_dropbox_secret');
|
|
|
351 |
|
352 |
// Set the callback URL
|
353 |
$callback = admin_url('options-general.php?page=updraftplus&action=updraftmethod-dropbox-auth');
|
readme.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
=== UpdraftPlus Backup ===
|
2 |
Contributors: David Anderson
|
3 |
-
Tags: backup, restore, database, cloud, amazon, s3, dropbox, google drive, ftp, cloud, back up, multisite
|
4 |
Requires at least: 3.2
|
5 |
Tested up to: 3.5
|
6 |
Stable tag: 1.3.2
|
@@ -113,7 +113,7 @@ You can check the changelog for changes; but the original Updraft, before I fork
|
|
113 |
|
114 |
= Any known bugs ? =
|
115 |
|
116 |
-
Not a bug as such, but one issue to be aware of is that backups of very large sites (lots of uploaded media)
|
117 |
|
118 |
= I encrypted my database - how do I decrypt it? =
|
119 |
|
@@ -141,11 +141,6 @@ Thanks for asking - yes, I have. Check out my profile page - http://profiles.wor
|
|
141 |
|
142 |
== Changelog ==
|
143 |
|
144 |
-
= 1.3.6 - 01/24/2013 =
|
145 |
-
* Fixed faulty assumptions in 'resume' code, now leading to more reliable resuming
|
146 |
-
* Removed some duplicate code; first attempt and resumptions now uses same code
|
147 |
-
* Added further parameters that should be removed on a wipe operation
|
148 |
-
|
149 |
= 1.3.2 - 01/23/2013 =
|
150 |
* Internal reorganisation, enabling UpdraftPlus Premium
|
151 |
|
1 |
=== UpdraftPlus Backup ===
|
2 |
Contributors: David Anderson
|
3 |
+
Tags: backup, restore, database, cloud, amazon, s3, dropbox, google drive, gdrive, ftp, cloud, updraft, back up, multisite
|
4 |
Requires at least: 3.2
|
5 |
Tested up to: 3.5
|
6 |
Stable tag: 1.3.2
|
113 |
|
114 |
= Any known bugs ? =
|
115 |
|
116 |
+
Not a bug as such, but one issue to be aware of is that backups of very large sites (lots of uploaded media) can fail, or require a longer period of time to succeed, due to timing out. This depends on how many seconds your web host allows a PHP process to run and how many resources they give you. With such sites, you need to use Amazon S3, which UpdraftPlus supports (since 0.9.20) or Google Drive (since 0.9.21) or Dropbox (since 1.2.19) with chunked, resumable uploads. Other backup methods have code (since 0.9.0) to retry failed uploads of an archive, but the upload cannot be chunked, so if an archive is enormous (i.e. cannot be completely uploaded in the time that PHP is allowed for running on your web host) it cannot work.
|
117 |
|
118 |
= I encrypted my database - how do I decrypt it? =
|
119 |
|
141 |
|
142 |
== Changelog ==
|
143 |
|
|
|
|
|
|
|
|
|
|
|
144 |
= 1.3.2 - 01/23/2013 =
|
145 |
* Internal reorganisation, enabling UpdraftPlus Premium
|
146 |
|
updraftplus.php
CHANGED
@@ -4,7 +4,7 @@ Plugin Name: UpdraftPlus - Backup/Restore
|
|
4 |
Plugin URI: http://wordpress.org/extend/plugins/updraftplus
|
5 |
Description: Backup and restore: your content and database can be automatically backed up to Amazon S3, Dropbox, Google Drive, FTP or email, on separate schedules.
|
6 |
Author: David Anderson.
|
7 |
-
Version: 1.3.
|
8 |
Donate link: http://david.dw-perspective.org.uk/donate
|
9 |
License: GPLv3 or later
|
10 |
Author URI: http://wordshell.net
|
@@ -13,25 +13,19 @@ Author URI: http://wordshell.net
|
|
13 |
/*
|
14 |
TODO
|
15 |
//Add SFTP, Box.Net, SugarSync and Microsoft Skydrive support??
|
16 |
-
//The restorer has a hard-coded wp-content - fix
|
17 |
-
//Read safe-mode only once, remembering it will be totally removed from PHP
|
18 |
-
//Button for wiping files. Also auto-wipe on de-activate/de-install.
|
19 |
-
//Change DB encryption to not require whole gzip in memory (twice)
|
20 |
//improve error reporting / pretty up return messages in admin area. One thing: have a "backup is now finished" flag. Otherwise with the resuming things get ambiguous/confusing. See http://wordpress.org/support/topic/backup-status - user was not aware that backup completely failed. Maybe a "backup status" field for each nonce that gets updated? (Even via AJAX?)
|
21 |
//?? On 'backup now', open up a Lightbox, count down 5 seconds, then start examining the log file (if it can be found)
|
22 |
//Should make clear in dashboard what is a non-fatal error (i.e. can be retried) - leads to unnecessary bug reports
|
23 |
-
//
|
24 |
// Should we resume if the only errors were upon deletion (i.e. the backup itself was fine?) Presently we do, but it displays errors for the user to confuse them. Perhaps better to make pruning a separate scheuled task??
|
25 |
// Make jobs *individually* resumable (i.e. all the state info must be keyed on the nonce; then call the resume event *specifying the nonce*)
|
26 |
// Warn the user if their zip-file creation is slooowww...
|
27 |
// Create a "Want Support?" button/console, that leads them through what is needed, and performs some basic tests...
|
28 |
// Resuming partial FTP uploads
|
29 |
// Turn expert options into a jQuery toggle
|
30 |
-
// Provide backup/restoration for UpdraftPlus's settings, to allow 'bootstrap' on a fresh WP install
|
31 |
// Multiple jobs
|
32 |
-
//
|
33 |
-
// Create single zip, containing even WordPress itself
|
34 |
-
// When a new backup starts, AJAX-update the 'Last backup' display in the admin page.
|
35 |
|
36 |
Encrypt filesystem, if memory allows (and have option for abort if not); split up into multiple zips when needed
|
37 |
// Does not delete old custom directories upon a restore?
|
@@ -78,7 +72,7 @@ if (!class_exists('UpdraftPlus_Options')) require_once(UPDRAFTPLUS_DIR.'/options
|
|
78 |
|
79 |
class UpdraftPlus {
|
80 |
|
81 |
-
var $version = '1.3.
|
82 |
var $plugin_title = 'UpdraftPlus Backup/Restore';
|
83 |
|
84 |
// Choices will be shown in the admin menu in the order used here
|
@@ -94,6 +88,7 @@ class UpdraftPlus {
|
|
94 |
var $dbhandle_isgz;
|
95 |
var $errors = array();
|
96 |
var $nonce;
|
|
|
97 |
var $logfile_name = "";
|
98 |
var $logfile_handle = false;
|
99 |
var $backup_time;
|
@@ -101,8 +96,6 @@ class UpdraftPlus {
|
|
101 |
var $opened_log_time;
|
102 |
var $backup_dir;
|
103 |
|
104 |
-
var $jobdata;
|
105 |
-
|
106 |
function __construct() {
|
107 |
// Initialisation actions - takes place on plugin load
|
108 |
# Create admin page
|
@@ -112,7 +105,7 @@ class UpdraftPlus {
|
|
112 |
# backup_all is used by the manual "Backup Now" button
|
113 |
add_action('updraft_backup_all', array($this,'backup_all'));
|
114 |
# this is our runs-after-backup event, whose purpose is to see if it succeeded or failed, and resume/mom-up etc.
|
115 |
-
add_action('updraft_backup_resume', array($this,'backup_resume')
|
116 |
add_action('wp_enqueue_scripts', array($this, 'ajax_enqueue') );
|
117 |
add_action('wp_ajax_updraft_download_backup', array($this, 'updraft_download_backup'));
|
118 |
add_action('wp_ajax_updraft_ajax', array($this, 'updraft_ajax_handler'));
|
@@ -162,6 +155,8 @@ class UpdraftPlus {
|
|
162 |
$this->backup_time = time();
|
163 |
$nonce = substr(md5(time().rand()), 20);
|
164 |
$this->nonce = $nonce;
|
|
|
|
|
165 |
}
|
166 |
|
167 |
function logfile_open($nonce) {
|
@@ -181,65 +176,58 @@ class UpdraftPlus {
|
|
181 |
UpdraftPlus_Options::update_updraft_option("updraft_lastmessage", $line." (".date('M d H:i:s').")");
|
182 |
}
|
183 |
|
184 |
-
function backup_resume($resumption_no
|
185 |
-
|
186 |
@ignore_user_abort(true);
|
187 |
// This is scheduled for 5 minutes after a backup job starts
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
|
|
|
|
|
|
194 |
}
|
195 |
-
|
196 |
-
$this->log("Backup run: resumption=$resumption_no, nonce=$bnonce, begun at=$btime");
|
197 |
-
|
198 |
// Schedule again, to run in 5 minutes again, in case we again fail
|
199 |
$resume_delay = 300;
|
200 |
// A different argument than before is needed otherwise the event is ignored
|
201 |
$next_resumption = $resumption_no+1;
|
202 |
if ($next_resumption < 10) {
|
203 |
-
|
204 |
-
wp_schedule_single_event(time()+$resume_delay, 'updraft_backup_resume', array($next_resumption, $bnonce, $btime));
|
205 |
} else {
|
206 |
-
$this->log("The current run is our tenth attempt - will not
|
207 |
}
|
|
|
208 |
|
209 |
-
|
210 |
-
$backup_array = $this->resumable_backup_of_files($resumption_no);
|
211 |
// This save, if there was something, is then immediately picked up again
|
212 |
if (is_array($backup_array)) $this->save_backup_history($backup_array);
|
213 |
|
214 |
// Returns an array, most recent first, of backup sets
|
215 |
$backup_history = $this->get_backup_history();
|
216 |
-
if (!isset($backup_history[$btime]))
|
217 |
-
$this->log("Could not find a record in the database of a backup with this timestamp");
|
218 |
-
}
|
219 |
|
220 |
$our_files=$backup_history[$btime];
|
221 |
if (!is_array($our_files)) $our_files = array();
|
222 |
|
223 |
$undone_files = array();
|
224 |
|
225 |
-
$backup_database =
|
226 |
|
227 |
// The transient is read and written below (instead of using the existing variable) so that we can copy-and-paste this part as needed.
|
228 |
-
if ($backup_database == "begun" || $backup_database == "finished"
|
229 |
if ($backup_database == "begun") {
|
230 |
-
|
231 |
-
$this->log("Resuming creation of database dump");
|
232 |
-
} else {
|
233 |
-
$this->log("Beginning creation of database dump");
|
234 |
-
}
|
235 |
-
} elseif ($backup_database == 'encrypted') {
|
236 |
-
$this->log("Database dump: Creation and encryption were completed already");
|
237 |
} else {
|
238 |
$this->log("Database dump: Creation was completed already");
|
239 |
}
|
240 |
$db_backup = $this->backup_db($backup_database);
|
241 |
if(is_array($our_files) && is_string($db_backup)) $our_files['db'] = $db_backup;
|
242 |
-
|
|
|
|
|
243 |
} else {
|
244 |
$this->log("Unrecognised data when trying to ascertain if the database was backed up ($backup_database)");
|
245 |
}
|
@@ -253,20 +241,18 @@ class UpdraftPlus {
|
|
253 |
if (isset($our_files['db']) && !preg_match("/\.crypt$/", $our_files['db'])) {
|
254 |
$our_files['db'] = $this->encrypt_file($our_files['db']);
|
255 |
$this->save_backup_history($our_files);
|
256 |
-
$this->jobdata_set("backup_database", "encrypted");
|
257 |
}
|
258 |
|
259 |
foreach ($our_files as $key => $file) {
|
260 |
|
261 |
-
|
262 |
-
if ($key != 'plugins' && $key != 'themes' && $key != 'others' && $key != 'uploads' && $key != 'db') continue;
|
263 |
|
264 |
$hash = md5($file);
|
265 |
$fullpath = $this->backups_dir_location().'/'.$file;
|
266 |
-
if (
|
267 |
-
$this->log("$file: $key: This file has
|
268 |
} elseif (is_file($fullpath)) {
|
269 |
-
$this->log("$file: $key: This file has
|
270 |
$undone_files[$key] = $file;
|
271 |
} else {
|
272 |
$this->log("$file: Note: This file was not marked as successfully uploaded, but does not exist on the local filesystem");
|
@@ -276,58 +262,68 @@ class UpdraftPlus {
|
|
276 |
|
277 |
if (count($undone_files) == 0) {
|
278 |
$this->log("There were no more files that needed uploading; backup job is complete");
|
279 |
-
// No email, as the user probably already got one if something else completed the run
|
280 |
-
$this->backup_finish($next_resumption, true, false, $resumption_no);
|
281 |
return;
|
282 |
}
|
283 |
|
284 |
$this->log("Requesting backup of the files that were not successfully uploaded");
|
285 |
$this->cloud_backup($undone_files);
|
286 |
|
287 |
-
$this->log("Resume backup ($
|
|
|
288 |
$this->backup_finish($next_resumption, true, true, $resumption_no);
|
289 |
|
290 |
}
|
291 |
|
292 |
function backup_all() {
|
293 |
-
$this->
|
294 |
}
|
295 |
|
296 |
function backup_files() {
|
297 |
# Note that the "false" for database gets over-ridden automatically if they turn out to have the same schedules
|
298 |
-
$this->
|
|
|
299 |
}
|
300 |
|
301 |
function backup_database() {
|
302 |
# Note that nothing will happen if the file backup had the same schedule
|
303 |
-
$this->
|
304 |
-
|
305 |
-
|
306 |
-
function jobdata_set($key, $value) {
|
307 |
-
if (is_array($this->jobdata)) {
|
308 |
-
$this->jobdata[$key] = $value;
|
309 |
-
} else {
|
310 |
-
$this->jobdata = array($key => $value);
|
311 |
-
}
|
312 |
-
set_transient("updraft_jobdata_".$this->nonce, $this->jobdata, 14400);
|
313 |
}
|
314 |
|
315 |
-
function
|
316 |
-
|
317 |
-
|
318 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
319 |
}
|
320 |
-
return (isset($this->jobdata[$key])) ? $this->jobdata[$key] : false;
|
321 |
}
|
322 |
|
323 |
// This uses a transient; its only purpose is to indicate *total* completion; there is no actual danger, just wasted time, in resuming when it was not needed. So the transient just helps save resources.
|
324 |
-
function resumable_backup_of_files($
|
325 |
//backup directories and return a numerically indexed array of file paths to the backup files
|
326 |
-
$transient_status =
|
327 |
if ($transient_status == "finished") {
|
328 |
$this->log("Creation of backups of directories: already finished");
|
329 |
} elseif ($transient_status == "begun") {
|
330 |
-
if ($
|
331 |
$this->log("Creation of backups of directories: had begun; will resume");
|
332 |
} else {
|
333 |
$this->log("Creation of backups of directories: beginning");
|
@@ -339,23 +335,24 @@ class UpdraftPlus {
|
|
339 |
}
|
340 |
// We want this array, even if already finished
|
341 |
$backup_array = $this->backup_dirs($transient_status);
|
|
|
342 |
// This can get over-written later
|
343 |
-
|
|
|
344 |
return $backup_array;
|
345 |
}
|
346 |
|
347 |
-
|
348 |
-
function boot_backup($backup_files, $backup_database) {
|
349 |
|
350 |
@ignore_user_abort(true);
|
351 |
-
|
352 |
//generate backup information
|
353 |
$this->backup_time_nonce();
|
|
|
354 |
$this->logfile_open($this->nonce);
|
355 |
|
356 |
// Log some information that may be helpful
|
357 |
global $wp_version;
|
358 |
-
$this->log("Tasks: Backup files: $backup_files (schedule: ".UpdraftPlus_Options::get_updraft_option('updraft_interval',
|
359 |
|
360 |
# If the files and database schedules are the same, and if this the file one, then we rope in database too.
|
361 |
# On the other hand, if the schedules were the same and this was the database run, then there is nothing to do.
|
@@ -365,18 +362,87 @@ class UpdraftPlus {
|
|
365 |
|
366 |
$this->log("Processed schedules. Tasks now: Backup files: $backup_files Backup DB: $backup_database");
|
367 |
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
373 |
|
374 |
-
|
375 |
-
|
376 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
377 |
|
378 |
-
|
379 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
380 |
|
381 |
}
|
382 |
|
@@ -392,7 +458,15 @@ class UpdraftPlus {
|
|
392 |
$rijndael->setKey($encryption);
|
393 |
$updraft_dir = $this->backups_dir_location();
|
394 |
$file_size = @filesize($updraft_dir.'/'.$file)/1024;
|
395 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
if (0 == $encryption_error) {
|
397 |
$time_taken = max(0.000001, microtime(true)-$microstart);
|
398 |
$this->log("$file: encryption successful: ".round($file_size,1)."Kb in ".round($time_taken,1)."s (".round($file_size/$time_taken, 1)."Kb/s)");
|
@@ -415,8 +489,9 @@ class UpdraftPlus {
|
|
415 |
if (empty($this->errors)) {
|
416 |
if ($clear_nonce_transient) {
|
417 |
$this->log("There were no errors in the uploads, so the 'resume' event is being unscheduled");
|
418 |
-
wp_clear_scheduled_hook('updraft_backup_resume', array($cancel_event
|
419 |
-
|
|
|
420 |
}
|
421 |
} else {
|
422 |
$this->log("There were errors in the uploads, so the 'resume' event is remaining scheduled");
|
@@ -479,12 +554,7 @@ class UpdraftPlus {
|
|
479 |
|
480 |
$append_log = ($debug_mode && $this->logfile_name != "") ? "\r\nLog contents:\r\n".file_get_contents($this->logfile_name) : "" ;
|
481 |
|
482 |
-
$
|
483 |
-
$backup_db = $this->jobdata_get("backup_database");
|
484 |
-
|
485 |
-
$backup_contains = (substr($backup_contains,0,10) == "Files only") ? "Files and database" : "Database only (no files)";
|
486 |
-
|
487 |
-
wp_mail($sendmail_to,'Backed up: '.get_bloginfo('name').' (UpdraftPlus '.$this->version.') '.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);
|
488 |
|
489 |
}
|
490 |
|
@@ -498,9 +568,10 @@ class UpdraftPlus {
|
|
498 |
|
499 |
// This should be called whenever a file is successfully uploaded
|
500 |
function uploaded_file($file, $id = false) {
|
|
|
501 |
$hash = md5($file);
|
502 |
$this->log("Recording as successfully uploaded: $file ($hash)");
|
503 |
-
|
504 |
if ($id) {
|
505 |
$ids = UpdraftPlus_Options::get_updraft_option('updraft_file_ids', array() );
|
506 |
$ids[$file] = $id;
|
@@ -681,7 +752,7 @@ class UpdraftPlus {
|
|
681 |
$rate = round($kbsize/$timetaken, 1);
|
682 |
$this->log("Created $whichone zip - file size is ".round($kbsize,1)." Kb in ".round($timetaken,1)." s ($rate Kb/s)");
|
683 |
}
|
684 |
-
|
685 |
return basename($full_path);
|
686 |
}
|
687 |
|
@@ -731,51 +802,51 @@ class UpdraftPlus {
|
|
731 |
|
732 |
# Others
|
733 |
if (UpdraftPlus_Options::get_updraft_option('updraft_include_others', true)) {
|
|
|
734 |
|
735 |
if ($transient_status == 'finished') {
|
736 |
$backup_array['others'] = $backup_file_basename.'-others.zip';
|
737 |
} else {
|
738 |
-
$this->log("Beginning backup of other directories found in the content directory");
|
739 |
-
|
740 |
-
// http://www.phpconcept.net/pclzip/user-guide/53
|
741 |
-
/* First parameter to create is:
|
742 |
-
An array of filenames or dirnames,
|
743 |
-
or
|
744 |
-
A string containing the filename or a dirname,
|
745 |
-
or
|
746 |
-
A string containing a list of filename or dirname separated by a comma.
|
747 |
-
*/
|
748 |
-
|
749 |
-
# Initialise
|
750 |
-
$other_dirlist = array();
|
751 |
-
|
752 |
-
$others_skip = preg_split("/,/",UpdraftPlus_Options::get_updraft_option('updraft_include_others_exclude', UPDRAFT_DEFAULT_OTHERS_EXCLUDE));
|
753 |
-
# Make the values into the keys
|
754 |
-
$others_skip = array_flip($others_skip);
|
755 |
-
|
756 |
-
$this->log('Looking for candidates to back up in: '.WP_CONTENT_DIR);
|
757 |
-
if ($handle = opendir(WP_CONTENT_DIR)) {
|
758 |
-
while (false !== ($entry = readdir($handle))) {
|
759 |
-
$candidate = WP_CONTENT_DIR.'/'.$entry;
|
760 |
-
if ($entry == "." || $entry == "..") { ; }
|
761 |
-
elseif ($candidate == $updraft_dir) { $this->log("others: $entry: skipping: this is the updraft directory"); }
|
762 |
-
elseif ($candidate == $wp_themes_dir) { $this->log("others: $entry: skipping: this is the themes directory"); }
|
763 |
-
elseif ($candidate == $wp_upload_dir) { $this->log("others: $entry: skipping: this is the uploads directory"); }
|
764 |
-
elseif ($candidate == $wp_plugins_dir) { $this->log("others: $entry: skipping: this is the plugins directory"); }
|
765 |
-
elseif (isset($others_skip[$entry])) { $this->log("others: $entry: skipping: excluded by options"); }
|
766 |
-
else { $this->log("others: $entry: adding to list"); array_push($other_dirlist, $candidate); }
|
767 |
-
}
|
768 |
-
} else {
|
769 |
-
$this->log('ERROR: Could not read the content directory: '.WP_CONTENT_DIR);
|
770 |
-
$this->error('Could not read the content directory: '.WP_CONTENT_DIR);
|
771 |
-
}
|
772 |
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
778 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
779 |
# If we are not already finished
|
780 |
}
|
781 |
} else {
|
@@ -803,7 +874,7 @@ class UpdraftPlus {
|
|
803 |
global $wpdb;
|
804 |
$backup_history = @unserialize($wpdb->get_var($wpdb->prepare("SELECT option_value from $wpdb->options WHERE option_name='updraft_backup_history'")));
|
805 |
if(is_array($backup_history)) {
|
806 |
-
krsort($backup_history); //reverse sort so earliest backup is last on the array.
|
807 |
} else {
|
808 |
$backup_history = array();
|
809 |
}
|
@@ -864,7 +935,6 @@ class UpdraftPlus {
|
|
864 |
$backup_file_base = $updraft_dir.'/'.$file_base;
|
865 |
|
866 |
if ("finished" == $already_done) return basename($backup_file_base.'-db.gz');
|
867 |
-
if ("encrypted" == $already_done) return basename($backup_file_base.'-db.gz.crypt');
|
868 |
|
869 |
$total_tables = 0;
|
870 |
|
@@ -1002,7 +1072,10 @@ class UpdraftPlus {
|
|
1002 |
}
|
1003 |
|
1004 |
// Comment in SQL-file
|
1005 |
-
$this->stow("\n\n
|
|
|
|
|
|
|
1006 |
}
|
1007 |
|
1008 |
// In UpdraftPlus, segment is always 'none'
|
@@ -1018,16 +1091,19 @@ class UpdraftPlus {
|
|
1018 |
}
|
1019 |
}
|
1020 |
|
|
|
|
|
|
|
1021 |
if($segment == 'none') {
|
1022 |
$row_start = 0;
|
1023 |
-
$row_inc =
|
1024 |
} else {
|
1025 |
-
$row_start = $segment *
|
1026 |
-
$row_inc =
|
1027 |
}
|
1028 |
-
|
1029 |
do {
|
1030 |
-
|
|
|
1031 |
$table_data = $wpdb->get_results("SELECT * FROM $table LIMIT {$row_start}, {$row_inc}", ARRAY_A);
|
1032 |
$entries = 'INSERT INTO ' . $this->backquote($table) . ' VALUES (';
|
1033 |
// \x08\\x09, not required
|
@@ -1445,7 +1521,6 @@ class UpdraftPlus {
|
|
1445 |
}
|
1446 |
|
1447 |
function wordshell_random_advert($urls) {
|
1448 |
-
if (defined('UPDRAFTPLUS_PREMIUM')) return "";
|
1449 |
$rad = rand(0,6);
|
1450 |
switch ($rad) {
|
1451 |
case 0:
|
@@ -1652,21 +1727,16 @@ class UpdraftPlus {
|
|
1652 |
$dir_info = '<span style="color:red">Backup directory specified is <b>not</b> writable, or does not exist. <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>';
|
1653 |
}
|
1654 |
|
1655 |
-
echo $dir_info ?> This is where
|
1656 |
</tr>
|
1657 |
<tr>
|
1658 |
<td></td>
|
1659 |
<td>
|
1660 |
-
<?php
|
1661 |
-
$ws_ad = $this->wordshell_random_advert(1);
|
1662 |
-
if ($ws_ad) {
|
1663 |
-
?>
|
1664 |
<p style="margin: 10px 0; padding: 10px; font-size: 140%; background-color: lightYellow; border-color: #E6DB55; border: 1px solid; border-radius: 4px;">
|
1665 |
-
<?php echo $ws_ad; ?>
|
1666 |
-
</p>
|
1667 |
<?php
|
1668 |
-
|
1669 |
?>
|
|
|
1670 |
</td>
|
1671 |
</tr>
|
1672 |
<tr>
|
@@ -1748,10 +1818,10 @@ class UpdraftPlus {
|
|
1748 |
echo '</div>';
|
1749 |
}
|
1750 |
|
1751 |
-
if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_all') { $this->
|
1752 |
elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_db') { $this->backup_db(); }
|
1753 |
elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_wipesettings') {
|
1754 |
-
$settings = array('updraft_interval', 'updraft_interval_database', 'updraft_retain', 'updraft_retain_db', 'updraft_encryptionphrase', 'updraft_service', 'updraft_s3_login', 'updraft_s3_pass', 'updraft_s3_remote_path', 'updraft_dropbox_appkey', 'updraft_dropbox_secret', 'updraft_dropbox_folder', 'updraft_googledrive_clientid', 'updraft_googledrive_secret', 'updraft_googledrive_remotepath', 'updraft_ftp_login', 'updraft_ftp_pass', 'updraft_ftp_remote_path', 'updraft_server_address', 'updraft_dir', 'updraft_email', 'updraft_delete_local', 'updraft_debug_mode', 'updraft_include_plugins', 'updraft_include_themes', 'updraft_include_uploads', 'updraft_include_others', 'updraft_include_others_exclude', 'updraft_lastmessage'
|
1755 |
foreach ($settings as $s) {
|
1756 |
UpdraftPlus_Options::delete_updraft_option($s);
|
1757 |
}
|
@@ -1762,7 +1832,7 @@ class UpdraftPlus {
|
|
1762 |
<div class="wrap">
|
1763 |
<h1><?php echo $this->plugin_title; ?></h1>
|
1764 |
|
1765 |
-
Maintained by <b>David Anderson</b> (<a href="http://david.dw-perspective.org.uk">Homepage</a
|
1766 |
<br>
|
1767 |
<?php
|
1768 |
if(isset($_GET['updraft_restore_success'])) {
|
@@ -1770,7 +1840,9 @@ class UpdraftPlus {
|
|
1770 |
}
|
1771 |
|
1772 |
$ws_advert = $this->wordshell_random_advert(1);
|
1773 |
-
|
|
|
|
|
1774 |
|
1775 |
if($deleted_old_dirs) echo '<div style="color:blue">Old directories successfully deleted.</div>';
|
1776 |
|
4 |
Plugin URI: http://wordpress.org/extend/plugins/updraftplus
|
5 |
Description: Backup and restore: your content and database can be automatically backed up to Amazon S3, Dropbox, Google Drive, FTP or email, on separate schedules.
|
6 |
Author: David Anderson.
|
7 |
+
Version: 1.3.2
|
8 |
Donate link: http://david.dw-perspective.org.uk/donate
|
9 |
License: GPLv3 or later
|
10 |
Author URI: http://wordshell.net
|
13 |
/*
|
14 |
TODO
|
15 |
//Add SFTP, Box.Net, SugarSync and Microsoft Skydrive support??
|
|
|
|
|
|
|
|
|
16 |
//improve error reporting / pretty up return messages in admin area. One thing: have a "backup is now finished" flag. Otherwise with the resuming things get ambiguous/confusing. See http://wordpress.org/support/topic/backup-status - user was not aware that backup completely failed. Maybe a "backup status" field for each nonce that gets updated? (Even via AJAX?)
|
17 |
//?? On 'backup now', open up a Lightbox, count down 5 seconds, then start examining the log file (if it can be found)
|
18 |
//Should make clear in dashboard what is a non-fatal error (i.e. can be retried) - leads to unnecessary bug reports
|
19 |
+
//Eventually, when everything can be resumed, we will no longer need the backup() routine; it can be replaced with the resume() routine
|
20 |
// Should we resume if the only errors were upon deletion (i.e. the backup itself was fine?) Presently we do, but it displays errors for the user to confuse them. Perhaps better to make pruning a separate scheuled task??
|
21 |
// Make jobs *individually* resumable (i.e. all the state info must be keyed on the nonce; then call the resume event *specifying the nonce*)
|
22 |
// Warn the user if their zip-file creation is slooowww...
|
23 |
// Create a "Want Support?" button/console, that leads them through what is needed, and performs some basic tests...
|
24 |
// Resuming partial FTP uploads
|
25 |
// Turn expert options into a jQuery toggle
|
26 |
+
// Provide backup/restoration for UpdraftPlus's settings, to allow 'bootstrap' on a fresh WP install
|
27 |
// Multiple jobs
|
28 |
+
// Multi-site
|
|
|
|
|
29 |
|
30 |
Encrypt filesystem, if memory allows (and have option for abort if not); split up into multiple zips when needed
|
31 |
// Does not delete old custom directories upon a restore?
|
72 |
|
73 |
class UpdraftPlus {
|
74 |
|
75 |
+
var $version = '1.3.2';
|
76 |
var $plugin_title = 'UpdraftPlus Backup/Restore';
|
77 |
|
78 |
// Choices will be shown in the admin menu in the order used here
|
88 |
var $dbhandle_isgz;
|
89 |
var $errors = array();
|
90 |
var $nonce;
|
91 |
+
var $cronrun_type = "none";
|
92 |
var $logfile_name = "";
|
93 |
var $logfile_handle = false;
|
94 |
var $backup_time;
|
96 |
var $opened_log_time;
|
97 |
var $backup_dir;
|
98 |
|
|
|
|
|
99 |
function __construct() {
|
100 |
// Initialisation actions - takes place on plugin load
|
101 |
# Create admin page
|
105 |
# backup_all is used by the manual "Backup Now" button
|
106 |
add_action('updraft_backup_all', array($this,'backup_all'));
|
107 |
# this is our runs-after-backup event, whose purpose is to see if it succeeded or failed, and resume/mom-up etc.
|
108 |
+
add_action('updraft_backup_resume', array($this,'backup_resume'));
|
109 |
add_action('wp_enqueue_scripts', array($this, 'ajax_enqueue') );
|
110 |
add_action('wp_ajax_updraft_download_backup', array($this, 'updraft_download_backup'));
|
111 |
add_action('wp_ajax_updraft_ajax', array($this, 'updraft_ajax_handler'));
|
155 |
$this->backup_time = time();
|
156 |
$nonce = substr(md5(time().rand()), 20);
|
157 |
$this->nonce = $nonce;
|
158 |
+
// Short-lived, as we only use this for detecting a race condition
|
159 |
+
set_transient("updraftplus_runtype_$nonce", $this->cronrun_type, 300);
|
160 |
}
|
161 |
|
162 |
function logfile_open($nonce) {
|
176 |
UpdraftPlus_Options::update_updraft_option("updraft_lastmessage", $line." (".date('M d H:i:s').")");
|
177 |
}
|
178 |
|
179 |
+
function backup_resume($resumption_no) {
|
|
|
180 |
@ignore_user_abort(true);
|
181 |
// This is scheduled for 5 minutes after a backup job starts
|
182 |
+
$bnonce = get_transient('updraftplus_backup_job_nonce');
|
183 |
+
if (!$bnonce) return;
|
184 |
+
$this->nonce = $bnonce;
|
185 |
+
$this->logfile_open($bnonce);
|
186 |
+
$this->log("Resume backup ($resumption_no): begin run (will check for any remaining jobs)");
|
187 |
+
$btime = get_transient('updraftplus_backup_job_time');
|
188 |
+
if (!$btime) {
|
189 |
+
$this->log("Did not find stored time setting - aborting");
|
190 |
+
return;
|
191 |
}
|
192 |
+
$this->log("Resuming backup: resumption=$resumption_no, nonce=$bnonce, begun at=$btime");
|
|
|
|
|
193 |
// Schedule again, to run in 5 minutes again, in case we again fail
|
194 |
$resume_delay = 300;
|
195 |
// A different argument than before is needed otherwise the event is ignored
|
196 |
$next_resumption = $resumption_no+1;
|
197 |
if ($next_resumption < 10) {
|
198 |
+
wp_schedule_single_event(time()+$resume_delay, 'updraft_backup_resume' ,array($next_resumption));
|
|
|
199 |
} else {
|
200 |
+
$this->log("The current run is our tenth attempt - will not try again");
|
201 |
}
|
202 |
+
$this->backup_time = $btime;
|
203 |
|
204 |
+
$backup_array = $this->resumable_backup_of_files(false);
|
|
|
205 |
// This save, if there was something, is then immediately picked up again
|
206 |
if (is_array($backup_array)) $this->save_backup_history($backup_array);
|
207 |
|
208 |
// Returns an array, most recent first, of backup sets
|
209 |
$backup_history = $this->get_backup_history();
|
210 |
+
if (!isset($backup_history[$btime])) $this->log("Could not find a record in the database of a backup with this timestamp");
|
|
|
|
|
211 |
|
212 |
$our_files=$backup_history[$btime];
|
213 |
if (!is_array($our_files)) $our_files = array();
|
214 |
|
215 |
$undone_files = array();
|
216 |
|
217 |
+
$backup_database = get_transient("updraft_backdb_".$bnonce);
|
218 |
|
219 |
// The transient is read and written below (instead of using the existing variable) so that we can copy-and-paste this part as needed.
|
220 |
+
if ($backup_database == "begun" || $backup_database == "finished") {
|
221 |
if ($backup_database == "begun") {
|
222 |
+
$this->log("Resuming creation of database dump");
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
} else {
|
224 |
$this->log("Database dump: Creation was completed already");
|
225 |
}
|
226 |
$db_backup = $this->backup_db($backup_database);
|
227 |
if(is_array($our_files) && is_string($db_backup)) $our_files['db'] = $db_backup;
|
228 |
+
$backup_contains = get_transient("updraft_backupcontains_".$this->nonce);
|
229 |
+
$backup_contains = (substr($backup_contains,0,10) == "Files only") ? "Files and database" : "Database only (no files)";
|
230 |
+
set_transient("updraft_backupcontains_".$this->nonce, $backup_contains, 3600*3);
|
231 |
} else {
|
232 |
$this->log("Unrecognised data when trying to ascertain if the database was backed up ($backup_database)");
|
233 |
}
|
241 |
if (isset($our_files['db']) && !preg_match("/\.crypt$/", $our_files['db'])) {
|
242 |
$our_files['db'] = $this->encrypt_file($our_files['db']);
|
243 |
$this->save_backup_history($our_files);
|
|
|
244 |
}
|
245 |
|
246 |
foreach ($our_files as $key => $file) {
|
247 |
|
248 |
+
if ($key == 'nonce') continue;
|
|
|
249 |
|
250 |
$hash = md5($file);
|
251 |
$fullpath = $this->backups_dir_location().'/'.$file;
|
252 |
+
if (get_transient('updraft_'.$hash) === "yes") {
|
253 |
+
$this->log("$file: $key: This file has been successfully uploaded in the last 3 hours");
|
254 |
} elseif (is_file($fullpath)) {
|
255 |
+
$this->log("$file: $key: This file has NOT been successfully uploaded in the last 3 hours: will retry");
|
256 |
$undone_files[$key] = $file;
|
257 |
} else {
|
258 |
$this->log("$file: Note: This file was not marked as successfully uploaded, but does not exist on the local filesystem");
|
262 |
|
263 |
if (count($undone_files) == 0) {
|
264 |
$this->log("There were no more files that needed uploading; backup job is complete");
|
|
|
|
|
265 |
return;
|
266 |
}
|
267 |
|
268 |
$this->log("Requesting backup of the files that were not successfully uploaded");
|
269 |
$this->cloud_backup($undone_files);
|
270 |
|
271 |
+
$this->log("Resume backup ($resumption_no): finish run");
|
272 |
+
|
273 |
$this->backup_finish($next_resumption, true, true, $resumption_no);
|
274 |
|
275 |
}
|
276 |
|
277 |
function backup_all() {
|
278 |
+
$this->backup(true,true);
|
279 |
}
|
280 |
|
281 |
function backup_files() {
|
282 |
# Note that the "false" for database gets over-ridden automatically if they turn out to have the same schedules
|
283 |
+
$this->cronrun_type = "files";
|
284 |
+
$this->backup(true,false);
|
285 |
}
|
286 |
|
287 |
function backup_database() {
|
288 |
# Note that nothing will happen if the file backup had the same schedule
|
289 |
+
$this->cronrun_type = "database";
|
290 |
+
$this->backup(false,true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
}
|
292 |
|
293 |
+
function check_backup_race( $to_delete = false ) {
|
294 |
+
// Avoid caching
|
295 |
+
global $wpdb;
|
296 |
+
$row = $wpdb->get_row($wpdb->prepare("SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", "_transient_updraftplus_backup_job_nonce"));
|
297 |
+
$cur_trans = ( is_object( $row ) ) ? $row->option_value : "";
|
298 |
+
// Check if another backup job ID is stored in the transient
|
299 |
+
if ($cur_trans != "" && $cur_trans != $this->nonce) {
|
300 |
+
// Also check if that job is of the same type as ours, as two cron jobs could legitimately fire at the same time
|
301 |
+
$otherjob_crontype = get_transient("updraftplus_runtype_".$cur_trans);
|
302 |
+
// $this->cronrun_type should be "files", "database" or blank (if we were not run via a cron job)
|
303 |
+
if ($otherjob_crontype == $this->cronrun_type) {
|
304 |
+
$this->log("Another backup job ($cur_trans) of the same type ($otherjob_crontype) appears to now be running - terminating our run (apparent race condition)");
|
305 |
+
$bdir = $this->backups_dir_location();
|
306 |
+
if (is_array($to_delete)) {
|
307 |
+
foreach ($to_delete as $key => $file) {
|
308 |
+
if (is_file($bdir.'/'.$file)) {
|
309 |
+
$this->log("Deleting the file we created: ".$file);
|
310 |
+
@unlink($bdir.'/'.$file);
|
311 |
+
}
|
312 |
+
}
|
313 |
+
}
|
314 |
+
exit;
|
315 |
+
}
|
316 |
}
|
|
|
317 |
}
|
318 |
|
319 |
// This uses a transient; its only purpose is to indicate *total* completion; there is no actual danger, just wasted time, in resuming when it was not needed. So the transient just helps save resources.
|
320 |
+
function resumable_backup_of_files($resumptionrun) {
|
321 |
//backup directories and return a numerically indexed array of file paths to the backup files
|
322 |
+
$transient_status = get_transient("updraft_backf_".$this->nonce);
|
323 |
if ($transient_status == "finished") {
|
324 |
$this->log("Creation of backups of directories: already finished");
|
325 |
} elseif ($transient_status == "begun") {
|
326 |
+
if ($resumptionrun) {
|
327 |
$this->log("Creation of backups of directories: had begun; will resume");
|
328 |
} else {
|
329 |
$this->log("Creation of backups of directories: beginning");
|
335 |
}
|
336 |
// We want this array, even if already finished
|
337 |
$backup_array = $this->backup_dirs($transient_status);
|
338 |
+
$backup_contains = "Files only (no database)";
|
339 |
// This can get over-written later
|
340 |
+
set_transient("updraft_backupcontains_".$this->nonce, $backup_contains, 3600*3);
|
341 |
+
set_transient("updraft_backf_".$this->nonce, "finished", 3600*3);
|
342 |
return $backup_array;
|
343 |
}
|
344 |
|
345 |
+
function backup($backup_files, $backup_database) {
|
|
|
346 |
|
347 |
@ignore_user_abort(true);
|
|
|
348 |
//generate backup information
|
349 |
$this->backup_time_nonce();
|
350 |
+
|
351 |
$this->logfile_open($this->nonce);
|
352 |
|
353 |
// Log some information that may be helpful
|
354 |
global $wp_version;
|
355 |
+
$this->log("Tasks: Backup files: $backup_files (schedule: ".UpdraftPlus_Options::get_updraft_option('updraft_interval','unset').") Backup DB: $backup_database (schedule: ".UpdraftPlus_Options::get_updraft_option('updraft_interval_database','unset').")");
|
356 |
|
357 |
# If the files and database schedules are the same, and if this the file one, then we rope in database too.
|
358 |
# On the other hand, if the schedules were the same and this was the database run, then there is nothing to do.
|
362 |
|
363 |
$this->log("Processed schedules. Tasks now: Backup files: $backup_files Backup DB: $backup_database");
|
364 |
|
365 |
+
$clear_nonce_transient = false;
|
366 |
+
|
367 |
+
# Possibly now nothing is to be done, except to close the log file
|
368 |
+
if ($backup_files || $backup_database) {
|
369 |
+
|
370 |
+
$clear_nonce_transient = true;
|
371 |
+
|
372 |
+
// Do not set the transient or schedule the resume event until now, when we know there is something to do - otherwise 'vacatated' runs (when the database is on the same schedule as the files, and they get combined, leading to an empty run) can over-write the resume event and prevent resumption (because it is 'successful' - there was nothing to do).
|
373 |
+
// If we don't finish in 3 hours, then we won't finish
|
374 |
+
// This transient indicates the identity of the current backup job (which can be used to find the files and logfile)
|
375 |
+
set_transient("updraftplus_backup_job_nonce", $this->nonce, 3600*3);
|
376 |
+
set_transient("updraftplus_backup_job_time", $this->backup_time, 3600*3);
|
377 |
|
378 |
+
// Schedule the event to run later, which checks on success and can resume the backup
|
379 |
+
// We save the time to a variable because it is needed for un-scheduling
|
380 |
+
$resume_delay = 300;
|
381 |
+
wp_schedule_single_event(time()+$resume_delay, 'updraft_backup_resume', array(1));
|
382 |
+
$this->log("In case we run out of time, scheduled a resumption at: $resume_delay seconds from now");
|
383 |
+
|
384 |
+
$backup_contains = "";
|
385 |
+
set_transient("updraft_backupcontains_".$this->nonce, "");
|
386 |
+
|
387 |
+
$backup_array = array();
|
388 |
+
|
389 |
+
$this->check_backup_race();
|
390 |
+
|
391 |
+
// Save what *should* be done, to make it resumable from this point on
|
392 |
+
set_transient("updraft_backdb_".$this->nonce, "begun", 3600*3);
|
393 |
+
|
394 |
+
// The function itself will set to 'finished' if relevant
|
395 |
+
// The presence of the transient indicates that files are supposed to be in this set
|
396 |
+
if ($backup_files) {
|
397 |
+
set_transient("updraft_backf_".$this->nonce, "begun", 3600*3);
|
398 |
+
$backup_array = $this->resumable_backup_of_files(false);
|
399 |
+
}
|
400 |
+
|
401 |
+
// Save this to our history so we can track backups for the retain feature
|
402 |
+
$this->log("Saving backup history");
|
403 |
+
$this->save_backup_history($backup_array);
|
404 |
+
|
405 |
+
$this->check_backup_race($backup_array);
|
406 |
+
|
407 |
+
// The transient is read and written below (instead of using the existing variable) so that we can copy-and-paste this part as needed.
|
408 |
+
if ($backup_database) {
|
409 |
+
$this->log("Beginning backup of database");
|
410 |
+
$db_backup = $this->backup_db();
|
411 |
+
if ($db_backup) $backup_array['db'] = $db_backup;
|
412 |
+
$backup_contains = get_transient("updraft_backupcontains_".$this->nonce);
|
413 |
+
$backup_contains = (substr($backup_contains,0,10) == "Files only") ? "Files and database" : "Database only (no files)";
|
414 |
+
set_transient("updraft_backupcontains_".$this->nonce, $backup_contains, 3600*3);
|
415 |
+
set_transient("updraft_backdb_".$this->nonce, "finished", 3600*3);
|
416 |
+
}
|
417 |
|
418 |
+
$this->check_backup_race($backup_array);
|
419 |
+
|
420 |
+
// Save this to our history so we can track backups for the retain feature
|
421 |
+
$this->log("Saving backup history");
|
422 |
+
// 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.
|
423 |
+
$this->save_backup_history($backup_array);
|
424 |
+
|
425 |
+
// Now encrypt the database, and re-save
|
426 |
+
if ($backup_database && isset($backup_array['db'])) {
|
427 |
+
$backup_array['db'] = $this->encrypt_file($backup_array['db']);
|
428 |
+
// Re-save with the possibly-altered database filename
|
429 |
+
$this->save_backup_history($backup_array);
|
430 |
+
}
|
431 |
+
|
432 |
+
//cloud operations (S3,Google Drive,FTP,email,nothing)
|
433 |
+
//this also calls the retain (prune) feature at the end (done in this method to reuse existing cloud connections)
|
434 |
+
if(is_array($backup_array) && count($backup_array) >0) {
|
435 |
+
$this->cloud_backup($backup_array);
|
436 |
+
}
|
437 |
+
|
438 |
+
//save the last backup info, including errors, if any
|
439 |
+
$this->log("Saving last backup information into WordPress db");
|
440 |
+
$this->save_last_backup($backup_array);
|
441 |
+
|
442 |
+
}
|
443 |
+
|
444 |
+
// Close log file; delete and also delete transients if not in debug mode
|
445 |
+
$this->backup_finish(1, $clear_nonce_transient, $clear_nonce_transient, 0);
|
446 |
|
447 |
}
|
448 |
|
458 |
$rijndael->setKey($encryption);
|
459 |
$updraft_dir = $this->backups_dir_location();
|
460 |
$file_size = @filesize($updraft_dir.'/'.$file)/1024;
|
461 |
+
$in_handle = @fopen($updraft_dir.'/'.$file,'r');
|
462 |
+
$buffer = "";
|
463 |
+
while (!feof ($in_handle)) {
|
464 |
+
$buffer .= fread($in_handle, 16384);
|
465 |
+
}
|
466 |
+
fclose ($in_handle);
|
467 |
+
$out_handle = @fopen($updraft_dir.'/'.$file.'.crypt','w');
|
468 |
+
if (!fwrite($out_handle, $rijndael->encrypt($buffer))) {$encryption_error = 1;}
|
469 |
+
fclose ($out_handle);
|
470 |
if (0 == $encryption_error) {
|
471 |
$time_taken = max(0.000001, microtime(true)-$microstart);
|
472 |
$this->log("$file: encryption successful: ".round($file_size,1)."Kb in ".round($time_taken,1)."s (".round($file_size/$time_taken, 1)."Kb/s)");
|
489 |
if (empty($this->errors)) {
|
490 |
if ($clear_nonce_transient) {
|
491 |
$this->log("There were no errors in the uploads, so the 'resume' event is being unscheduled");
|
492 |
+
wp_clear_scheduled_hook('updraft_backup_resume', array($cancel_event));
|
493 |
+
delete_transient("updraftplus_backup_job_nonce");
|
494 |
+
delete_transient("updraftplus_backup_job_time");
|
495 |
}
|
496 |
} else {
|
497 |
$this->log("There were errors in the uploads, so the 'resume' event is remaining scheduled");
|
554 |
|
555 |
$append_log = ($debug_mode && $this->logfile_name != "") ? "\r\nLog contents:\r\n".file_get_contents($this->logfile_name) : "" ;
|
556 |
|
557 |
+
wp_mail($sendmail_to,'Backed up: '.get_bloginfo('name').' (UpdraftPlus '.$this->version.') '.date('Y-m-d H:i',time()),'Site: '.site_url()."\r\nUpdraftPlus WordPress backup is complete.\r\nBackup contains: ".get_transient("updraft_backupcontains_".$this->nonce)."\r\n\r\n".$this->wordshell_random_advert(0)."\r\n".$append_log);
|
|
|
|
|
|
|
|
|
|
|
558 |
|
559 |
}
|
560 |
|
568 |
|
569 |
// This should be called whenever a file is successfully uploaded
|
570 |
function uploaded_file($file, $id = false) {
|
571 |
+
# We take an MD5 hash because set_transient wants a name of 45 characters or less
|
572 |
$hash = md5($file);
|
573 |
$this->log("Recording as successfully uploaded: $file ($hash)");
|
574 |
+
set_transient("updraft_".$hash, "yes", 3600*4);
|
575 |
if ($id) {
|
576 |
$ids = UpdraftPlus_Options::get_updraft_option('updraft_file_ids', array() );
|
577 |
$ids[$file] = $id;
|
752 |
$rate = round($kbsize/$timetaken, 1);
|
753 |
$this->log("Created $whichone zip - file size is ".round($kbsize,1)." Kb in ".round($timetaken,1)." s ($rate Kb/s)");
|
754 |
}
|
755 |
+
$this->check_backup_race($backup_array);
|
756 |
return basename($full_path);
|
757 |
}
|
758 |
|
802 |
|
803 |
# Others
|
804 |
if (UpdraftPlus_Options::get_updraft_option('updraft_include_others', true)) {
|
805 |
+
$this->log("Beginning backup of other directories found in the content directory");
|
806 |
|
807 |
if ($transient_status == 'finished') {
|
808 |
$backup_array['others'] = $backup_file_basename.'-others.zip';
|
809 |
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
810 |
|
811 |
+
// http://www.phpconcept.net/pclzip/user-guide/53
|
812 |
+
/* First parameter to create is:
|
813 |
+
An array of filenames or dirnames,
|
814 |
+
or
|
815 |
+
A string containing the filename or a dirname,
|
816 |
+
or
|
817 |
+
A string containing a list of filename or dirname separated by a comma.
|
818 |
+
*/
|
819 |
+
|
820 |
+
# Initialise
|
821 |
+
$other_dirlist = array();
|
822 |
+
|
823 |
+
$others_skip = preg_split("/,/",UpdraftPlus_Options::get_updraft_option('updraft_include_others_exclude', UPDRAFT_DEFAULT_OTHERS_EXCLUDE));
|
824 |
+
# Make the values into the keys
|
825 |
+
$others_skip = array_flip($others_skip);
|
826 |
+
|
827 |
+
$this->log('Looking for candidates to back up in: '.WP_CONTENT_DIR);
|
828 |
+
if ($handle = opendir(WP_CONTENT_DIR)) {
|
829 |
+
while (false !== ($entry = readdir($handle))) {
|
830 |
+
$candidate = WP_CONTENT_DIR.'/'.$entry;
|
831 |
+
if ($entry == "." || $entry == "..") { ; }
|
832 |
+
elseif ($candidate == $updraft_dir) { $this->log("others: $entry: skipping: this is the updraft directory"); }
|
833 |
+
elseif ($candidate == $wp_themes_dir) { $this->log("others: $entry: skipping: this is the themes directory"); }
|
834 |
+
elseif ($candidate == $wp_upload_dir) { $this->log("others: $entry: skipping: this is the uploads directory"); }
|
835 |
+
elseif ($candidate == $wp_plugins_dir) { $this->log("others: $entry: skipping: this is the plugins directory"); }
|
836 |
+
elseif (isset($others_skip[$entry])) { $this->log("others: $entry: skipping: excluded by options"); }
|
837 |
+
else { $this->log("others: $entry: adding to list"); array_push($other_dirlist, $candidate); }
|
838 |
}
|
839 |
+
} else {
|
840 |
+
$this->log('ERROR: Could not read the content directory: '.WP_CONTENT_DIR);
|
841 |
+
$this->error('Could not read the content directory: '.WP_CONTENT_DIR);
|
842 |
+
}
|
843 |
+
|
844 |
+
if (count($other_dirlist)>0) {
|
845 |
+
$created = $this->create_zip($other_dirlist, 'others', $updraft_dir, $backup_file_basename);
|
846 |
+
if ($created) $backup_array['others'] = $created;
|
847 |
+
} else {
|
848 |
+
$this->log("No backup of other directories: there was nothing found to back up");
|
849 |
+
}
|
850 |
# If we are not already finished
|
851 |
}
|
852 |
} else {
|
874 |
global $wpdb;
|
875 |
$backup_history = @unserialize($wpdb->get_var($wpdb->prepare("SELECT option_value from $wpdb->options WHERE option_name='updraft_backup_history'")));
|
876 |
if(is_array($backup_history)) {
|
877 |
+
krsort($backup_history); //reverse sort so earliest backup is last on the array. this way we can array_pop
|
878 |
} else {
|
879 |
$backup_history = array();
|
880 |
}
|
935 |
$backup_file_base = $updraft_dir.'/'.$file_base;
|
936 |
|
937 |
if ("finished" == $already_done) return basename($backup_file_base.'-db.gz');
|
|
|
938 |
|
939 |
$total_tables = 0;
|
940 |
|
1072 |
}
|
1073 |
|
1074 |
// Comment in SQL-file
|
1075 |
+
$this->stow("\n\n");
|
1076 |
+
$this->stow("#\n");
|
1077 |
+
$this->stow('# ' . sprintf(__('Data contents of table %s','wp-db-backup'),$this->backquote($table)) . "\n");
|
1078 |
+
$this->stow("#\n");
|
1079 |
}
|
1080 |
|
1081 |
// In UpdraftPlus, segment is always 'none'
|
1091 |
}
|
1092 |
}
|
1093 |
|
1094 |
+
// Batch by $row_inc
|
1095 |
+
if ( ! defined('ROWS_PER_SEGMENT') ) define('ROWS_PER_SEGMENT', 100);
|
1096 |
+
|
1097 |
if($segment == 'none') {
|
1098 |
$row_start = 0;
|
1099 |
+
$row_inc = ROWS_PER_SEGMENT;
|
1100 |
} else {
|
1101 |
+
$row_start = $segment * ROWS_PER_SEGMENT;
|
1102 |
+
$row_inc = ROWS_PER_SEGMENT;
|
1103 |
}
|
|
|
1104 |
do {
|
1105 |
+
|
1106 |
+
if ( !ini_get('safe_mode') || strtolower(ini_get('safe_mode')) == "off") @set_time_limit(15*60);
|
1107 |
$table_data = $wpdb->get_results("SELECT * FROM $table LIMIT {$row_start}, {$row_inc}", ARRAY_A);
|
1108 |
$entries = 'INSERT INTO ' . $this->backquote($table) . ' VALUES (';
|
1109 |
// \x08\\x09, not required
|
1521 |
}
|
1522 |
|
1523 |
function wordshell_random_advert($urls) {
|
|
|
1524 |
$rad = rand(0,6);
|
1525 |
switch ($rad) {
|
1526 |
case 0:
|
1727 |
$dir_info = '<span style="color:red">Backup directory specified is <b>not</b> writable, or does not exist. <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>';
|
1728 |
}
|
1729 |
|
1730 |
+
echo $dir_info ?> This is where Updraft Backup/Restore will write the zip files it creates initially. This directory must be writable by your web server. Typically you'll want to have it inside your wp-content folder (this is the default). <b>Do not</b> place it inside your uploads dir, as that will cause recursion issues (backups of backups of backups of...).</td>
|
1731 |
</tr>
|
1732 |
<tr>
|
1733 |
<td></td>
|
1734 |
<td>
|
|
|
|
|
|
|
|
|
1735 |
<p style="margin: 10px 0; padding: 10px; font-size: 140%; background-color: lightYellow; border-color: #E6DB55; border: 1px solid; border-radius: 4px;">
|
|
|
|
|
1736 |
<?php
|
1737 |
+
echo $this->wordshell_random_advert(1);
|
1738 |
?>
|
1739 |
+
</p>
|
1740 |
</td>
|
1741 |
</tr>
|
1742 |
<tr>
|
1818 |
echo '</div>';
|
1819 |
}
|
1820 |
|
1821 |
+
if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_all') { $this->backup(true,true); }
|
1822 |
elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_db') { $this->backup_db(); }
|
1823 |
elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_wipesettings') {
|
1824 |
+
$settings = array('updraft_interval', 'updraft_interval_database', 'updraft_retain', 'updraft_retain_db', 'updraft_encryptionphrase', 'updraft_service', 'updraft_s3_login', 'updraft_s3_pass', 'updraft_s3_remote_path', 'updraft_dropbox_appkey', 'updraft_dropbox_secret', 'updraft_dropbox_folder', 'updraft_googledrive_clientid', 'updraft_googledrive_secret', 'updraft_googledrive_remotepath', 'updraft_ftp_login', 'updraft_ftp_pass', 'updraft_ftp_remote_path', 'updraft_server_address', 'updraft_dir', 'updraft_email', 'updraft_delete_local', 'updraft_debug_mode', 'updraft_include_plugins', 'updraft_include_themes', 'updraft_include_uploads', 'updraft_include_others', 'updraft_include_others_exclude', 'updraft_lastmessage');
|
1825 |
foreach ($settings as $s) {
|
1826 |
UpdraftPlus_Options::delete_updraft_option($s);
|
1827 |
}
|
1832 |
<div class="wrap">
|
1833 |
<h1><?php echo $this->plugin_title; ?></h1>
|
1834 |
|
1835 |
+
Maintained by <b>David Anderson</b> (<a href="http://david.dw-perspective.org.uk">Homepage</a> | <a href="http://updraftplus.com">Premium</a> | <a href="http://wordshell.net">WordShell - WordPress command line</a> | <a href="http://david.dw-perspective.org.uk/donate">Donate</a> | <a href="http://wordpress.org/extend/plugins/updraftplus/faq/">FAQs</a> | <a href="http://profiles.wordpress.org/davidanderson/">My other WordPress plugins</a>). Version: <?php echo $this->version; ?>
|
1836 |
<br>
|
1837 |
<?php
|
1838 |
if(isset($_GET['updraft_restore_success'])) {
|
1840 |
}
|
1841 |
|
1842 |
$ws_advert = $this->wordshell_random_advert(1);
|
1843 |
+
echo <<<ENDHERE
|
1844 |
+
<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;">${ws_advert}</div>
|
1845 |
+
ENDHERE;
|
1846 |
|
1847 |
if($deleted_old_dirs) echo '<div style="color:blue">Old directories successfully deleted.</div>';
|
1848 |
|