UpdraftPlus WordPress Backup Plugin - Version 1.7.20

Version Description

  • 2013/09/20 =
  • TWEAK: Add semaphore locking to prevent WP's cron system kicking off multiple jobs on overloaded systems
  • TWEAK: Catch and display some previously uncaught AJAX notices when restoring, and display information on the restore process earlier
Download this release

Release Info

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

Code changes from version 1.7.18 to 1.7.20

admin.php CHANGED
@@ -85,7 +85,9 @@ class UpdraftPlus_Admin {
85
 
86
  wp_localize_script( 'updraftplus-admin-ui', 'updraftlion', array(
87
  'rescanning' => __('Rescanning (looking for backups that you have uploaded manually into the internal backup store)...','updraftplus'),
 
88
  'unexpectedresponse' => __('Unexpected response:','updraftplus'),
 
89
  'calculating' => __('calculating...','updraftplus'),
90
  'begunlooking' => __('Begun looking for this entity','updraftplus'),
91
  'stilldownloading' => __('Some files are still downloading or being processed - please wait.', 'updraftplus'),
@@ -116,7 +118,7 @@ class UpdraftPlus_Admin {
116
  'uploaded' => __('The file was uploaded.','updraftplus'),
117
  'backupnow' => __('Backup Now', 'updraftplus'),
118
  'cancel' => __('Cancel', 'updraftplus'),
119
- 'delete' => __('Delete', 'updraftplus'),
120
  'close' => __('Close', 'updraftplus'),
121
  'restore' => __('Restore', 'updraftplus'),
122
  ) );
@@ -1444,7 +1446,7 @@ CREATE TABLE $wpdb->signups (
1444
  </p>
1445
  <p style="max-width: 740px;"><ul style="list-style: disc inside;">
1446
  <li><strong><?php _e('Downloading','updraftplus');?>:</strong> <?php _e("Pressing a button for Database/Plugins/Themes/Uploads/Others will make UpdraftPlus try to bring the backup file back from the remote storage (if any - e.g. Amazon S3, Dropbox, Google Drive, FTP) to your webserver. Then you will be allowed to download it to your computer. If the fetch from the remote storage stops progressing (wait 30 seconds to make sure), then press again to resume. Remember that you can also visit the cloud storage vendor's website directly.",'updraftplus');?></li>
1447
- <li><strong><?php _e('Restoring','updraftplus');?>:</strong> <?php _e("Press the button for the backup you wish to restore. If your site is large and you are using remote storage, then you should first click on each entity in order to retrieve it back to the webserver. This will prevent time-outs from occuring during the restore process itself.",'updraftplus');?> <?php _e('More tasks:','updraftplus');?> <a href="#" onclick="jQuery('#updraft-plupload-modal').slideToggle(); return false;"><?php _e('upload backup files','updraftplus');?></a> | <a href="#" onclick="updraft_updatehistory(1); return false;" title="<?php _e('Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below.','updraftplus'); ?>"><?php _e('rescan folder for new backup sets','updraftplus');?></a></li>
1448
  <li><strong><?php _e('Opera web browser','updraftplus');?>:</strong> <?php _e('If you are using this, then turn Turbo/Road mode off.','updraftplus');?></li>
1449
 
1450
  <?php
@@ -1460,8 +1462,8 @@ CREATE TABLE $wpdb->signups (
1460
  <div id="plupload-upload-ui" style="width: 70%;">
1461
  <div id="drag-drop-area">
1462
  <div class="drag-drop-inside">
1463
- <p class="drag-drop-info"><?php _e('Drop backup zips here', 'updraftplus'); ?></p>
1464
- <p><?php _ex('or', 'Uploader: Drop zip files here - or - Select Files'); ?></p>
1465
  <p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
1466
  </div>
1467
  </div>
@@ -1713,7 +1715,7 @@ CREATE TABLE $wpdb->signups (
1713
  #if (!is_array($jobdata)) $jobdata = array();
1714
  if (!isset($jobdata['backup_time'])) return '';
1715
 
1716
- $began_at = (isset($jobdata['backup_time'])) ? get_date_from_gmt(gmdate('Y-m-d H:i:s', $jobdata['backup_time']), 'D, F j, Y H:i') : '?';
1717
 
1718
  $jobstatus = empty($jobdata['jobstatus']) ? 'unknown' : $jobdata['jobstatus'];
1719
  $stage = 0;
@@ -1806,10 +1808,11 @@ CREATE TABLE $wpdb->signups (
1806
  }
1807
  }
1808
 
1809
- $next_res_txt = ($is_oneshot) ? '' : ' - '.sprintf(__("next resumption: %d (after %ss)", 'updraftplus'), $next_resumption, $time-time()). ' ';
 
1810
  $last_activity_txt = ($last_checkin_ago >= 0) ? ' - '.sprintf(__('last activity: %ss ago', 'updraftplus'), floor($last_checkin_ago)).' ' : '';
1811
 
1812
- if ($last_checkin_ago < 50 || $is_oneshot) {
1813
  $show_inline_info = $last_activity_txt;
1814
  $title_info = $next_res_txt;
1815
  } else {
@@ -1976,7 +1979,7 @@ CREATE TABLE $wpdb->signups (
1976
  if($updraft_last_backup) {
1977
 
1978
  // Convert to GMT, then to blog time
1979
- $last_backup_text = "<span style=\"color:".(($updraft_last_backup['success']) ? 'green' : 'black').";\">".get_date_from_gmt(gmdate('Y-m-d H:i:s', $updraft_last_backup['backup_time']), 'D, F j, Y H:i').'</span><br>';
1980
 
1981
  if (is_array($updraft_last_backup['errors'])) {
1982
  foreach ($updraft_last_backup['errors'] as $err) {
@@ -2413,7 +2416,7 @@ CREATE TABLE $wpdb->signups (
2413
  # https://core.trac.wordpress.org/ticket/25331
2414
  # $pretty_date = date_i18n('Y-m-d G:i',$key);
2415
  // Convert to blog time zone
2416
- $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', $key), 'Y-m-d G:i');
2417
 
2418
  $esc_pretty_date=esc_attr($pretty_date);
2419
  $entities = '';
85
 
86
  wp_localize_script( 'updraftplus-admin-ui', 'updraftlion', array(
87
  'rescanning' => __('Rescanning (looking for backups that you have uploaded manually into the internal backup store)...','updraftplus'),
88
+ 'restoreproceeding' => __('The restore operation has begun. Do not press stop or close your browser until it reports itself as having finished.', 'updraftplus'),
89
  'unexpectedresponse' => __('Unexpected response:','updraftplus'),
90
+ 'servererrorcode' => __('The web server returned an error code (try again, or check your web server logs)', 'updraftplus'),
91
  'calculating' => __('calculating...','updraftplus'),
92
  'begunlooking' => __('Begun looking for this entity','updraftplus'),
93
  'stilldownloading' => __('Some files are still downloading or being processed - please wait.', 'updraftplus'),
118
  'uploaded' => __('The file was uploaded.','updraftplus'),
119
  'backupnow' => __('Backup Now', 'updraftplus'),
120
  'cancel' => __('Cancel', 'updraftplus'),
121
+ 'deletebutton' => __('Delete', 'updraftplus'),
122
  'close' => __('Close', 'updraftplus'),
123
  'restore' => __('Restore', 'updraftplus'),
124
  ) );
1446
  </p>
1447
  <p style="max-width: 740px;"><ul style="list-style: disc inside;">
1448
  <li><strong><?php _e('Downloading','updraftplus');?>:</strong> <?php _e("Pressing a button for Database/Plugins/Themes/Uploads/Others will make UpdraftPlus try to bring the backup file back from the remote storage (if any - e.g. Amazon S3, Dropbox, Google Drive, FTP) to your webserver. Then you will be allowed to download it to your computer. If the fetch from the remote storage stops progressing (wait 30 seconds to make sure), then press again to resume. Remember that you can also visit the cloud storage vendor's website directly.",'updraftplus');?></li>
1449
+ <li><strong><?php _e('Restoring:','updraftplus');?></strong> <?php _e('Press the Restore button next to the chosen backup set.', 'updraftplus');?> <strong><?php _e('More tasks:','updraftplus');?></strong> <a href="#" onclick="jQuery('#updraft-plupload-modal').slideToggle(); return false;"><?php _e('upload backup files','updraftplus');?></a> | <a href="#" onclick="updraft_updatehistory(1); return false;" title="<?php _e('Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below.','updraftplus'); ?>"><?php _e('rescan folder for new backup sets','updraftplus');?></a></li>
1450
  <li><strong><?php _e('Opera web browser','updraftplus');?>:</strong> <?php _e('If you are using this, then turn Turbo/Road mode off.','updraftplus');?></li>
1451
 
1452
  <?php
1462
  <div id="plupload-upload-ui" style="width: 70%;">
1463
  <div id="drag-drop-area">
1464
  <div class="drag-drop-inside">
1465
+ <p class="drag-drop-info"><?php _e('Drop backup files here', 'updraftplus'); ?></p>
1466
+ <p><?php _ex('or', 'Uploader: Drop backup files here - or - Select Files'); ?></p>
1467
  <p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
1468
  </div>
1469
  </div>
1715
  #if (!is_array($jobdata)) $jobdata = array();
1716
  if (!isset($jobdata['backup_time'])) return '';
1717
 
1718
+ $began_at = (isset($jobdata['backup_time'])) ? get_date_from_gmt(gmdate('Y-m-d H:i:s', (int)$jobdata['backup_time']), 'D, F j, Y H:i') : '?';
1719
 
1720
  $jobstatus = empty($jobdata['jobstatus']) ? 'unknown' : $jobdata['jobstatus'];
1721
  $stage = 0;
1808
  }
1809
  }
1810
 
1811
+ $next_res_after = $time-time();
1812
+ $next_res_txt = ($is_oneshot) ? '' : ' - '.sprintf(__("next resumption: %d (after %ss)", 'updraftplus'), $next_resumption, $next_res_after). ' ';
1813
  $last_activity_txt = ($last_checkin_ago >= 0) ? ' - '.sprintf(__('last activity: %ss ago', 'updraftplus'), floor($last_checkin_ago)).' ' : '';
1814
 
1815
+ if (($last_checkin_ago < 50 && $next_res_after>30) || $is_oneshot) {
1816
  $show_inline_info = $last_activity_txt;
1817
  $title_info = $next_res_txt;
1818
  } else {
1979
  if($updraft_last_backup) {
1980
 
1981
  // Convert to GMT, then to blog time
1982
+ $last_backup_text = "<span style=\"color:".(($updraft_last_backup['success']) ? 'green' : 'black').";\">".get_date_from_gmt(gmdate('Y-m-d H:i:s', (int)$updraft_last_backup['backup_time']), 'D, F j, Y H:i').'</span><br>';
1983
 
1984
  if (is_array($updraft_last_backup['errors'])) {
1985
  foreach ($updraft_last_backup['errors'] as $err) {
2416
  # https://core.trac.wordpress.org/ticket/25331
2417
  # $pretty_date = date_i18n('Y-m-d G:i',$key);
2418
  // Convert to blog time zone
2419
+ $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', (int)$key), 'Y-m-d G:i');
2420
 
2421
  $esc_pretty_date=esc_attr($pretty_date);
2422
  $entities = '';
backup.php CHANGED
@@ -876,7 +876,7 @@ class UpdraftPlus_Backup {
876
  $updraftplus->log("Table $table: Total expected rows (approximate): ".$rows);
877
  $this->stow("# Approximate rows expected in table: $rows\n");
878
  if ($rows > UPDRAFTPLUS_WARN_DB_ROWS) {
879
- $updraftplus->log(sprintf(__("Table %s has very many rows (%s) - we hope your web hosting company gives you enough resources to dump out that table in the backup", 'updraftplus'), $table, $rows), 'warning');
880
  }
881
  }
882
 
876
  $updraftplus->log("Table $table: Total expected rows (approximate): ".$rows);
877
  $this->stow("# Approximate rows expected in table: $rows\n");
878
  if ($rows > UPDRAFTPLUS_WARN_DB_ROWS) {
879
+ $updraftplus->log(sprintf(__("Table %s has very many rows (%s) - we hope your web hosting company gives you enough resources to dump out that table in the backup", 'updraftplus'), $table, $rows), 'warning', 'manyrows_'.$table);
880
  }
881
  }
882
 
includes/class-semaphore.php ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Adapted from WP Social under the GPL - thanks to Alex King (https://github.com/crowdfavorite/wp-social)
3
+ /**
4
+ * Semaphore Lock Management
5
+ */
6
+ class UpdraftPlus_Semaphore {
7
+
8
+ /**
9
+ * Initializes the semaphore object.
10
+ *
11
+ * @static
12
+ * @return UpdraftPlus_Semaphore
13
+ */
14
+ public static function factory() {
15
+ return new self;
16
+ }
17
+
18
+ /**
19
+ * @var bool
20
+ */
21
+ protected $lock_broke = false;
22
+
23
+ public $lock_name = 'lock';
24
+
25
+ /**
26
+ * Attempts to start the lock. If the rename works, the lock is started.
27
+ *
28
+ * @return bool
29
+ */
30
+ public function lock() {
31
+ global $wpdb, $updraftplus;
32
+
33
+ // Attempt to set the lock
34
+ $affected = $wpdb->query("
35
+ UPDATE $wpdb->options
36
+ SET option_name = 'updraftplus_locked_".$this->lock_name."'
37
+ WHERE option_name = 'updraftplus_unlocked_".$this->lock_name."'
38
+ ");
39
+
40
+ if ($affected == '0' and !$this->stuck_check()) {
41
+ $updraftplus->log('Semaphore lock ('.$this->lock_name.') failed. (Line '.__LINE__.')');
42
+ return false;
43
+ }
44
+
45
+ // Check to see if all processes are complete
46
+ $affected = $wpdb->query("
47
+ UPDATE $wpdb->options
48
+ SET option_value = CAST(option_value AS UNSIGNED) + 1
49
+ WHERE option_name = 'updraftplus_semaphore_".$this->lock_name."'
50
+ AND option_value = '0'
51
+ ");
52
+ if ($affected != '1') {
53
+ if (!$this->stuck_check()) {
54
+ $updraftplus->log('Semaphore lock ('.$this->lock_name.') failed. (Line '.__LINE__.')');
55
+ return false;
56
+ }
57
+
58
+ // Reset the semaphore to 1
59
+ $wpdb->query("
60
+ UPDATE $wpdb->options
61
+ SET option_value = '1'
62
+ WHERE option_name = 'updraftplus_semaphore_".$this->lock_name."'
63
+ ");
64
+
65
+ $updraftplus->log('Semaphore ('.$this->lock_name.') reset to 1.');
66
+ }
67
+
68
+ // Set the lock time
69
+ $wpdb->query($wpdb->prepare("
70
+ UPDATE $wpdb->options
71
+ SET option_value = %s
72
+ WHERE option_name = 'updraftplus_last_lock_time_".$this->lock_name."'
73
+ ", current_time('mysql', 1)));
74
+ $updraftplus->log('Set semaphore last lock ('.$this->lock_name.') time to '.current_time('mysql', 1));
75
+
76
+ $updraftplus->log('Semaphore lock ('.$this->lock_name.') complete.');
77
+ return true;
78
+ }
79
+
80
+ /**
81
+ * Increment the semaphore.
82
+ *
83
+ * @param array $filters
84
+ * @return Social_Semaphore
85
+ */
86
+ public function increment(array $filters = array()) {
87
+ global $wpdb;
88
+
89
+ if (count($filters)) {
90
+ // Loop through all of the filters and increment the semaphore
91
+ foreach ($filters as $priority) {
92
+ for ($i = 0, $j = count($priority); $i < $j; ++$i) {
93
+ $this->increment();
94
+ }
95
+ }
96
+ }
97
+ else {
98
+ $wpdb->query("
99
+ UPDATE $wpdb->options
100
+ SET option_value = CAST(option_value AS UNSIGNED) + 1
101
+ WHERE option_name = 'updraftplus_semaphore_".$this->lock_name."'
102
+ ");
103
+ $updraftplus->log('Incremented the semaphore ('.$this->lock_name.') by 1.');
104
+ }
105
+
106
+ return $this;
107
+ }
108
+
109
+ /**
110
+ * Decrements the semaphore.
111
+ *
112
+ * @return void
113
+ */
114
+ public function decrement() {
115
+ global $wpdb, $updraftplus;
116
+
117
+ $wpdb->query("
118
+ UPDATE $wpdb->options
119
+ SET option_value = CAST(option_value AS UNSIGNED) - 1
120
+ WHERE option_name = 'updraftplus_semaphore_".$this->lock_name."'
121
+ AND CAST(option_value AS UNSIGNED) > 0
122
+ ");
123
+ $updraftplus->log('Decremented the semaphore ('.$this->lock_name.') by 1.');
124
+ }
125
+
126
+ /**
127
+ * Unlocks the process.
128
+ *
129
+ * @return bool
130
+ */
131
+ public function unlock() {
132
+ global $wpdb, $updraftplus;
133
+
134
+ // Decrement for the master process.
135
+ $this->decrement();
136
+
137
+ $result = $wpdb->query("
138
+ UPDATE $wpdb->options
139
+ SET option_name = 'updraftplus_unlocked_".$this->lock_name."'
140
+ WHERE option_name = 'updraftplus_locked_".$this->lock_name."'
141
+ ");
142
+
143
+ if ($result == '1') {
144
+ $updraftplus->log('Semaphore ('.$this->lock_name.') unlocked.');
145
+ return true;
146
+ }
147
+
148
+ $updraftplus->log('Semaphore ('.$this->lock_name.') still locked.');
149
+ return false;
150
+ }
151
+
152
+ /**
153
+ * Attempts to jiggle the stuck lock loose.
154
+ *
155
+ * @return bool
156
+ */
157
+ private function stuck_check() {
158
+ global $wpdb, $updraftplus;
159
+
160
+ // Check to see if we already broke the lock.
161
+ if ($this->lock_broke) {
162
+ return true;
163
+ }
164
+
165
+ $current_time = current_time('mysql', 1);
166
+ $affected = $wpdb->query($wpdb->prepare("
167
+ UPDATE $wpdb->options
168
+ SET option_value = %s
169
+ WHERE option_name = 'updraftplus_last_lock_time_".$this->lock_name."'
170
+ AND option_value <= DATE_SUB(%s, INTERVAL 3 MINUTE)
171
+ ", $current_time, $current_time));
172
+
173
+ if ($affected == '1') {
174
+ $updraftplus->log('Semaphore ('.$this->lock_name.') was stuck, set lock time to '.$current_time);
175
+
176
+ $this->lock_broke = true;
177
+ return true;
178
+ }
179
+
180
+ return false;
181
+ }
182
+
183
+ } // End UpdraftPlus_Semaphore
includes/jquery-ui-1.8.22.custom.css CHANGED
@@ -411,8 +411,8 @@ button.ui-button-icons-only { width: 3.7em; }
411
  input.ui-button { padding: .4em 1em; }
412
 
413
  /*button icon element(s) */
414
- .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
415
- .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
416
  .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
417
  .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
418
  .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
@@ -432,7 +432,7 @@ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra pad
432
  *
433
  * http://docs.jquery.com/UI/Dialog#theming
434
  */
435
- .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
436
  .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
437
  .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
438
  .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
411
  input.ui-button { padding: .4em 1em; }
412
 
413
  /*button icon element(s) */
414
+ .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: -1px; margin-top: -8px; }
415
+ .ui-button-icon-only .ui-icon { left: -1px; margin-left: -8px; }
416
  .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
417
  .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
418
  .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
432
  *
433
  * http://docs.jquery.com/UI/Dialog#theming
434
  */
435
+ .ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; z-index: 300003;}
436
  .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
437
  .ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
438
  .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
includes/updraft-admin-ui.js CHANGED
@@ -51,7 +51,7 @@ function updraft_activejobs_update(repeat) {
51
  jQuery('#updraft_activejobsrow').show();
52
  } else {
53
  if (!jQuery('#updraft_activejobsrow').is(':hidden')) {
54
- updraft_showlastbackup();
55
  jQuery('#updraft_activejobsrow').hide();
56
  }
57
  }
@@ -151,8 +151,8 @@ function updraft_check_same_times() {
151
  }
152
  }
153
 
154
- // Visit the site in the background every 3 minutes - ensures that backups can progress if you've got the UD settings page open
155
- setInterval(function() {jQuery.get(updraft_siteurl+'/wp-cron.php');}, 180000);
156
 
157
  function updraft_activejobs_delete(jobid) {
158
  jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'activejobs_delete', jobid: jobid, nonce: updraft_credentialtest_nonce }, function(response) {
@@ -220,7 +220,7 @@ function updraft_downloader(base, nonce, what, whicharea, set_contents, prettyda
220
  var itext = (set_contents[i] == 0) ? '' : ' ('+show_index+')';
221
  if (!jQuery('#'+stid).length) {
222
  var prdate = (prettydate) ? prettydate : nonce;
223
- jQuery(whicharea).append('<div style="clear:left; border: 1px solid; padding: 8px; margin-top: 4px; max-width:840px;" id="'+stid+'"><button onclick="jQuery(\'#'+stid+'\').fadeOut().remove();" type="button" style="float:right; margin-bottom: 8px;">X</button><strong>Download '+what+itext+' ('+prdate+')</strong>:<div class="raw">'+updraftlion.begunlooking+'</div><div class="file" id="'+stid+'_st"><div class="dlfileprogress" style="width: 0;"></div></div>');
224
  // <b><span class="dlname">??</span></b> (<span class="dlsofar">?? KB</span>/<span class="dlsize">??</span> KB)
225
  (function(base, nonce, what, i) {
226
  setTimeout(function(){updraft_downloader_status(base, nonce, what, i);}, 300);
@@ -232,6 +232,31 @@ function updraft_downloader(base, nonce, what, whicharea, set_contents, prettyda
232
  // We don't want the form to submit as that replaces the document
233
  return false;
234
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  function updraft_restorer_checkstage2(doalert) {
236
  // How many left?
237
  var stilldownloading = jQuery('#ud_downloadstatus2 .file').length;
@@ -280,11 +305,13 @@ function updraft_downloader_status(base, nonce, what, findex) {
280
  // Get the DOM id of the status div (add _st for the id of the file itself)
281
  var stid = base+nonce+'_'+what+'_'+findex;
282
  if (!jQuery('#'+stid).length) { return; }
283
- // console.log(stid+": "+jQuery('#'+stid).length);
284
  dlstatus_sdata.nonce=updraft_credentialtest_nonce;
285
  dlstatus_sdata.timestamp = nonce;
286
  dlstatus_sdata.type = what;
287
  dlstatus_sdata.findex = findex;
 
 
288
  jQuery.get(ajaxurl, dlstatus_sdata, function(response) {
289
  nexttimer = 1250;
290
  if (dlstatus_lastlog == response) { nexttimer = 3000; }
@@ -344,7 +371,7 @@ jQuery(document).ready(function($){
344
  updraft_check_same_times();
345
 
346
  var updraft_delete_modal_buttons = {};
347
- updraft_delete_modal_buttons[updraftlion.delete] = function() {
348
  jQuery('#updraft-delete-waitwarning').slideDown();
349
  timestamp = jQuery('#updraft_delete_timestamp').val();
350
  jQuery.post(ajaxurl, jQuery('#updraft_delete_form').serialize(), function(response) {
@@ -387,25 +414,26 @@ jQuery(document).ready(function($){
387
  //alert(jQuery(y).val());
388
  }
389
  });
390
- if (anyselected == 1) {
391
- if (updraft_restore_stage == 1) {
392
- jQuery('#updraft-restore-modal-stage1').slideUp('slow');
393
- jQuery('#updraft-restore-modal-stage2').show();
394
- updraft_restore_stage = 2;
395
- var pretty_date = jQuery('.updraft_restore_date').first().text();
396
- // Create the downloader active widgets
397
- for (var i=0; i<whichselected.length; i++) {
398
- updraft_downloader('udrestoredlstatus_', jQuery('#updraft_restore_timestamp').val(), whichselected[i][0], '#ud_downloadstatus2', whichselected[i][1], pretty_date);
399
- }
400
- // Make sure all are downloaded
401
- } else if (updraft_restore_stage == 2) {
402
- updraft_restorer_checkstage2(1);
403
- } else if (updraft_restore_stage == 3) {
404
- jQuery('#updraft_restore_form').submit();
405
- }
406
- } else {
407
- alert('You did not select any components to restore. Please select at least one, and then try again.');
408
  }
 
 
 
 
 
 
 
 
 
 
409
  };
410
  updraft_restore_modal_buttons[updraftlion.cancel] = function() { jQuery(this).dialog("close"); };
411
 
@@ -426,14 +454,7 @@ jQuery(document).ready(function($){
426
  jQuery('#updraft_backup_started').html(response);
427
  // Kick off some activity to get WP to get the scheduled task moving as soon as possible
428
  setTimeout(function() {jQuery.get(updraft_siteurl);}, 5100);
429
- // If the site has cron or loopbacks disabled, then there may be a backlog to clear... if the site does not have cron disabled, then these have no performance impact
430
- setTimeout(function() {jQuery.get(updraft_siteurl+'/wp-cron.php', function() {
431
- setTimeout(function() { jQuery.get(updraft_siteurl, function() {
432
- setTimeout(function() { jQuery.get(updraft_siteurl+'/wp-cron.php', function() {
433
- setTimeout(function() { jQuery.get(updraft_siteurl); }, 10000);
434
- }); }, 10000);
435
- });}, 10000);
436
- } );}, 13600);
437
  //setTimeout(function() {updraft_showlastlog();}, 6000);
438
  setTimeout(function() {updraft_activejobs_update();}, 6000);
439
  setTimeout(function() {
51
  jQuery('#updraft_activejobsrow').show();
52
  } else {
53
  if (!jQuery('#updraft_activejobsrow').is(':hidden')) {
54
+ if (typeof lastbackup_laststatus != 'undefined') { updraft_showlastbackup(); }
55
  jQuery('#updraft_activejobsrow').hide();
56
  }
57
  }
151
  }
152
  }
153
 
154
+ // Visit the site in the background every 3.5 minutes - ensures that backups can progress if you've got the UD settings page open
155
+ setInterval(function() {jQuery.get(updraft_siteurl+'/wp-cron.php');}, 210000);
156
 
157
  function updraft_activejobs_delete(jobid) {
158
  jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'activejobs_delete', jobid: jobid, nonce: updraft_credentialtest_nonce }, function(response) {
220
  var itext = (set_contents[i] == 0) ? '' : ' ('+show_index+')';
221
  if (!jQuery('#'+stid).length) {
222
  var prdate = (prettydate) ? prettydate : nonce;
223
+ jQuery(whicharea).append('<div style="clear:left; border: 1px solid; padding: 8px; margin-top: 4px; max-width:840px;" id="'+stid+'" class="updraftplus_downloader"><button onclick="jQuery(\'#'+stid+'\').fadeOut().remove();" type="button" style="float:right; margin-bottom: 8px;">X</button><strong>Download '+what+itext+' ('+prdate+')</strong>:<div class="raw">'+updraftlion.begunlooking+'</div><div class="file" id="'+stid+'_st"><div class="dlfileprogress" style="width: 0;"></div></div>');
224
  // <b><span class="dlname">??</span></b> (<span class="dlsofar">?? KB</span>/<span class="dlsize">??</span> KB)
225
  (function(base, nonce, what, i) {
226
  setTimeout(function(){updraft_downloader_status(base, nonce, what, i);}, 300);
232
  // We don't want the form to submit as that replaces the document
233
  return false;
234
  }
235
+
236
+ // Catch HTTP errors if the download status check returns them
237
+ jQuery(document).ajaxError(function( event, jqxhr, settings, exception ) {
238
+ if (exception == null || exception == '') return;
239
+ if (jxqhr.responseText == null || jxqhr.responseText == '') return;
240
+ console.log("Error caught by UpdraftPlus ajaxError handler (follows)");
241
+ console.log(exception);
242
+ if (settings.url.search(ajaxurl) == 0) {
243
+ if (settings.url.search('subaction=downloadstatus')) {
244
+ var timestamp = settings.url.match(/timestamp=\d+/);
245
+ var type = settings.url.match(/type=[a-z]+/);
246
+ var findex = settings.url.match(/findex=\d+/);
247
+ var base = settings.url.match(/base=[a-z_]+/);
248
+ findex = (findex instanceof Array) ? parseInt(findex[0].substr(7)) : 0;
249
+ type = (type instanceof Array) ? type[0].substr(5) : '';
250
+ base = (base instanceof Array) ? base[0].substr(5) : '';
251
+ timestamp = (timestamp instanceof Array) ? parseInt(timestamp[0].substr(10)) : 0;
252
+ if ('' != base && '' != type && timestamp >0) {
253
+ var stid = base+timestamp+'_'+type+'_'+findex;
254
+ jQuery('#'+stid+' .raw').html('<strong>'+updraftlion.error+'</strong> '+updraftlion.servererrorcode);
255
+ }
256
+ }
257
+ }
258
+ });
259
+
260
  function updraft_restorer_checkstage2(doalert) {
261
  // How many left?
262
  var stilldownloading = jQuery('#ud_downloadstatus2 .file').length;
305
  // Get the DOM id of the status div (add _st for the id of the file itself)
306
  var stid = base+nonce+'_'+what+'_'+findex;
307
  if (!jQuery('#'+stid).length) { return; }
308
+ //console.log(stid+": "+jQuery('#'+stid).length);
309
  dlstatus_sdata.nonce=updraft_credentialtest_nonce;
310
  dlstatus_sdata.timestamp = nonce;
311
  dlstatus_sdata.type = what;
312
  dlstatus_sdata.findex = findex;
313
+ // This goes in because we want to read it back on any ajaxError event
314
+ dlstatus_sdata.base = base;
315
  jQuery.get(ajaxurl, dlstatus_sdata, function(response) {
316
  nexttimer = 1250;
317
  if (dlstatus_lastlog == response) { nexttimer = 3000; }
371
  updraft_check_same_times();
372
 
373
  var updraft_delete_modal_buttons = {};
374
+ updraft_delete_modal_buttons[updraftlion.deletebutton] = function() {
375
  jQuery('#updraft-delete-waitwarning').slideDown();
376
  timestamp = jQuery('#updraft_delete_timestamp').val();
377
  jQuery.post(ajaxurl, jQuery('#updraft_delete_form').serialize(), function(response) {
414
  //alert(jQuery(y).val());
415
  }
416
  });
417
+ if (anyselected == 1) {
418
+ if (updraft_restore_stage == 1) {
419
+ jQuery('#updraft-restore-modal-stage1').slideUp('slow');
420
+ jQuery('#updraft-restore-modal-stage2').show();
421
+ updraft_restore_stage = 2;
422
+ var pretty_date = jQuery('.updraft_restore_date').first().text();
423
+ // Create the downloader active widgets
424
+ for (var i=0; i<whichselected.length; i++) {
425
+ updraft_downloader('udrestoredlstatus_', jQuery('#updraft_restore_timestamp').val(), whichselected[i][0], '#ud_downloadstatus2', whichselected[i][1], pretty_date);
 
 
 
 
 
 
 
 
 
426
  }
427
+ // Make sure all are downloaded
428
+ } else if (updraft_restore_stage == 2) {
429
+ updraft_restorer_checkstage2(1);
430
+ } else if (updraft_restore_stage == 3) {
431
+ jQuery('#updraft-restore-modal-stage2a').html(updraftlion.restoreproceeding);
432
+ jQuery('#updraft_restore_form').submit();
433
+ }
434
+ } else {
435
+ alert('You did not select any components to restore. Please select at least one, and then try again.');
436
+ }
437
  };
438
  updraft_restore_modal_buttons[updraftlion.cancel] = function() { jQuery(this).dialog("close"); };
439
 
454
  jQuery('#updraft_backup_started').html(response);
455
  // Kick off some activity to get WP to get the scheduled task moving as soon as possible
456
  setTimeout(function() {jQuery.get(updraft_siteurl);}, 5100);
457
+ setTimeout(function() {jQuery.get(updraft_siteurl+'/wp-cron.php');}, 13500);
 
 
 
 
 
 
 
458
  //setTimeout(function() {updraft_showlastlog();}, 6000);
459
  setTimeout(function() {updraft_activejobs_update();}, 6000);
460
  setTimeout(function() {
methods/dropbox.php CHANGED
@@ -32,7 +32,7 @@ class UpdraftPlus_BackupModule_dropbox {
32
 
33
  if (!function_exists('mcrypt_encrypt')) {
34
  $updraftplus->log('The mcrypt PHP module is not installed');
35
- $updraftplus->log(sprintf(__('The %s PHP module is not installed', 'updraftplus'), 'mcrypt'), 'error');
36
  return false;
37
  }
38
 
32
 
33
  if (!function_exists('mcrypt_encrypt')) {
34
  $updraftplus->log('The mcrypt PHP module is not installed');
35
+ $updraftplus->log(sprintf(__('The %s PHP module is not installed - ask your web hosting company to enable it', 'updraftplus'), 'mcrypt'), 'error');
36
  return false;
37
  }
38
 
methods/ftp.php CHANGED
@@ -28,15 +28,15 @@ class UpdraftPlus_BackupModule_ftp {
28
 
29
  global $updraftplus, $updraftplus_backup;
30
 
31
- $server = UpdraftPlus_Options::get_updraft_option('updraft_server_address');
32
- $user = UpdraftPlus_Options::get_updraft_option('updraft_ftp_login');
33
 
34
  $ftp = $this->getFTP(
35
  $server,
36
  $user,
37
- UpdraftPlus_Options::get_updraft_option('updraft_ftp_pass'), UpdraftPlus_Options::get_updraft_option('updraft_ssl_nossl'),
38
- UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify'),
39
- UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts')
40
  );
41
 
42
  if (!$ftp->connect()) {
@@ -49,7 +49,7 @@ class UpdraftPlus_BackupModule_ftp {
49
 
50
  $updraft_dir = $updraftplus->backups_dir_location().'/';
51
 
52
- $ftp_remote_path = trailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_ftp_remote_path'));
53
  foreach($backup_array as $file) {
54
  $fullpath = $updraft_dir.$file;
55
  $updraftplus->log("FTP upload attempt: $file -> ftp://$user@$server/${ftp_remote_path}${file}");
@@ -76,15 +76,15 @@ class UpdraftPlus_BackupModule_ftp {
76
  $ftp = $ftparr['ftp_object'];
77
  } else {
78
 
79
- $server = UpdraftPlus_Options::get_updraft_option('updraft_server_address');
80
- $user = UpdraftPlus_Options::get_updraft_option('updraft_ftp_login');
81
 
82
  $ftp = $this->getFTP(
83
  $server,
84
  $user,
85
- UpdraftPlus_Options::get_updraft_option('updraft_ftp_pass'), UpdraftPlus_Options::get_updraft_option('updraft_ssl_nossl'),
86
- UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify'),
87
- UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts')
88
  );
89
 
90
  if (!$ftp->connect()) {
@@ -94,7 +94,7 @@ class UpdraftPlus_BackupModule_ftp {
94
 
95
  }
96
 
97
- $ftp_remote_path = isset($ftparr['ftp_remote_path']) ? $ftparr['ftp_remote_path'] : trailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_ftp_remote_path'));
98
 
99
  $ret = true;
100
  foreach ($files as $file) {
@@ -115,11 +115,11 @@ class UpdraftPlus_BackupModule_ftp {
115
  global $updraftplus;
116
 
117
  $ftp = $this->getFTP(
118
- UpdraftPlus_Options::get_updraft_option('updraft_server_address'),
119
- UpdraftPlus_Options::get_updraft_option('updraft_ftp_login'),
120
- UpdraftPlus_Options::get_updraft_option('updraft_ftp_pass'), UpdraftPlus_Options::get_updraft_option('updraft_ssl_nossl'),
121
- UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify'),
122
- UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts')
123
  );
124
 
125
  if (!$ftp->connect()) {
@@ -130,7 +130,7 @@ class UpdraftPlus_BackupModule_ftp {
130
 
131
  //$ftp->make_dir(); we may need to recursively create dirs? TODO
132
 
133
- $ftp_remote_path = trailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_ftp_remote_path'));
134
  $fullpath = $updraftplus->backups_dir_location().'/'.$file;
135
 
136
  $resume = false;
@@ -169,6 +169,7 @@ class UpdraftPlus_BackupModule_ftp {
169
  }
170
 
171
  public static function config_print() {
 
172
  ?>
173
 
174
  <tr class="updraftplusmethod ftp">
@@ -183,19 +184,19 @@ class UpdraftPlus_BackupModule_ftp {
183
 
184
  <tr class="updraftplusmethod ftp">
185
  <th><?php _e('FTP Server','updraftplus');?>:</th>
186
- <td><input type="text" size="40" id="updraft_server_address" name="updraft_server_address" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_server_address')); ?>" /></td>
187
  </tr>
188
  <tr class="updraftplusmethod ftp">
189
  <th><?php _e('FTP Login','updraftplus');?>:</th>
190
- <td><input type="text" size="40" id="updraft_ftp_login" name="updraft_ftp_login" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_ftp_login')) ?>" /></td>
191
  </tr>
192
  <tr class="updraftplusmethod ftp">
193
  <th><?php _e('FTP Password','updraftplus');?>:</th>
194
- <td><input type="<?php echo apply_filters('updraftplus_admin_secret_field_type', 'text'); ?>" size="40" id="updraft_ftp_pass" name="updraft_ftp_pass" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_ftp_pass')); ?>" /></td>
195
  </tr>
196
  <tr class="updraftplusmethod ftp">
197
  <th><?php _e('Remote Path','updraftplus');?>:</th>
198
- <td><input type="text" size="64" id="updraft_ftp_remote_path" name="updraft_ftp_remote_path" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_ftp_remote_path')); ?>" /> <em><?php _e('Needs to already exist','updraftplus');?></em></td>
199
  </tr>
200
  <tr class="updraftplusmethod ftp">
201
  <th></th>
@@ -204,6 +205,10 @@ class UpdraftPlus_BackupModule_ftp {
204
  <?php
205
  }
206
 
 
 
 
 
207
  public static function credentials_test() {
208
 
209
  $server = $_POST['server'];
28
 
29
  global $updraftplus, $updraftplus_backup;
30
 
31
+ $server = $updraftplus->get_job_option('updraft_server_address');
32
+ $user = $updraftplus->get_job_option('updraft_ftp_login');
33
 
34
  $ftp = $this->getFTP(
35
  $server,
36
  $user,
37
+ $updraftplus->get_job_option('updraft_ftp_pass'), $updraftplus->get_job_option('updraft_ssl_nossl'),
38
+ $updraftplus->get_job_option('updraft_ssl_disableverify'),
39
+ $updraftplus->get_job_option('updraft_ssl_useservercerts')
40
  );
41
 
42
  if (!$ftp->connect()) {
49
 
50
  $updraft_dir = $updraftplus->backups_dir_location().'/';
51
 
52
+ $ftp_remote_path = trailingslashit($updraftplus->get_job_option('updraft_ftp_remote_path'));
53
  foreach($backup_array as $file) {
54
  $fullpath = $updraft_dir.$file;
55
  $updraftplus->log("FTP upload attempt: $file -> ftp://$user@$server/${ftp_remote_path}${file}");
76
  $ftp = $ftparr['ftp_object'];
77
  } else {
78
 
79
+ $server = $updraftplus->get_job_option('updraft_server_address');
80
+ $user = $updraftplus->get_job_option('updraft_ftp_login');
81
 
82
  $ftp = $this->getFTP(
83
  $server,
84
  $user,
85
+ $updraftplus->get_job_option('updraft_ftp_pass'), $updraftplus->get_job_option('updraft_ssl_nossl'),
86
+ $updraftplus->get_job_option('updraft_ssl_disableverify'),
87
+ $updraftplus->get_job_option('updraft_ssl_useservercerts')
88
  );
89
 
90
  if (!$ftp->connect()) {
94
 
95
  }
96
 
97
+ $ftp_remote_path = isset($ftparr['ftp_remote_path']) ? $ftparr['ftp_remote_path'] : trailingslashit($updraftplus->get_job_option('updraft_ftp_remote_path'));
98
 
99
  $ret = true;
100
  foreach ($files as $file) {
115
  global $updraftplus;
116
 
117
  $ftp = $this->getFTP(
118
+ $updraftplus->get_job_option('updraft_server_address'),
119
+ $updraftplus->get_job_option('updraft_ftp_login'),
120
+ $updraftplus->get_job_option('updraft_ftp_pass'), $updraftplus->get_job_option('updraft_ssl_nossl'),
121
+ $updraftplus->get_job_option('updraft_ssl_disableverify'),
122
+ $updraftplus->get_job_option('updraft_ssl_useservercerts')
123
  );
124
 
125
  if (!$ftp->connect()) {
130
 
131
  //$ftp->make_dir(); we may need to recursively create dirs? TODO
132
 
133
+ $ftp_remote_path = trailingslashit($updraftplus->get_job_option('updraft_ftp_remote_path'));
134
  $fullpath = $updraftplus->backups_dir_location().'/'.$file;
135
 
136
  $resume = false;
169
  }
170
 
171
  public static function config_print() {
172
+ global $updraftplus;
173
  ?>
174
 
175
  <tr class="updraftplusmethod ftp">
184
 
185
  <tr class="updraftplusmethod ftp">
186
  <th><?php _e('FTP Server','updraftplus');?>:</th>
187
+ <td><input type="text" size="40" id="updraft_server_address" name="updraft_server_address" value="<?php echo htmlspecialchars($updraftplus->get_job_option('updraft_server_address')); ?>" /></td>
188
  </tr>
189
  <tr class="updraftplusmethod ftp">
190
  <th><?php _e('FTP Login','updraftplus');?>:</th>
191
+ <td><input type="text" size="40" id="updraft_ftp_login" name="updraft_ftp_login" value="<?php echo htmlspecialchars($updraftplus->get_job_option('updraft_ftp_login')) ?>" /></td>
192
  </tr>
193
  <tr class="updraftplusmethod ftp">
194
  <th><?php _e('FTP Password','updraftplus');?>:</th>
195
+ <td><input type="<?php echo apply_filters('updraftplus_admin_secret_field_type', 'text'); ?>" size="40" id="updraft_ftp_pass" name="updraft_ftp_pass" value="<?php echo htmlspecialchars($updraftplus->get_job_option('updraft_ftp_pass')); ?>" /></td>
196
  </tr>
197
  <tr class="updraftplusmethod ftp">
198
  <th><?php _e('Remote Path','updraftplus');?>:</th>
199
+ <td><input type="text" size="64" id="updraft_ftp_remote_path" name="updraft_ftp_remote_path" value="<?php echo htmlspecialchars($updraftplus->get_job_option('updraft_ftp_remote_path')); ?>" /> <em><?php _e('Needs to already exist','updraftplus');?></em></td>
200
  </tr>
201
  <tr class="updraftplusmethod ftp">
202
  <th></th>
205
  <?php
206
  }
207
 
208
+ public function get_credentials() {
209
+ return array('updraft_server_address', 'updraft_ftp_login', 'updraft_ftp_pass', 'updraft_ftp_remote_path', 'updraft_ssl_disableverify', 'updraft_ssl_nossl', 'updraft_ssl_useservercerts');
210
+ }
211
+
212
  public static function credentials_test() {
213
 
214
  $server = $_POST['server'];
options.php CHANGED
@@ -79,6 +79,7 @@ class UpdraftPlus_Options {
79
  register_setting('updraft-options-group', 'updraft_ftp_login' );
80
  register_setting('updraft-options-group', 'updraft_ftp_pass' );
81
  register_setting('updraft-options-group', 'updraft_ftp_remote_path' );
 
82
  register_setting('updraft-options-group', 'updraft_server_address' );
83
  register_setting('updraft-options-group', 'updraft_dir', array($updraftplus_admin, 'prune_updraft_dir_prefix') );
84
  register_setting('updraft-options-group', 'updraft_email');
79
  register_setting('updraft-options-group', 'updraft_ftp_login' );
80
  register_setting('updraft-options-group', 'updraft_ftp_pass' );
81
  register_setting('updraft-options-group', 'updraft_ftp_remote_path' );
82
+
83
  register_setting('updraft-options-group', 'updraft_server_address' );
84
  register_setting('updraft-options-group', 'updraft_dir', array($updraftplus_admin, 'prune_updraft_dir_prefix') );
85
  register_setting('updraft-options-group', 'updraft_email');
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === UpdraftPlus - WordPress Backup and Restoration ===
2
- Contributors: DavidAnderson
3
- Tags: backup, backups, restore, database, rackspace, amazon, s3, amazon s3, s3 compatible, dropbox, google drive, rackspace cloud files, rackspace, cloud files, dreamhost, dreamobjects, ftp, webdav, google cloud storage, cloudian, cloudn, connectria, constant cloud, eucalyptus, nifty, nimbula, back up, multisite, restoration, sftp, ftps, scp, migrate, duplicate, copy, updraft, schedule, database backup
4
  Requires at least: 3.2
5
  Tested up to: 3.6.1
6
- Stable tag: 1.7.18
7
  Author URI: http://updraftplus.com
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
@@ -14,13 +14,16 @@ Easy and complete backups + restoration. Manual or automated backups (Amazon S3,
14
 
15
  <a href="http://updraftplus.com">UpdraftPlus</a> simplifies backups (and restoration). Backup into the cloud (Amazon S3 (or compatible), Dropbox, Google Drive, Rackspace Cloud, DreamObjects, FTP, SFTP, SCP, WebDAV and email) and restore with a single click. Backups of files and database can have separate schedules.
16
 
17
- * Thousands of users: widely tested and reliable (over 270,000 downloads). Ranks in the top 0.5% on rankwp.com (70th out of 25,000 plugins).
18
- * Top-quality: ranks 52nd out of 25,000 WordPress plugins for quality on rankwp.com (top 0.25% - last checked 20th August 2013).
 
 
 
19
  * Supports WordPress backups to Amazon S3 (or compatible), Dropbox, Rackspace Cloud Files, Google Drive, Google Cloud Storage, DreamHost DreamObjects, FTP and email. Also (via an add-on) FTP over SSL, SFTP, SCP and WebDAV. (Note: Microsoft forbid SkyDrive to be used by backup software). Some examples of S3-compatible providers: Cloudian, Connectria, Constant, Eucalyptus, Nifty, Nimbula, Cloudn.
20
  * Quick restore (both file and database backups)
21
  * Backup automatically on a repeating schedule
22
  * Site duplicator/migrator: can copy sites, and (with add-on) move them to new locations
23
- * Files and databases can have separate schedules
24
  * Failed uploads are automatically resumed/retried
25
  * Large sites can be split into multiple archives
26
  * Select which files to backup (plugins, themes, content, other)
@@ -72,6 +75,7 @@ We hang out in the WordPress support forum for this plugin - http://wordpress.or
72
 
73
  <a href="http://updraftplus.com/download/">Please go here for full instructions for installing this plugin.</a>
74
 
 
75
  == Frequently Asked Questions ==
76
 
77
  <a href="http://updraftplus.com/support/frequently-asked-questions/"><strong>Please go here for the full FAQs - there are many more than below.</strong></a> Below are just a handful which particularly apply to the free wordpress.org version, or which bear repeating.
@@ -126,6 +130,10 @@ Thanks for asking - yes, I have. Check out my profile page - http://profiles.wor
126
 
127
  == Changelog ==
128
 
 
 
 
 
129
  = 1.7.18 - 2013/09/17 =
130
  * FEATURE: <a href="http://updraftplus.com/shop/morestorage/">New "more storage" add-on</a>, enabling backing up to multiple storage destinations
131
  * FEATURE: New progress meter on dashboard page when a backup is running
1
  === UpdraftPlus - WordPress Backup and Restoration ===
2
+ Contributors: Backup with UpdraftPlus, DavidAnderson
3
+ Tags: backup, backups, restore, database, rackspace, amazon, s3, amazon s3, s3 compatible, dropbox, google drive, rackspace cloud files, rackspace, cloud files, dreamhost, dreamobjects, ftp, webdav, google cloud storage, cloudian, cloudn, connectria, constant cloud, eucalyptus, nifty, nimbula, back up, multisite, restoration, sftp, ftps, scp, migrate, duplicate, copy, updraft, schedule, database backup, wordpress backup, full backup
4
  Requires at least: 3.2
5
  Tested up to: 3.6.1
6
+ Stable tag: 1.7.20
7
  Author URI: http://updraftplus.com
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
14
 
15
  <a href="http://updraftplus.com">UpdraftPlus</a> simplifies backups (and restoration). Backup into the cloud (Amazon S3 (or compatible), Dropbox, Google Drive, Rackspace Cloud, DreamObjects, FTP, SFTP, SCP, WebDAV and email) and restore with a single click. Backups of files and database can have separate schedules.
16
 
17
+ <strong>Top-quality:</strong> UpdraftPlus is the highest-ranking backup plugin on rankwp.com (ranks 16th out of 25,000 WordPress plugins for quality on rankwp.com - last checked 28th September 2013).
18
+
19
+ <strong>Tens of thousands of users:</strong> widely tested and reliable (over 300,000 downloads). Ranks in the top 50 most popular of all WordPress plugins on rankwp.com. Millions of backups completed!
20
+
21
+
22
  * Supports WordPress backups to Amazon S3 (or compatible), Dropbox, Rackspace Cloud Files, Google Drive, Google Cloud Storage, DreamHost DreamObjects, FTP and email. Also (via an add-on) FTP over SSL, SFTP, SCP and WebDAV. (Note: Microsoft forbid SkyDrive to be used by backup software). Some examples of S3-compatible providers: Cloudian, Connectria, Constant, Eucalyptus, Nifty, Nimbula, Cloudn.
23
  * Quick restore (both file and database backups)
24
  * Backup automatically on a repeating schedule
25
  * Site duplicator/migrator: can copy sites, and (with add-on) move them to new locations
26
+ * Files and database backups can have separate schedules
27
  * Failed uploads are automatically resumed/retried
28
  * Large sites can be split into multiple archives
29
  * Select which files to backup (plugins, themes, content, other)
75
 
76
  <a href="http://updraftplus.com/download/">Please go here for full instructions for installing this plugin.</a>
77
 
78
+
79
  == Frequently Asked Questions ==
80
 
81
  <a href="http://updraftplus.com/support/frequently-asked-questions/"><strong>Please go here for the full FAQs - there are many more than below.</strong></a> Below are just a handful which particularly apply to the free wordpress.org version, or which bear repeating.
130
 
131
  == Changelog ==
132
 
133
+ = 1.7.20 - 2013/09/20 =
134
+ * TWEAK: Add semaphore locking to prevent WP's cron system kicking off multiple jobs on overloaded systems
135
+ * TWEAK: Catch and display some previously uncaught AJAX notices when restoring, and display information on the restore process earlier
136
+
137
  = 1.7.18 - 2013/09/17 =
138
  * FEATURE: <a href="http://updraftplus.com/shop/morestorage/">New "more storage" add-on</a>, enabling backing up to multiple storage destinations
139
  * FEATURE: New progress meter on dashboard page when a backup is running
restorer.php CHANGED
@@ -666,7 +666,7 @@ class Updraft_Restorer extends WP_Upgrader {
666
 
667
  $this->last_error = '';
668
  $random_table_name = 'updraft_tmp_'.rand(0,9999999).md5(microtime(true));
669
- if ($use_wpdb) {
670
  $req = $wpdb->query("CREATE TABLE $random_table_name");
671
  if (!$req) $this->last_error = $wpdb->last_error;
672
  $this->last_error_no = false;
@@ -788,6 +788,7 @@ class Updraft_Restorer extends WP_Upgrader {
788
  $old_table_prefix = $tmatches[1].'_';
789
  echo '<strong>'.__('Old table prefix:', 'updraftplus').'</strong> '.htmlspecialchars($old_table_prefix).'<br>';
790
  }
 
791
  if ('' != $old_table_prefix && $import_table_prefix != $old_table_prefix) {
792
  $sql_line = $updraftplus->str_replace_once($old_table_prefix, $import_table_prefix, $sql_line);
793
  }
@@ -891,14 +892,16 @@ class Updraft_Restorer extends WP_Upgrader {
891
  // echo "Memory usage (Mb): ".round(memory_get_usage(false)/1048576, 1)." : ".round(memory_get_usage(true)/1048576, 1)."<br>";
892
 
893
  global $wpdb, $updraftplus;
 
894
 
895
  if ($sql_type == 2 && $this->create_forbidden) {
896
- echo sprintf(__('Cannot create new tables, so skipping this command (%s)', 'updraftplus'), htmlspecialchars("CREATE TABLE ".$this->table_name))."<br>";
897
  $req = true;
898
  } else {
899
  if ($sql_type == 1 && $this->drop_forbidden) {
900
- $sql_line = "DELETE FROM ".$updraftplus->backquote($this->table_name);
901
  echo sprintf(__('Cannot drop tables, so deleting instead (%s)', 'updraftplus'), $sql_line)."<br>";
 
902
  }
903
  // echo substr($sql_line, 0, 50)." (".strlen($sql_line).")<br>";
904
  if ($this->use_wpdb) {
@@ -912,7 +915,7 @@ class Updraft_Restorer extends WP_Upgrader {
912
  }
913
 
914
  if (!$req) {
915
- $this->errors++;
916
  echo sprintf(_x('An error (%s) occured:', 'The user is being told the number of times an error has happened, e.g. An error (27) occurred', 'updraftplus'), $this->errors)." - ".htmlspecialchars($this->last_error)." - ".__('the database query being run was:','updraftplus').' '.htmlspecialchars($sql_line).'<br>';
917
  // First command is expected to be DROP TABLE
918
  if (1 == $this->errors && 2 == $sql_type && 0 == $this->tables_created) {
@@ -1045,4 +1048,4 @@ class UpdraftPlus_WPDB extends wpdb {
1045
  return $this->dbh;
1046
  }
1047
  }
1048
- ?>
666
 
667
  $this->last_error = '';
668
  $random_table_name = 'updraft_tmp_'.rand(0,9999999).md5(microtime(true));
669
+ if ($this->use_wpdb) {
670
  $req = $wpdb->query("CREATE TABLE $random_table_name");
671
  if (!$req) $this->last_error = $wpdb->last_error;
672
  $this->last_error_no = false;
788
  $old_table_prefix = $tmatches[1].'_';
789
  echo '<strong>'.__('Old table prefix:', 'updraftplus').'</strong> '.htmlspecialchars($old_table_prefix).'<br>';
790
  }
791
+ $this->new_table_name = ($old_table_prefix) ? $updraftplus->str_replace_once($old_table_prefix, $import_table_prefix, $this->table_name) : $this->table_name;
792
  if ('' != $old_table_prefix && $import_table_prefix != $old_table_prefix) {
793
  $sql_line = $updraftplus->str_replace_once($old_table_prefix, $import_table_prefix, $sql_line);
794
  }
892
  // echo "Memory usage (Mb): ".round(memory_get_usage(false)/1048576, 1)." : ".round(memory_get_usage(true)/1048576, 1)."<br>";
893
 
894
  global $wpdb, $updraftplus;
895
+ $ignore_errors = false;
896
 
897
  if ($sql_type == 2 && $this->create_forbidden) {
898
+ echo sprintf(__('Cannot create new tables, so skipping this command (%s)', 'updraftplus'), htmlspecialchars($sql_line))."<br>";
899
  $req = true;
900
  } else {
901
  if ($sql_type == 1 && $this->drop_forbidden) {
902
+ $sql_line = "DELETE FROM ".$updraftplus->backquote($this->new_table_name);
903
  echo sprintf(__('Cannot drop tables, so deleting instead (%s)', 'updraftplus'), $sql_line)."<br>";
904
+ $ignore_errors = true;
905
  }
906
  // echo substr($sql_line, 0, 50)." (".strlen($sql_line).")<br>";
907
  if ($this->use_wpdb) {
915
  }
916
 
917
  if (!$req) {
918
+ if (!$ignore_errors) $this->errors++;
919
  echo sprintf(_x('An error (%s) occured:', 'The user is being told the number of times an error has happened, e.g. An error (27) occurred', 'updraftplus'), $this->errors)." - ".htmlspecialchars($this->last_error)." - ".__('the database query being run was:','updraftplus').' '.htmlspecialchars($sql_line).'<br>';
920
  // First command is expected to be DROP TABLE
921
  if (1 == $this->errors && 2 == $sql_type && 0 == $this->tables_created) {
1048
  return $this->dbh;
1049
  }
1050
  }
1051
+ ?>
updraftplus.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: UpdraftPlus - Backup/Restore
4
  Plugin URI: http://updraftplus.com
5
  Description: Backup and restore: take backups locally, or backup to Amazon S3, Dropbox, Google Drive, Rackspace, (S)FTP, WebDAV & email, on automatic schedules.
6
  Author: UpdraftPlus.Com, DavidAnderson
7
- Version: 1.7.18
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
10
  Text Domain: updraftplus
@@ -15,13 +15,16 @@ Author URI: http://updraftplus.com
15
  TODO - some of these are out of date/done, needs pruning
16
  // Raise a warning for probably-too-large email attachments (make intelligent - i.e. record what's the largest succesfully despatched so far? Or is that not relevant, since that only tells us about the first link?)
17
  // After Oct 15 2013: Remove page(s) from websites discussing W3TC
 
 
 
 
18
  // Exempt UD itself from a plugins restore? (will options be out-of-sync? exempt options too?)
19
  // Post restore/migrate, check updraft_dir, and reset if non-existent
20
  // Auto-empty caches post-restore/post-migration (prevent support requests from people with state/wrong cacheing data)
21
  // Show 'Migrate' instead of 'Restore' on the button if relevant
22
  // Test with: http://wordpress.org/plugins/wp-db-driver/
23
  // Backup notes
24
- // Detect scheduler not running. Could detect possible causes? (e.g. parse .htaccess)
25
  // The delete-em at the end needs to be made resumable
26
  // Show running jobs at top. If there are some, and are overdue, kick off a few visits to wp-cron.php to help along.
27
  // Incremental - can leverage some of the multi-zip work???
@@ -383,7 +386,7 @@ class UpdraftPlus {
383
  # Clean out old job data
384
  if ($older_than >10000) {
385
  global $wpdb;
386
- $all_jobs = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE 'updraft_jobdata_%' LIMIT 1", ARRAY_A);
387
  foreach ($all_jobs as $job) {
388
  $val = maybe_unserialize($job['option_value']);
389
  if (!empty($val['backup_time_ms']) && time() > $val['backup_time_ms'] + 86400) {
@@ -470,7 +473,7 @@ class UpdraftPlus {
470
 
471
  $memory_usage = round(@memory_get_usage(false)/1048576, 1);
472
  $memory_usage2 = round(@memory_get_usage(true)/1048576, 1);
473
- $logline = "UpdraftPlus: ".$this->version." WP: ".$wp_version." PHP: ".phpversion()." (".php_uname().") MySQL: $mysql_version Server: ".$_SERVER["SERVER_SOFTWARE"]." safe_mode: $safe_mode max_execution_time: ".@ini_get("max_execution_time")." memory_limit: ".ini_get('memory_limit')." (used: ${memory_usage}M | ${memory_usage2}M) ZipArchive::addFile: ";
474
 
475
  // method_exists causes some faulty PHP installations to segfault, leading to support requests
476
  if (version_compare(phpversion(), '5.2.0', '>=') && extension_loaded('zip')) {
@@ -492,9 +495,6 @@ class UpdraftPlus {
492
 
493
  $this->log($logline);
494
 
495
- if ('Y' === $w3oc) $this->log(__('W3 Total Cache\'s object cache is active. This is known to have a bug that messes with all scheduled tasks (including backup jobs).','updraftplus').' '.__('You should go to the W3 Total Cache settings page and turn it off.', 'updraftplus'), 'warning');
496
-
497
-
498
  $disk_free_space = @disk_free_space($updraft_dir);
499
  if ($disk_free_space === false) {
500
  $this->log("Free space on disk containing Updraft's temporary directory: Unknown");
@@ -804,9 +804,9 @@ class UpdraftPlus {
804
  }
805
 
806
  # This is just a long-winded way of forcing WP to get the value afresh from the db, instead of using the auto-loaded/cached value (which can be out of date, especially since backups are, by their nature, long-running)
807
- public function filter_pre_option_cron($v) {
808
  global $wpdb;
809
- $row = $wpdb->get_row( $wpdb->prepare("SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", 'cron' ) );
810
  if (is_object($row )) return maybe_unserialize($row->option_value);
811
  return false;
812
  }
@@ -824,7 +824,7 @@ class UpdraftPlus {
824
  $runs_started = array();
825
  $time_now = microtime(true);
826
 
827
- add_filter('pre_option_cron', array($this, 'filter_pre_option_cron'));
828
 
829
  // Restore state
830
  $resumption_extralog = '';
@@ -1023,6 +1023,8 @@ class UpdraftPlus {
1023
  }
1024
  }
1025
 
 
 
1026
  if (count($undone_files) == 0) {
1027
  $this->log("Resume backup ($bnonce, $resumption_no): finish run");
1028
  $this->log("There were no more files that needed uploading; backup job is complete");
@@ -1107,6 +1109,15 @@ class UpdraftPlus {
1107
  update_site_option("updraft_jobdata_".$this->nonce, $this->jobdata);
1108
  }
1109
 
 
 
 
 
 
 
 
 
 
1110
  public function jobdata_get($key, $default = null) {
1111
  if (!is_array($this->jobdata)) {
1112
  $this->jobdata = get_site_option("updraft_jobdata_".$this->nonce, array());
@@ -1150,8 +1161,42 @@ class UpdraftPlus {
1150
  $this->log("Processed schedules. Tasks now: Backup files: $backup_files Backup DB: $backup_database");
1151
  }
1152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1153
  if (!is_string($service) && !is_array($service)) $service = UpdraftPlus_Options::get_updraft_option('updraft_service');
1154
  $service = $this->just_one($service);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1155
 
1156
  # If nothing to be done, then just finish
1157
  if (!$backup_files && !$backup_database) {
@@ -1159,6 +1204,15 @@ class UpdraftPlus {
1159
  return;
1160
  }
1161
 
 
 
 
 
 
 
 
 
 
1162
  // Allow the resume interval to be more than 300 if last time we know we went beyond that - but never more than 600
1163
  $resume_interval = (int)min(max(300, get_transient('updraft_initial_resume_interval')), 600);
1164
  # We delete it because we only want to know about behaviour found during the very last backup run (so, if you move servers then old data is not retained)
@@ -1187,6 +1241,7 @@ class UpdraftPlus {
1187
  'split_every', max(intval(UpdraftPlus_Options::get_updraft_option('updraft_split_every', 800)), UPDRAFTPLUS_SPLIT_MIN),
1188
  'maxzipbatch', 26214400, #25Mb
1189
  'job_file_entities', $job_file_entities,
 
1190
  'one_shot', $one_shot
1191
  );
1192
 
@@ -1243,12 +1298,12 @@ class UpdraftPlus {
1243
  $final_message = __('The backup apparently succeeded and is now complete','updraftplus');
1244
  # Ensure it is logged in English. Not hugely important; but helps with a tiny number of really broken setups in which the options cacheing is broken
1245
  if ('The backup apparently succeeded and is now complete' != $final_message) {
1246
- $updraftplus->log('The backup apparently succeeded and is now complete');
1247
  }
1248
  } else {
1249
  $final_message = __('The backup apparently succeeded (with warnings) and is now complete','updraftplus');
1250
  if ('The backup apparently succeeded (with warnings) and is now complete' != $final_message) {
1251
- $updraftplus->log('The backup apparently succeeded (with warnings) and is now complete');
1252
  }
1253
  }
1254
  } elseif ($this->newresumption_scheduled == false) {
4
  Plugin URI: http://updraftplus.com
5
  Description: Backup and restore: take backups locally, or backup to Amazon S3, Dropbox, Google Drive, Rackspace, (S)FTP, WebDAV & email, on automatic schedules.
6
  Author: UpdraftPlus.Com, DavidAnderson
7
+ Version: 1.7.20
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
10
  Text Domain: updraftplus
15
  TODO - some of these are out of date/done, needs pruning
16
  // Raise a warning for probably-too-large email attachments (make intelligent - i.e. record what's the largest succesfully despatched so far? Or is that not relevant, since that only tells us about the first link?)
17
  // After Oct 15 2013: Remove page(s) from websites discussing W3TC
18
+ // Change migrate window: 1) Retain link to article 2) Have selector to choose which backup set to migrate - or a fresh one 3) Have option for FTP/SFTP/SCP despatch 4) Have big "Go" button. Have some indication of what happens next. Test the login first. Have the remote site auto-scan its directory + pick up new sets. Have a way of querying the remote site for its UD-dir. Have a way of saving the settings as a 'profile'. Or just save the last set of settings (since mostly will be just one place to send to). Implement an HTTP/JSON method for sending files too.
19
+ // ancient .table.gz files need to be purged by the temp reaper
20
+ // Backup Now should have an option for files-only/database-only
21
+ // Prettify shop page: http://wordpress.org/plugins/pricing-table-extended/
22
  // Exempt UD itself from a plugins restore? (will options be out-of-sync? exempt options too?)
23
  // Post restore/migrate, check updraft_dir, and reset if non-existent
24
  // Auto-empty caches post-restore/post-migration (prevent support requests from people with state/wrong cacheing data)
25
  // Show 'Migrate' instead of 'Restore' on the button if relevant
26
  // Test with: http://wordpress.org/plugins/wp-db-driver/
27
  // Backup notes
 
28
  // The delete-em at the end needs to be made resumable
29
  // Show running jobs at top. If there are some, and are overdue, kick off a few visits to wp-cron.php to help along.
30
  // Incremental - can leverage some of the multi-zip work???
386
  # Clean out old job data
387
  if ($older_than >10000) {
388
  global $wpdb;
389
+ $all_jobs = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE 'updraft_jobdata_%'", ARRAY_A);
390
  foreach ($all_jobs as $job) {
391
  $val = maybe_unserialize($job['option_value']);
392
  if (!empty($val['backup_time_ms']) && time() > $val['backup_time_ms'] + 86400) {
473
 
474
  $memory_usage = round(@memory_get_usage(false)/1048576, 1);
475
  $memory_usage2 = round(@memory_get_usage(true)/1048576, 1);
476
+ $logline = "UpdraftPlus WordPress backup plugin (http://updraftplus.com): ".$this->version." WP: ".$wp_version." PHP: ".phpversion()." (".php_uname().") MySQL: $mysql_version Server: ".$_SERVER["SERVER_SOFTWARE"]." safe_mode: $safe_mode max_execution_time: ".@ini_get("max_execution_time")." memory_limit: ".ini_get('memory_limit')." (used: ${memory_usage}M | ${memory_usage2}M) ZipArchive::addFile: ";
477
 
478
  // method_exists causes some faulty PHP installations to segfault, leading to support requests
479
  if (version_compare(phpversion(), '5.2.0', '>=') && extension_loaded('zip')) {
495
 
496
  $this->log($logline);
497
 
 
 
 
498
  $disk_free_space = @disk_free_space($updraft_dir);
499
  if ($disk_free_space === false) {
500
  $this->log("Free space on disk containing Updraft's temporary directory: Unknown");
804
  }
805
 
806
  # This is just a long-winded way of forcing WP to get the value afresh from the db, instead of using the auto-loaded/cached value (which can be out of date, especially since backups are, by their nature, long-running)
807
+ public function filter_updraft_backup_history($v) {
808
  global $wpdb;
809
+ $row = $wpdb->get_row( $wpdb->prepare("SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", 'updraft_backup_history' ) );
810
  if (is_object($row )) return maybe_unserialize($row->option_value);
811
  return false;
812
  }
824
  $runs_started = array();
825
  $time_now = microtime(true);
826
 
827
+ add_filter('pre_option_updraft_backup_history', array($this, 'filter_updraft_backup_history'));
828
 
829
  // Restore state
830
  $resumption_extralog = '';
1023
  }
1024
  }
1025
 
1026
+ if (!empty($this->semaphore)) $this->semaphore->unlock();
1027
+
1028
  if (count($undone_files) == 0) {
1029
  $this->log("Resume backup ($bnonce, $resumption_no): finish run");
1030
  $this->log("There were no more files that needed uploading; backup job is complete");
1109
  update_site_option("updraft_jobdata_".$this->nonce, $this->jobdata);
1110
  }
1111
 
1112
+ public function get_job_option($opt) {
1113
+ // These are meant to be read-only
1114
+ if (!is_array($this->jobdata['option_cache'])) {
1115
+ if (!is_array($this->jobdata)) $this->jobdata = get_site_option("updraft_jobdata_".$this->nonce, array());
1116
+ $this->jobdata['option_cache'] = array();
1117
+ }
1118
+ return (isset($this->jobdata['option_cache'][$opt])) ? $this->jobdata['option_cache'][$opt] : UpdraftPlus_Options::get_updraft_option($opt);
1119
+ }
1120
+
1121
  public function jobdata_get($key, $default = null) {
1122
  if (!is_array($this->jobdata)) {
1123
  $this->jobdata = get_site_option("updraft_jobdata_".$this->nonce, array());
1161
  $this->log("Processed schedules. Tasks now: Backup files: $backup_files Backup DB: $backup_database");
1162
  }
1163
 
1164
+ $semaphore = (($backup_files) ? 'f' : '') . (($backup_database) ? 'd' : '');
1165
+
1166
+ // Make sure the options for semaphores exist
1167
+ global $wpdb;
1168
+ $results = $wpdb->get_results("
1169
+ SELECT option_id
1170
+ FROM $wpdb->options
1171
+ WHERE option_name IN ('updraftplus_locked_$semaphore', 'updraftplus_unlocked_$semaphore')
1172
+ ");
1173
+ // Use of update_option() is correct here - since it is what is used in class-semaphore.php
1174
+ if (!count($results)) {
1175
+ update_option('updraftplus_unlocked_'.$semaphore, '1');
1176
+ update_option('updraftplus_last_lock_time_'.$semaphore, current_time('mysql', 1));
1177
+ update_option('updraftplus_semaphore_'.$semaphore, '0');
1178
+ }
1179
+
1180
  if (!is_string($service) && !is_array($service)) $service = UpdraftPlus_Options::get_updraft_option('updraft_service');
1181
  $service = $this->just_one($service);
1182
+ if (is_string($service)) $service = array($service);
1183
+
1184
+ $option_cache = array();
1185
+ foreach ($service as $serv) {
1186
+ if ('' == $serv || 'none' == $serv) continue;
1187
+ include_once(UPDRAFTPLUS_DIR.'/methods/'.$serv.'.php');
1188
+ $cclass = 'UpdraftPlus_BackupModule_'.$serv;
1189
+ $obj = new $cclass;
1190
+ if (method_exists($cclass, 'get_credentials')) {
1191
+ $opts = $obj->get_credentials();
1192
+ if (is_array($opts)) {
1193
+ foreach ($opts as $opt) {
1194
+ $option_cache[$opt] = UpdraftPlus_Options::get_updraft_option($opt);
1195
+ }
1196
+ }
1197
+ }
1198
+ }
1199
+ $option_cache = apply_filters('updraftplus_job_option_cache', $option_cache);
1200
 
1201
  # If nothing to be done, then just finish
1202
  if (!$backup_files && !$backup_database) {
1204
  return;
1205
  }
1206
 
1207
+ require_once(UPDRAFTPLUS_DIR.'/includes/class-semaphore.php');
1208
+ $this->semaphore = UpdraftPlus_Semaphore::factory();
1209
+ $this->semaphore->lock_name = $semaphore;
1210
+ $this->log('Requesting semaphore lock ('.$semaphore.')');
1211
+ if (!$this->semaphore->lock()) {
1212
+ $this->log('Failed to gain semaphore lock ('.$semaphore.') - another backup is apparently already active - aborting (backups of the same time must be started at least 1 minute apart; otherwise they are assumed to be unwanted duplicates)');
1213
+ return;
1214
+ }
1215
+
1216
  // Allow the resume interval to be more than 300 if last time we know we went beyond that - but never more than 600
1217
  $resume_interval = (int)min(max(300, get_transient('updraft_initial_resume_interval')), 600);
1218
  # We delete it because we only want to know about behaviour found during the very last backup run (so, if you move servers then old data is not retained)
1241
  'split_every', max(intval(UpdraftPlus_Options::get_updraft_option('updraft_split_every', 800)), UPDRAFTPLUS_SPLIT_MIN),
1242
  'maxzipbatch', 26214400, #25Mb
1243
  'job_file_entities', $job_file_entities,
1244
+ 'option_cache', $option_cache,
1245
  'one_shot', $one_shot
1246
  );
1247
 
1298
  $final_message = __('The backup apparently succeeded and is now complete','updraftplus');
1299
  # Ensure it is logged in English. Not hugely important; but helps with a tiny number of really broken setups in which the options cacheing is broken
1300
  if ('The backup apparently succeeded and is now complete' != $final_message) {
1301
+ $this->log('The backup apparently succeeded and is now complete');
1302
  }
1303
  } else {
1304
  $final_message = __('The backup apparently succeeded (with warnings) and is now complete','updraftplus');
1305
  if ('The backup apparently succeeded (with warnings) and is now complete' != $final_message) {
1306
+ $this->log('The backup apparently succeeded (with warnings) and is now complete');
1307
  }
1308
  }
1309
  } elseif ($this->newresumption_scheduled == false) {