UpdraftPlus WordPress Backup Plugin - Version 1.4.13

Version Description

  • 02/18/2013 =
  • Some extra hooks for "fix time" add-on (http://updraftplus.com/shop/fix-time/)
  • Some internal simplification
  • Small spelling + text fixes
Download this release

Release Info

Developer DavidAnderson
Plugin Icon 128x128 UpdraftPlus WordPress Backup Plugin
Version 1.4.13
Comparing to
See all releases

Code changes from version 1.4.12 to 1.4.13

Files changed (3) hide show
  1. methods/s3.php +1 -0
  2. readme.txt +7 -2
  3. updraftplus.php +50 -29
methods/s3.php CHANGED
@@ -313,6 +313,7 @@ class UpdraftPlus_BackupModule_s3 {
313
 
314
  if (isset($bucket_exists)) {
315
  $try_file = md5(rand());
 
316
  if (!$s3->putObjectString($try_file, $bucket, $path.$try_file)) {
317
  echo "Failure: We successfully $bucket_verb the bucket, but the attempt to create a file in it failed.";
318
  } else {
313
 
314
  if (isset($bucket_exists)) {
315
  $try_file = md5(rand());
316
+ $this->set_endpoint($s3, $location);
317
  if (!$s3->putObjectString($try_file, $bucket, $path.$try_file)) {
318
  echo "Failure: We successfully $bucket_verb the bucket, but the attempt to create a file in it failed.";
319
  } else {
readme.txt CHANGED
@@ -3,13 +3,13 @@ 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.1
6
- Stable tag: 1.4.11
7
  Author URI: http://updraftplus.com
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
10
 
11
  == Upgrade Notice ==
12
- Important fix for people backing up databases without encryption
13
 
14
  == Description ==
15
 
@@ -100,6 +100,11 @@ Thanks for asking - yes, I have. Check out my profile page - http://profiles.wor
100
 
101
  == Changelog ==
102
 
 
 
 
 
 
103
  = 1.4.11 - 02/13/2013 =
104
  * Various branding tweaks - <a href="http://updraftplus.com">launch of updraftplus.com</a>
105
  * Important fix for people with non-encrypted database backups
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.1
6
+ Stable tag: 1.4.13
7
  Author URI: http://updraftplus.com
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
10
 
11
  == Upgrade Notice ==
12
+ Minor tweaks
13
 
14
  == Description ==
15
 
100
 
101
  == Changelog ==
102
 
103
+ = 1.4.13 - 02/18/2013 =
104
+ * Some extra hooks for "fix time" add-on (http://updraftplus.com/shop/fix-time/)
105
+ * Some internal simplification
106
+ * Small spelling + text fixes
107
+
108
  = 1.4.11 - 02/13/2013 =
109
  * Various branding tweaks - <a href="http://updraftplus.com">launch of updraftplus.com</a>
110
  * Important fix for people with non-encrypted database backups
updraftplus.php CHANGED
@@ -1,13 +1,13 @@
1
  <?php
2
  /*
3
  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.4.12
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
10
- Author URI: http://updraftplus.com
11
  */
12
 
13
  /*
@@ -27,11 +27,8 @@ TODO
27
  // Resuming partial FTP uploads
28
  // Provide backup/restoration for UpdraftPlus's settings, to allow 'bootstrap' on a fresh WP install - some kind of single-use code which a remote UpdraftPlus can use to authenticate
29
  // Multiple jobs
30
- // Expert setting: force PCLZip
31
- // Don't stop at 10 retries if something useful is still measurably being done (in particular, chunked uploads are proceeding - set a flag to indicate "try it again")
32
  // Change FTP to use SSL by default
33
  // Multisite add-on should allow restoring of each blog individually
34
- // Tweak random_advert to not show the same one twice
35
  // When looking for files to delete, is the current encryption setting used? Should not be.
36
  // Create single zip, containing even WordPress itself
37
  // Have something reap any remaining .tmp files, e.g. once a week
@@ -80,12 +77,13 @@ define('UPDRAFT_TRANSTIME', 3600*9+5);
80
  // Load add-ons
81
  if (is_file(UPDRAFTPLUS_DIR.'/premium.php')) require_once(UPDRAFTPLUS_DIR.'/premium.php');
82
 
83
- if ($dir_handle = @opendir(UPDRAFTPLUS_DIR.'/addons')) {
84
  while ($e = readdir($dir_handle)) {
85
  if (is_file(UPDRAFTPLUS_DIR.'/addons/'.$e) && preg_match('/\.php$/', $e)) {
86
  include_once(UPDRAFTPLUS_DIR.'/addons/'.$e);
87
  }
88
  }
 
89
  }
90
 
91
  if (!isset($updraftplus)) $updraftplus = new UpdraftPlus();
@@ -190,6 +188,21 @@ class UpdraftPlus {
190
  }
191
  }
192
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
  # Adds the settings link under the plugin on the plugin screen.
194
  function plugin_action_links($links, $file) {
195
  if ($file == plugin_basename(__FILE__)){
@@ -252,11 +265,11 @@ class UpdraftPlus {
252
  $schedule_for = time()+$resume_interval;
253
  $this->newresumption_scheduled = $schedule_for;
254
  $this->log("This is resumption ".$this->current_resumption.", but meaningful uploading is still taking place; so a new one will be scheduled");
255
- wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($this->current_resumption + 1, $this->nonce, $this->backup_time));
256
  }
257
  }
258
 
259
- function backup_resume($resumption_no, $bnonce, $btime) {
260
 
261
  @ignore_user_abort(true);
262
  // This is scheduled for 5 minutes after a backup job starts
@@ -264,10 +277,12 @@ class UpdraftPlus {
264
  // Restore state
265
  if ($resumption_no > 0) {
266
  $this->nonce = $bnonce;
267
- $this->backup_time = $btime;
268
  $this->logfile_open($bnonce);
269
  }
270
 
 
 
271
  $this->log("Backup run: resumption=$resumption_no, nonce=$bnonce, begun at=$btime");
272
  $this->current_resumption = $resumption_no;
273
 
@@ -281,7 +296,7 @@ class UpdraftPlus {
281
  if ($next_resumption < 10) {
282
  $this->log("Scheduling a resumption ($next_resumption) in case this run gets aborted");
283
  $schedule_for = time()+$resume_interval;
284
- wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($next_resumption, $bnonce, $btime));
285
  $this->newresumption_scheduled = $schedule_for;
286
  } else {
287
  $this->log("The current run is our tenth attempt - will not schedule a further attempt until we see something useful happening");
@@ -306,7 +321,7 @@ class UpdraftPlus {
306
  $backup_database = $this->jobdata_get('backup_database');
307
 
308
  // The transient is read and written below (instead of using the existing variable) so that we can copy-and-paste this part as needed.
309
- if ($backup_database == "begun" || $backup_database == "finished" || $backup_database == 'encrypted') {
310
  if ($backup_database == "begun") {
311
  if ($resumption_no > 0) {
312
  $this->log("Resuming creation of database dump");
@@ -405,8 +420,8 @@ class UpdraftPlus {
405
  // 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.
406
  function resumable_backup_of_files($resumption_no) {
407
  //backup directories and return a numerically indexed array of file paths to the backup files
408
- $transient_status = $this->jobdata_get("backup_files");
409
- if ($transient_status == "finished") {
410
  $this->log("Creation of backups of directories: already finished");
411
  } elseif ($transient_status == "begun") {
412
  if ($resumption_no>0) {
@@ -435,6 +450,9 @@ class UpdraftPlus {
435
  $this->backup_time_nonce();
436
  $this->logfile_open($this->nonce);
437
 
 
 
 
438
  // Log some information that may be helpful
439
  $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').")");
440
 
@@ -453,15 +471,17 @@ class UpdraftPlus {
453
  }
454
 
455
  // Save what *should* be done, to make it resumable from this point on
456
- if ($backup_database) $this->jobdata_set("backup_database", "begun");
457
- if ($backup_files) $this->jobdata_set("backup_files", "begun");
458
  $this->jobdata_set('service', UpdraftPlus_Options::get_updraft_option('updraft_service'));
459
 
460
  // This can be adapted if we see a need
461
  $this->jobdata_set('resume_interval', 300);
462
 
 
 
463
  // Everthing is now set up; now go
464
- $this->backup_resume(0, $this->nonce, $this->backup_time);
465
 
466
  }
467
 
@@ -500,7 +520,7 @@ class UpdraftPlus {
500
  if (empty($this->errors)) {
501
  if ($clear_nonce_transient) {
502
  $this->log("There were no errors in the uploads, so the 'resume' event is being unscheduled");
503
- wp_clear_scheduled_hook('updraft_backup_resume', array($cancel_event, $this->nonce, $this->backup_time));
504
  // TODO: Delete the job transient (is presently useful for debugging, and only lasts 4 hours)
505
  }
506
  } else {
@@ -560,23 +580,23 @@ class UpdraftPlus {
560
 
561
  $sendmail_to = UpdraftPlus_Options::get_updraft_option('updraft_email');
562
 
563
- $this->log("Sending email report to: ".substr($sendmail_to, 0, 5)."...");
564
-
565
- $append_log = ($debug_mode && $this->logfile_name != "") ? "\r\nLog contents:\r\n".file_get_contents($this->logfile_name) : "" ;
566
-
567
- $backup_files = $this->jobdata_get("backup_files");
568
  $backup_db = $this->jobdata_get("backup_database");
569
 
570
- if ($backup_files == "finished" && ( $backup_db == "finished" || $backup_db == 'encrypted' ) ) {
571
  $backup_contains = "Files and database";
572
- } elseif ($backup_files == "finished") {
573
  $backup_contains = ($backup_db == "begun") ? "Files (database backup has not completed)" : "Files only (database was not part of this particular schedule)";
574
- } elseif ($backup_db == "finished" || $backup_db == 'encrypted') {
575
  $backup_contains = ($backup_files == "begun") ? "Database (files backup has not completed)" : "Database only (files were not part of this particular schedule)";
576
  } else {
577
  $backup_contains = "Unknown/unexpected error - please raise a support request";
578
  }
579
 
 
 
 
 
580
  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);
581
 
582
  }
@@ -740,11 +760,11 @@ class UpdraftPlus {
740
 
741
  function reschedule($how_far_ahead) {
742
  // Reschedule - remove presently scheduled event
743
- wp_clear_scheduled_hook('updraft_backup_resume', array($this->current_resumption + 1, $this->nonce, $this->backup_time));
744
  // Add new event
745
  if ($how_far_ahead < 200) $how_far_ahead=200;
746
  $schedule_for = time() + $how_far_ahead;
747
- wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($this->current_resumption + 1, $this->nonce, $this->backup_time));
748
  $this->newresumption_scheduled = $schedule_for;
749
  }
750
 
@@ -880,6 +900,7 @@ class UpdraftPlus {
880
  elseif (isset($others_skip[$entry])) { $this->log("others: $entry: skipping: excluded by options"); }
881
  else { $this->log("others: $entry: adding to list"); array_push($other_dirlist, $candidate); }
882
  }
 
883
  } else {
884
  $this->log('ERROR: Could not read the content directory: '.WP_CONTENT_DIR);
885
  $this->error('Could not read the content directory: '.WP_CONTENT_DIR);
@@ -978,7 +999,7 @@ class UpdraftPlus {
978
  $file_base = 'backup_'.date('Y-m-d-Hi',$this->backup_time).'_'.$blog_name.'_'.$this->nonce;
979
  $backup_file_base = $updraft_dir.'/'.$file_base;
980
 
981
- if ("finished" == $already_done) return basename($backup_file_base.'-db.gz');
982
  if ('encrypted' == $already_done) return basename($backup_file_base.'-db.gz.crypt');
983
 
984
  $total_tables = 0;
1
  <?php
2
  /*
3
  Plugin Name: UpdraftPlus - Backup/Restore
4
+ Plugin URI: http://updraftplus.com
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.4.13
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
10
+ Author URI: http://wordshell.net
11
  */
12
 
13
  /*
27
  // Resuming partial FTP uploads
28
  // Provide backup/restoration for UpdraftPlus's settings, to allow 'bootstrap' on a fresh WP install - some kind of single-use code which a remote UpdraftPlus can use to authenticate
29
  // Multiple jobs
 
 
30
  // Change FTP to use SSL by default
31
  // Multisite add-on should allow restoring of each blog individually
 
32
  // When looking for files to delete, is the current encryption setting used? Should not be.
33
  // Create single zip, containing even WordPress itself
34
  // Have something reap any remaining .tmp files, e.g. once a week
77
  // Load add-ons
78
  if (is_file(UPDRAFTPLUS_DIR.'/premium.php')) require_once(UPDRAFTPLUS_DIR.'/premium.php');
79
 
80
+ if ($dir_handle = opendir(UPDRAFTPLUS_DIR.'/addons')) {
81
  while ($e = readdir($dir_handle)) {
82
  if (is_file(UPDRAFTPLUS_DIR.'/addons/'.$e) && preg_match('/\.php$/', $e)) {
83
  include_once(UPDRAFTPLUS_DIR.'/addons/'.$e);
84
  }
85
  }
86
+ @closedir($dir_handle);
87
  }
88
 
89
  if (!isset($updraftplus)) $updraftplus = new UpdraftPlus();
188
  }
189
  }
190
 
191
+ // Cleans up temporary files found in the updraft directory
192
+ function clean_temporary_files() {
193
+ $updraft_dir = $this->backups_dir_location();
194
+ if ($handle = opendir($updraft_dir)) {
195
+ $now_time=time();
196
+ while (false !== ($entry = readdir($handle))) {
197
+ if (preg_match('/\.tmp(\.gz)?$/', $entry) && is_file($updraft_dir.'/'.$entry) && $now_time-filemtime($updraft_dir.'/'.$entry)>86400) {
198
+ $this->log("Deleting old temporary file: $entry");
199
+ @unlink($updraft_dir.'/'.$entry);
200
+ }
201
+ }
202
+ @closedir($handle);
203
+ }
204
+ }
205
+
206
  # Adds the settings link under the plugin on the plugin screen.
207
  function plugin_action_links($links, $file) {
208
  if ($file == plugin_basename(__FILE__)){
265
  $schedule_for = time()+$resume_interval;
266
  $this->newresumption_scheduled = $schedule_for;
267
  $this->log("This is resumption ".$this->current_resumption.", but meaningful uploading is still taking place; so a new one will be scheduled");
268
+ wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($this->current_resumption + 1, $this->nonce));
269
  }
270
  }
271
 
272
+ function backup_resume($resumption_no, $bnonce) {
273
 
274
  @ignore_user_abort(true);
275
  // This is scheduled for 5 minutes after a backup job starts
277
  // Restore state
278
  if ($resumption_no > 0) {
279
  $this->nonce = $bnonce;
280
+ $this->backup_time = $this->jobdata_get('backup_time');
281
  $this->logfile_open($bnonce);
282
  }
283
 
284
+ $btime = $this->backup_time;
285
+
286
  $this->log("Backup run: resumption=$resumption_no, nonce=$bnonce, begun at=$btime");
287
  $this->current_resumption = $resumption_no;
288
 
296
  if ($next_resumption < 10) {
297
  $this->log("Scheduling a resumption ($next_resumption) in case this run gets aborted");
298
  $schedule_for = time()+$resume_interval;
299
+ wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($next_resumption, $bnonce));
300
  $this->newresumption_scheduled = $schedule_for;
301
  } else {
302
  $this->log("The current run is our tenth attempt - will not schedule a further attempt until we see something useful happening");
321
  $backup_database = $this->jobdata_get('backup_database');
322
 
323
  // The transient is read and written below (instead of using the existing variable) so that we can copy-and-paste this part as needed.
324
+ if ($backup_database == "begun" || $backup_database == 'finished' || $backup_database == 'encrypted') {
325
  if ($backup_database == "begun") {
326
  if ($resumption_no > 0) {
327
  $this->log("Resuming creation of database dump");
420
  // 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.
421
  function resumable_backup_of_files($resumption_no) {
422
  //backup directories and return a numerically indexed array of file paths to the backup files
423
+ $transient_status = $this->jobdata_get('backup_files');
424
+ if ($transient_status == 'finished') {
425
  $this->log("Creation of backups of directories: already finished");
426
  } elseif ($transient_status == "begun") {
427
  if ($resumption_no>0) {
450
  $this->backup_time_nonce();
451
  $this->logfile_open($this->nonce);
452
 
453
+ // Some house-cleaning
454
+ $this->clean_temporary_files();
455
+
456
  // Log some information that may be helpful
457
  $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').")");
458
 
471
  }
472
 
473
  // Save what *should* be done, to make it resumable from this point on
474
+ if ($backup_database) $this->jobdata_set("backup_database", 'begun');
475
+ if ($backup_files) $this->jobdata_set('backup_files', 'begun');
476
  $this->jobdata_set('service', UpdraftPlus_Options::get_updraft_option('updraft_service'));
477
 
478
  // This can be adapted if we see a need
479
  $this->jobdata_set('resume_interval', 300);
480
 
481
+ $this->jobdata_set('backup_time', $this->backup_time);
482
+
483
  // Everthing is now set up; now go
484
+ $this->backup_resume(0, $this->nonce);
485
 
486
  }
487
 
520
  if (empty($this->errors)) {
521
  if ($clear_nonce_transient) {
522
  $this->log("There were no errors in the uploads, so the 'resume' event is being unscheduled");
523
+ wp_clear_scheduled_hook('updraft_backup_resume', array($cancel_event, $this->nonce));
524
  // TODO: Delete the job transient (is presently useful for debugging, and only lasts 4 hours)
525
  }
526
  } else {
580
 
581
  $sendmail_to = UpdraftPlus_Options::get_updraft_option('updraft_email');
582
 
583
+ $backup_files = $this->jobdata_get('backup_files');
 
 
 
 
584
  $backup_db = $this->jobdata_get("backup_database");
585
 
586
+ if ($backup_files == 'finished' && ( $backup_db == 'finished' || $backup_db == 'encrypted' ) ) {
587
  $backup_contains = "Files and database";
588
+ } elseif ($backup_files == 'finished') {
589
  $backup_contains = ($backup_db == "begun") ? "Files (database backup has not completed)" : "Files only (database was not part of this particular schedule)";
590
+ } elseif ($backup_db == 'finished' || $backup_db == 'encrypted') {
591
  $backup_contains = ($backup_files == "begun") ? "Database (files backup has not completed)" : "Database only (files were not part of this particular schedule)";
592
  } else {
593
  $backup_contains = "Unknown/unexpected error - please raise a support request";
594
  }
595
 
596
+ $this->log("Sending email ('$backup_contains') report to: ".substr($sendmail_to, 0, 5)."...");
597
+
598
+ $append_log = ($debug_mode && $this->logfile_name != "") ? "\r\nLog contents:\r\n".file_get_contents($this->logfile_name) : "" ;
599
+
600
  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);
601
 
602
  }
760
 
761
  function reschedule($how_far_ahead) {
762
  // Reschedule - remove presently scheduled event
763
+ wp_clear_scheduled_hook('updraft_backup_resume', array($this->current_resumption + 1, $this->nonce));
764
  // Add new event
765
  if ($how_far_ahead < 200) $how_far_ahead=200;
766
  $schedule_for = time() + $how_far_ahead;
767
+ wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($this->current_resumption + 1, $this->nonce));
768
  $this->newresumption_scheduled = $schedule_for;
769
  }
770
 
900
  elseif (isset($others_skip[$entry])) { $this->log("others: $entry: skipping: excluded by options"); }
901
  else { $this->log("others: $entry: adding to list"); array_push($other_dirlist, $candidate); }
902
  }
903
+ @closedir($handle);
904
  } else {
905
  $this->log('ERROR: Could not read the content directory: '.WP_CONTENT_DIR);
906
  $this->error('Could not read the content directory: '.WP_CONTENT_DIR);
999
  $file_base = 'backup_'.date('Y-m-d-Hi',$this->backup_time).'_'.$blog_name.'_'.$this->nonce;
1000
  $backup_file_base = $updraft_dir.'/'.$file_base;
1001
 
1002
+ if ('finished' == $already_done) return basename($backup_file_base.'-db.gz');
1003
  if ('encrypted' == $already_done) return basename($backup_file_base.'-db.gz.crypt');
1004
 
1005
  $total_tables = 0;