PluginProbe
UpdraftPlus: WP Backup & Migration Plugin / 1.12.4
UpdraftPlus: WP Backup & Migration Plugin v1.12.4
1.26.7 1.26.6 1.26.5 1.26.4 1.26.3 1.9.19 1.9.25 1.9.26 1.9.30 1.9.31 1.9.32 1.9.4 1.9.40 1.9.41 1.9.42 1.9.43 1.9.44 1.9.45 1.9.46 1.9.5 1.9.50 1.9.51 1.9.60 1.9.62 1.9.63 All 371 releases
updraftplus / admin.php

admin.php in UpdraftPlus: WP Backup & Migration Plugin 1.12.4, at admin.php

5,235 lines 249.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined ('UPDRAFTPLUS_DIR')) die('No direct access allowed');
4
5 // Admin-area code lives here. This gets called in admin_menu, earlier than admin_init
6
7 global $updraftplus_admin;
8 if (!is_a($updraftplus_admin, 'UpdraftPlus_Admin')) $updraftplus_admin = new UpdraftPlus_Admin();
9
10 class UpdraftPlus_Admin {
11
12 public $logged = array();
13
14 public function __construct() {
15 $this->admin_init();
16 }
17
18 private function setup_all_admin_notices_global($service){
19 if ('googledrive' === $service || (is_array($service) && in_array('googledrive', $service))) {
20 $opts = UpdraftPlus_Options::get_updraft_option('updraft_googledrive');
21 if (empty($opts)) {
22 $clientid = UpdraftPlus_Options::get_updraft_option('updraft_googledrive_clientid', '');
23 $token = UpdraftPlus_Options::get_updraft_option('updraft_googledrive_token', '');
24 } else {
25 $clientid = $opts['clientid'];
26 $token = (empty($opts['token'])) ? '' : $opts['token'];
27 }
28 if (!empty($clientid) && empty($token)) add_action('all_admin_notices', array($this,'show_admin_warning_googledrive'));
29 }
30 if ('googlecloud' === $service || (is_array($service) && in_array('googlecloud', $service))) {
31 $opts = UpdraftPlus_Options::get_updraft_option('updraft_googlecloud');
32 if (!empty($opts)) {
33 $clientid = $opts['clientid'];
34 $token = (empty($opts['token'])) ? '' : $opts['token'];
35 }
36 if (!empty($clientid) && empty($token)) add_action('all_admin_notices', array($this,'show_admin_warning_googlecloud'));
37 }
38 if ('dropbox' === $service || (is_array($service) && in_array('dropbox', $service))) {
39 $opts = UpdraftPlus_Options::get_updraft_option('updraft_dropbox');
40 if (empty($opts['tk_request_token'])) {
41 add_action('all_admin_notices', array($this,'show_admin_warning_dropbox') );
42 }
43 }
44 if ('bitcasa' === $service || (is_array($service) && in_array('bitcasa', $service))) {
45 $opts = UpdraftPlus_Options::get_updraft_option('updraft_bitcasa');
46 if (!empty($opts['clientid']) && !empty($opts['secret']) && empty($opts['token'])) add_action('all_admin_notices', array($this,'show_admin_warning_bitcasa') );
47 }
48 if ('copycom' === $service || (is_array($service) && in_array('copycom', $service))) {
49 $opts = UpdraftPlus_Options::get_updraft_option('updraft_copycom');
50 if (!empty($opts['clientid']) && !empty($opts['secret']) && empty($opts['token'])) add_action('all_admin_notices', array($this,'show_admin_warning_copycom') );
51 }
52 if ('onedrive' === $service || (is_array($service) && in_array('onedrive', $service))) {
53 $opts = UpdraftPlus_Options::get_updraft_option('updraft_onedrive');
54 if (!empty($opts['clientid']) && !empty($opts['secret']) && empty($opts['refresh_token'])) add_action('all_admin_notices', array($this,'show_admin_warning_onedrive') );
55 }
56
57 if ('updraftvault' === $service || (is_array($service) && in_array('updraftvault', $service))) {
58 $vault_settings = UpdraftPlus_Options::get_updraft_option('updraft_updraftvault');
59 $connected = (is_array($vault_settings) && !empty($vault_settings['token']) && !empty($vault_settings['email'])) ? true : false;
60 if (!$connected) add_action('all_admin_notices', array($this,'show_admin_warning_updraftvault') );
61 }
62
63 if ($this->disk_space_check(1048576*35) === false) add_action('all_admin_notices', array($this, 'show_admin_warning_diskspace'));
64 }
65
66 private function setup_all_admin_notices_udonly($service, $override = false){
67 global $wp_version;
68
69 if (UpdraftPlus_Options::user_can_manage() && defined('DISABLE_WP_CRON') && DISABLE_WP_CRON == true) {
70 add_action('all_admin_notices', array($this, 'show_admin_warning_disabledcron'));
71 }
72
73 if (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
74 @ini_set('display_errors',1);
75 @error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
76 add_action('all_admin_notices', array($this, 'show_admin_debug_warning'));
77 }
78
79 if (null === UpdraftPlus_Options::get_updraft_option('updraft_interval')) {
80 add_action('all_admin_notices', array($this, 'show_admin_nosettings_warning'));
81 $this->no_settings_warning = true;
82 }
83
84 # Avoid false positives, by attempting to raise the limit (as happens when we actually do a backup)
85 @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
86 $max_execution_time = (int)@ini_get('max_execution_time');
87 if ($max_execution_time>0 && $max_execution_time<20) {
88 add_action('all_admin_notices', array($this, 'show_admin_warning_execution_time'));
89 }
90
91 // LiteSpeed has a generic problem with terminating cron jobs
92 if (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false) {
93 if (!is_file(ABSPATH.'.htaccess') || !preg_match('/noabort/i', file_get_contents(ABSPATH.'.htaccess'))) {
94 add_action('all_admin_notices', array($this, 'show_admin_warning_litespeed'));
95 }
96 }
97
98 if (version_compare($wp_version, '3.2', '<')) add_action('all_admin_notices', array($this, 'show_admin_warning_wordpressversion'));
99 }
100
101 /*
102 private function reset_all_updraft_admin_notices() {
103
104 $actions_to_remove = array('show_admin_warning_googledrive', 'show_admin_warning_googlecloud', 'show_admin_warning_dropbox', 'show_admin_warning_bitcasa', 'show_admin_warning_copycom', 'show_admin_warning_onedrive', 'show_admin_warning_updraftvault', 'show_admin_warning_diskspace', 'show_admin_warning_disabledcron', 'show_admin_debug_warning', 'show_admin_warning_execution_time', 'show_admin_warning_litespeed', 'show_admin_warning_wordpressversion');
105
106 foreach ($actions_to_remove as $action) {
107 remove_action('all_admin_notices', $action);
108 }
109
110 }
111 */
112
113 //Used to output the information for the next scheduled backup
114 //**// moved to function for the ajax saves
115 private function next_scheduled_backups_output() {
116 // UNIX timestamp
117 $next_scheduled_backup = wp_next_scheduled('updraft_backup');
118 if ($next_scheduled_backup) {
119 // Convert to GMT
120 $next_scheduled_backup_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup);
121 // Convert to blog time zone
122 $next_scheduled_backup = get_date_from_gmt($next_scheduled_backup_gmt, 'D, F j, Y H:i');
123 // $next_scheduled_backup = date_i18n('D, F j, Y H:i', $next_scheduled_backup);
124 } else {
125 $next_scheduled_backup = __('Nothing currently scheduled', 'updraftplus');
126 $files_not_scheduled = true;
127 }
128
129 $next_scheduled_backup_database = wp_next_scheduled('updraft_backup_database');
130 if (UpdraftPlus_Options::get_updraft_option('updraft_interval_database',UpdraftPlus_Options::get_updraft_option('updraft_interval')) == UpdraftPlus_Options::get_updraft_option('updraft_interval')) {
131 if (isset($files_not_scheduled)) {
132 $next_scheduled_backup_database = $next_scheduled_backup;
133 $database_not_scheduled = true;
134 } else {
135 $next_scheduled_backup_database = __("At the same time as the files backup", 'updraftplus');
136 $next_scheduled_backup_database_same_time = true;
137 }
138 } else {
139 if ($next_scheduled_backup_database) {
140 // Convert to GMT
141 $next_scheduled_backup_database_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup_database);
142 // Convert to blog time zone
143 $next_scheduled_backup_database = get_date_from_gmt($next_scheduled_backup_database_gmt, 'D, F j, Y H:i');
144 // $next_scheduled_backup_database = date_i18n('D, F j, Y H:i', $next_scheduled_backup_database);
145 } else {
146 $next_scheduled_backup_database = __('Nothing currently scheduled', 'updraftplus');
147 $database_not_scheduled = true;
148 }
149 }
150 ?>
151 <tr>
152 <?php if (isset($files_not_scheduled) && isset($database_not_scheduled)) { ?>
153 <td colspan="2" class="not-scheduled"><?php _e('Nothing currently scheduled','updraftplus'); ?></td>
154 <?php } else { ?>
155 <td class="updraft_scheduled"><?php echo empty($next_scheduled_backup_database_same_time) ? __('Files','updraftplus') : __('Files and database', 'updraftplus'); ?>:</td><td class="updraft_all-files"><?php echo $next_scheduled_backup; ?></td>
156 </tr>
157 <?php if (empty($next_scheduled_backup_database_same_time)) { ?>
158 <tr>
159 <td class="updraft_scheduled"><?php _e('Database','updraftplus');?>: </td><td class="updraft_all-files"><?php echo $next_scheduled_backup_database; ?></td>
160 </tr>
161 <?php } ?>
162 <?php
163 }
164 }
165
166 private function admin_init() {
167
168 add_action('core_upgrade_preamble', array($this, 'core_upgrade_preamble'));
169 add_action('admin_action_upgrade-plugin', array($this, 'admin_action_upgrade_pluginortheme'));
170 add_action('admin_action_upgrade-theme', array($this, 'admin_action_upgrade_pluginortheme'));
171
172 add_action('admin_head', array($this,'admin_head'));
173 add_filter((is_multisite() ? 'network_admin_' : '').'plugin_action_links', array($this, 'plugin_action_links'), 10, 2);
174 add_action('wp_ajax_updraft_download_backup', array($this, 'updraft_download_backup'));
175 add_action('wp_ajax_updraft_ajax', array($this, 'updraft_ajax_handler'));
176 add_action('wp_ajax_updraft_ajaxrestore', array($this, 'updraft_ajaxrestore'));
177 add_action('wp_ajax_nopriv_updraft_ajaxrestore', array($this, 'updraft_ajaxrestore'));
178
179 add_action('wp_ajax_plupload_action', array($this, 'plupload_action'));
180 add_action('wp_ajax_plupload_action2', array($this, 'plupload_action2'));
181
182 add_action('wp_before_admin_bar_render', array($this, 'wp_before_admin_bar_render'));
183
184 // Add a new Ajax action for saving settings
185 add_action('wp_ajax_updraft_savesettings', array($this, 'updraft_ajax_savesettings'));
186
187 global $updraftplus, $wp_version, $pagenow;
188 add_filter('updraftplus_dirlist_others', array($updraftplus, 'backup_others_dirlist'));
189 add_filter('updraftplus_dirlist_uploads', array($updraftplus, 'backup_uploads_dirlist'));
190
191 // First, the checks that are on all (admin) pages:
192
193 $service = UpdraftPlus_Options::get_updraft_option('updraft_service');
194
195 if (UpdraftPlus_Options::user_can_manage()) {
196
197 $this->print_restore_in_progress_box_if_needed();
198
199 // Main dashboard page advert
200 // Since our nonce is printed, make sure they have sufficient credentials
201 if (!file_exists(UPDRAFTPLUS_DIR.'/udaddons') && $pagenow == 'index.php' && current_user_can('update_plugins')) {
202
203 $dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismisseddashnotice', 0);
204
205 $backup_dir = $updraftplus->backups_dir_location();
206 // N.B. Not an exact proxy for the installed time; they may have tweaked the expert option to move the directory
207 $installed = @filemtime($backup_dir.'/index.html');
208 $installed_for = time() - $installed;
209
210 if (($installed && time() > $dismissed_until && $installed_for > 28*86400 && !defined('UPDRAFTPLUS_NOADS_B')) || (defined('UPDRAFTPLUS_FORCE_DASHNOTICE') && UPDRAFTPLUS_FORCE_DASHNOTICE)) {
211 add_action('all_admin_notices', array($this, 'show_admin_notice_upgradead') );
212 }
213 }
214
215 //Moved out for use with Ajax saving
216 $this->setup_all_admin_notices_global($service);
217 }
218
219 // Next, the actions that only come on the UpdraftPlus page
220 if ($pagenow != UpdraftPlus_Options::admin_page() || empty($_REQUEST['page']) || 'updraftplus' != $_REQUEST['page']) return;
221 $this->setup_all_admin_notices_udonly($service);
222
223 add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'), 99999);
224 }
225
226 public function updraft_ajaxrestore() {
227 // TODO: All needs testing with restricted filesystem permissions. Those credentials need to be POST-ed too - currently not.
228 // TODO
229 // error_log(serialize($_POST));
230
231 if (empty($_POST['subaction']) || 'restore' != $_POST['subaction']) {
232 echo json_encode(array('e' => 'Illegitimate data sent (0)'));
233 die();
234 }
235
236 if (empty($_POST['restorenonce'])) {
237 echo json_encode(array('e' => 'Illegitimate data sent (1)'));
238 die();
239 }
240
241 $restore_nonce = (string)$_POST['restorenonce'];
242
243 if (empty($_POST['ajaxauth'])) {
244 echo json_encode(array('e' => 'Illegitimate data sent (2)'));
245 die();
246 }
247
248 global $updraftplus;
249
250 $ajax_auth = get_site_option('updraft_ajax_restore_'.$restore_nonce);
251
252 if (!$ajax_auth) {
253 echo json_encode(array('e' => 'Illegitimate data sent (3)'));
254 die();
255 }
256
257 if (!preg_match('/^([0-9a-f]+):(\d+)/i', $ajax_auth, $matches)) {
258 echo json_encode(array('e' => 'Illegitimate data sent (4)'));
259 die();
260 }
261
262 $nonce_time = $matches[2];
263 $auth_code_sent = $matches[1];
264 if (time() > $nonce_time + 600) {
265 echo json_encode(array('e' => 'Illegitimate data sent (5)'));
266 die();
267 }
268
269 // TODO: Deactivate the auth code whilst the operation is underway
270
271 $last_one = empty($_POST['lastone']) ? false : true;
272
273 @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
274
275 $updraftplus->backup_time_nonce($restore_nonce);
276 $updraftplus->logfile_open($restore_nonce);
277
278 $timestamp = empty($_POST['timestamp']) ? false : (int)$_POST['timestamp'];
279 $multisite = empty($_POST['multisite']) ? false : (bool)$_POST['multisite'];
280 $created_by_version = empty($_POST['created_by_version']) ? false : (int)$_POST['created_by_version'];
281
282 // TODO: We need to know about first_one (not yet sent), as well as last_one
283
284 // TODO: Verify the values of these
285 $type = empty($_POST['type']) ? false : (int)$_POST['type'];
286 $backupfile = empty($_POST['backupfile']) ? false : (string)$_POST['backupfile'];
287
288 $updraftplus->log("Deferred restore resumption: $type: $backupfile (timestamp=$timestamp, last_one=$last_one)");
289
290
291
292 $backupable_entities = $updraftplus->get_backupable_file_entities(true);
293
294 if (!isset($backupable_entities[$type])) {
295 echo json_encode(array('e' => 'Illegitimate data sent (6 - no such entity)', 'data' => $type));
296 die();
297 }
298
299
300 if ($last_one) {
301 // Remove the auth nonce from the DB to prevent abuse
302 delete_site_option('updraft_ajax_restore_'.$restore_nonce);
303 } else {
304 // Reset the counter after a successful operation
305 update_site_option('updraft_ajax_restore_'.$restore_nonce, $auth_code_sent.':'.time());
306 }
307
308 echo json_encode(array('e' => 'TODO', 'd' => $_POST));
309 die;
310 }
311
312 public function wp_before_admin_bar_render() {
313 global $wp_admin_bar;
314
315 if (!UpdraftPlus_Options::user_can_manage()) return;
316 if (defined('UPDRAFTPLUS_ADMINBAR_DISABLE') && UPDRAFTPLUS_ADMINBAR_DISABLE) return;
317
318 if (false == apply_filters('updraftplus_settings_page_render', true)) return;
319
320 $option_location = UpdraftPlus_Options::admin_page_url();
321
322 $args = array(
323 'id' => 'updraft_admin_node',
324 'title' => 'UpdraftPlus'
325 );
326 $wp_admin_bar->add_node($args);
327
328 $args = array(
329 'id' => 'updraft_admin_node_status',
330 'title' => __('Current Status', 'updraftplus').' / '.__('Backup Now', 'updraftplus'),
331 'parent' => 'updraft_admin_node',
332 'href' => $option_location.'?page=updraftplus&tab=status'
333 );
334 $wp_admin_bar->add_node($args);
335
336 $args = array(
337 'id' => 'updraft_admin_node_backups',
338 'title' => __('Existing Backups', 'updraftplus'),
339 'parent' => 'updraft_admin_node',
340 'href' => $option_location.'?page=updraftplus&tab=backups'
341 );
342 $wp_admin_bar->add_node($args);
343
344 $args = array(
345 'id' => 'updraft_admin_node_settings',
346 'title' => __('Settings', 'updraftplus'),
347 'parent' => 'updraft_admin_node',
348 'href' => $option_location.'?page=updraftplus&tab=settings'
349 );
350 $wp_admin_bar->add_node($args);
351
352 $args = array(
353 'id' => 'updraft_admin_node_expert_content',
354 'title' => __('Advanced Tools', 'updraftplus'),
355 'parent' => 'updraft_admin_node',
356 'href' => $option_location.'?page=updraftplus&tab=expert'
357 );
358 $wp_admin_bar->add_node($args);
359
360 $args = array(
361 'id' => 'updraft_admin_node_addons',
362 'title' => __('Extensions', 'updraftplus'),
363 'parent' => 'updraft_admin_node',
364 'href' => $option_location.'?page=updraftplus&tab=addons'
365 );
366 $wp_admin_bar->add_node($args);
367
368 global $updraftplus;
369 if (!$updraftplus->have_addons) {
370 $args = array(
371 'id' => 'updraft_admin_node_premium',
372 'title' => 'UpdraftPlus Premium',
373 'parent' => 'updraft_admin_node',
374 'href' => 'https://updraftplus.com/shop/updraftplus-premium/'
375 );
376 $wp_admin_bar->add_node($args);
377 }
378 }
379
380 // // Defeat other plugins/themes which dump their jQuery UI CSS onto our settings page
381 // public function style_loader_tag($link, $handle) {
382 // if ('jquery-ui' != $handle || false === strpos) return $link;
383 // return "<link rel='stylesheet' id='$handle-css' $title href='$href' type='text/css' media='$media' />\n";
384 // }
385
386 public function show_admin_notice_upgradead() {
387 ?>
388 <div id="updraft-dashnotice" class="updated">
389 <div style="float:right;"><a href="#" onclick="jQuery('#updraft-dashnotice').slideUp(); jQuery.post(ajaxurl, {action: 'updraft_ajax', subaction: 'dismissdashnotice', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce');?>' });"><?php echo sprintf(__('Dismiss (for %s months)', 'updraftplus'), 12); ?></a></div>
390
391 <h3 class="thank-you"><?php _e('Thank you for backing up with UpdraftPlus!', 'updraftplus');?></h3>
392
393 <a href="https://updraftplus.com/"><img class="udp-logo" alt="UpdraftPlus" src="<?php echo UPDRAFTPLUS_URL.'/images/ud-logo-150.png' ?>"></a>
394
395 <?php
396 echo '<p><strong>'.__('Free Newsletter', 'updraftplus').'</strong> <br>'.__('UpdraftPlus news, high-quality training materials for WordPress developers and site-owners, and general WordPress news. You can de-subscribe at any time.', 'updraftplus').' <a href="https://updraftplus.com/newsletter-signup">'.__('Follow this link to sign up.', 'updraftplus').'</a></p>';
397
398 echo '<p><strong>'.__('UpdraftPlus Premium', 'updraftplus').'</strong> <br>'.__('For personal support, the ability to copy sites, more storage destinations, encrypted backups for security, multiple backup destinations, better reporting, no adverts and plenty more, take a look at the premium version of UpdraftPlus - the world’s most popular backup plugin.', 'updraftplus').' <a href="https://updraftplus.com/comparison-updraftplus-free-updraftplus-premium/">'.__('Compare with the free version', 'updraftplus').'</a> / <a href="https://updraftplus.com/shop/updraftplus-premium/">'.__('Go to the shop.', 'updraftplus').'</a></p>';
399
400 echo '<p><strong>'.__('More Quality Plugins', 'updraftplus').'</strong> <br> <a href="https://wordpress.org/plugins/two-factor-authentication/">'.__('Free two-factor security plugin', 'updraftplus').'</a> | <a href="https://www.simbahosting.co.uk/s3/shop/">'.__('Premium WooCommerce plugins', 'updraftplus').'</a></p>';
401 ?>
402
403 <div class="dismiss-dash-notice"><a href="#" onclick="jQuery('#updraft-dashnotice').slideUp(); jQuery.post(ajaxurl, {action: 'updraft_ajax', subaction: 'dismissdashnotice', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce');?>' });"><?php echo sprintf(__('Dismiss (for %s months)', 'updraftplus'), 12); ?></a></div>
404 </div>
405 <?php
406 }
407
408 private function ensure_sufficient_jquery_and_enqueue() {
409 global $updraftplus, $wp_version;
410
411 $enqueue_version = @constant('WP_DEBUG') ? $updraftplus->version.'-'.time() : $updraftplus->version;
412
413 if (version_compare($wp_version, '3.3', '<')) {
414 // Require a newer jQuery (3.2.1 has 1.6.1, so we go for something not too much newer). We use .on() in a way that is incompatible with < 1.7
415 wp_deregister_script('jquery');
416 wp_register_script('jquery', 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', false, '1.7.2', false);
417 wp_enqueue_script('jquery');
418 // No plupload until 3.3
419 wp_enqueue_script('updraftplus-admin-ui', UPDRAFTPLUS_URL.'/includes/updraft-admin-ui.js', array('jquery', 'jquery-ui-dialog'), $enqueue_version, true);
420 } else {
421 wp_enqueue_script('updraftplus-admin-ui', UPDRAFTPLUS_URL.'/includes/updraft-admin-ui.js', array('jquery', 'jquery-ui-dialog', 'plupload-all'), $enqueue_version);
422 }
423
424 }
425
426 // This is also called directly from the auto-backup add-on
427 public function admin_enqueue_scripts() {
428
429 global $updraftplus, $wp_locale;
430
431 // Defeat other plugins/themes which dump their jQuery UI CSS onto our settings page
432 wp_deregister_style('jquery-ui');
433 wp_enqueue_style('jquery-ui', UPDRAFTPLUS_URL.'/includes/jquery-ui.custom.css', array(), '1.11.4');
434
435 $our_version = @constant('SCRIPT_DEBUG') ? $updraftplus->version.'.'.time() : $updraftplus->version;
436
437 wp_enqueue_style('updraft-admin-css', UPDRAFTPLUS_URL.'/css/admin.css', array(), $our_version);
438 // add_filter('style_loader_tag', array($this, 'style_loader_tag'), 10, 2);
439
440 $this->ensure_sufficient_jquery_and_enqueue();
441
442 wp_enqueue_script('jquery-blockui', UPDRAFTPLUS_URL.'/includes/jquery.blockUI.js', array('jquery'), '2.70.0');
443
444 wp_enqueue_script('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.js', array('jquery'), '20150925');
445 wp_enqueue_style('jquery-labelauty', UPDRAFTPLUS_URL.'/includes/labelauty/jquery-labelauty.css', array(), '20150925');
446
447 do_action('updraftplus_admin_enqueue_scripts');
448
449 $day_selector = '';
450 for ($day_index = 0; $day_index <= 6; $day_index++) {
451 // $selected = ($opt == $day_index) ? 'selected="selected"' : '';
452 $selected = '';
453 $day_selector .= "\n\t<option value='" . $day_index . "' $selected>" . $wp_locale->get_weekday($day_index) . '</option>';
454 }
455
456 $mday_selector = '';
457 for ($mday_index = 1; $mday_index <= 28; $mday_index++) {
458 // $selected = ($opt == $mday_index) ? 'selected="selected"' : '';
459 $selected = '';
460 $mday_selector .= "\n\t<option value='" . $mday_index . "' $selected>" . $mday_index . '</option>';
461 }
462
463 wp_localize_script('updraftplus-admin-ui', 'updraftlion', array(
464 'sendonlyonwarnings' => __('Send a report only when there are warnings/errors', 'updraftplus'),
465 'wholebackup' => __('When the Email storage method is enabled, also send the entire backup', 'updraftplus'),
466 'emailsizelimits' => esc_attr(sprintf(__('Be aware that mail servers tend to have size limits; typically around %s Mb; backups larger than any limits will likely not arrive.','updraftplus'), '10-20')),
467 'rescanning' => __('Rescanning (looking for backups that you have uploaded manually into the internal backup store)...','updraftplus'),
468 'rescanningremote' => __('Rescanning remote and local storage for backup sets...','updraftplus'),
469 'enteremailhere' => esc_attr(__('To send to more than one address, separate each address with a comma.', 'updraftplus')),
470 'excludedeverything' => __('If you exclude both the database and the files, then you have excluded everything!', 'updraftplus'),
471 'nofileschosen' => __('You have chosen to backup files, but no file entities have been selected', 'updraftplus'),
472 'restoreproceeding' => __('The restore operation has begun. Do not press stop or close your browser until it reports itself as having finished.', 'updraftplus'),
473 'unexpectedresponse' => __('Unexpected response:','updraftplus'),
474 'servererrorcode' => __('The web server returned an error code (try again, or check your web server logs)', 'updraftplus'),
475 'newuserpass' => __("The new user's RackSpace console password is (this will not be shown again):", 'updraftplus'),
476 'trying' => __('Trying...', 'updraftplus'),
477 'fetching' => __('Fetching...', 'updraftplus'),
478 'calculating' => __('calculating...','updraftplus'),
479 'begunlooking' => __('Begun looking for this entity','updraftplus'),
480 'stilldownloading' => __('Some files are still downloading or being processed - please wait.', 'updraftplus'),
481 'processing' => __('Processing files - please wait...', 'updraftplus'),
482 'emptyresponse' => __('Error: the server sent an empty response.', 'updraftplus'),
483 'warnings' => __('Warnings:','updraftplus'),
484 'errors' => __('Errors:','updraftplus'),
485 'jsonnotunderstood' => __('Error: the server sent us a response which we did not understand.', 'updraftplus'),
486 'errordata' => __('Error data:', 'updraftplus'),
487 'error' => __('Error:','updraftplus'),
488 'errornocolon' => __('Error','updraftplus'),
489 'fileready' => __('File ready.','updraftplus'),
490 'youshould' => __('You should:','updraftplus'),
491 'deletefromserver' => __('Delete from your web server','updraftplus'),
492 'downloadtocomputer' => __('Download to your computer','updraftplus'),
493 'andthen' => __('and then, if you wish,', 'updraftplus'),
494 'notunderstood' => __('Download error: the server sent us a response which we did not understand.', 'updraftplus'),
495 'requeststart' => __('Requesting start of backup...', 'updraftplus'),
496 'phpinfo' => __('PHP information', 'updraftplus'),
497 'delete_old_dirs' => __('Delete Old Directories', 'updraftplus'),
498 'raw' => __('Raw backup history', 'updraftplus'),
499 'notarchive' => __('This file does not appear to be an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)).', 'updraftplus').' '.__('However, UpdraftPlus archives are standard zip/SQL files - so if you are sure that your file has the right format, then you can rename it to match that pattern.','updraftplus'),
500 'notarchive2' => '<p>'.__('This file does not appear to be an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)).', 'updraftplus').'</p> '.apply_filters('updraftplus_if_foreign_then_premium_message', '<p><a href="https://updraftplus.com/shop/updraftplus-premium/">'.__('If this is a backup created by a different backup plugin, then UpdraftPlus Premium may be able to help you.', 'updraftplus').'</a></p>'),
501 'makesure' => __('(make sure that you were trying to upload a zip file previously created by UpdraftPlus)','updraftplus'),
502 'uploaderror' => __('Upload error:','updraftplus'),
503 'notdba' => __('This file does not appear to be an UpdraftPlus encrypted database archive (such files are .gz.crypt files which have a name like: backup_(time)_(site name)_(code)_db.crypt.gz).','updraftplus'),
504 'uploaderr' => __('Upload error', 'updraftplus'),
505 'followlink' => __('Follow this link to attempt decryption and download the database file to your computer.','updraftplus'),
506 'thiskey' => __('This decryption key will be attempted:','updraftplus'),
507 'unknownresp' => __('Unknown server response:','updraftplus'),
508 'ukrespstatus' => __('Unknown server response status:','updraftplus'),
509 'uploaded' => __('The file was uploaded.','updraftplus'),
510 'backupnow' => __('Backup Now', 'updraftplus'),
511 'cancel' => __('Cancel', 'updraftplus'),
512 'deletebutton' => __('Delete', 'updraftplus'),
513 'createbutton' => __('Create', 'updraftplus'),
514 'youdidnotselectany' => __('You did not select any components to restore. Please select at least one, and then try again.', 'updraftplus'),
515 'proceedwithupdate' => __('Proceed with update', 'updraftplus'),
516 'close' => __('Close', 'updraftplus'),
517 'restore' => __('Restore', 'updraftplus'),
518 'downloadlogfile' => __('Download log file', 'updraftplus'),
519 'automaticbackupbeforeupdate' => __('Automatic backup before update', 'updraftplus'),
520 'unsavedsettings' => __('You have made changes to your settings, and not saved.', 'updraftplus'),
521 'saving' => __('Saving...', 'updraftplus'),
522 'connect' => __('Connect', 'updraftplus'),
523 'connecting' => __('Connecting...', 'updraftplus'),
524 'disconnect' => __('Disconnect', 'updraftplus'),
525 'disconnecting' => __('Disconnecting...', 'updraftplus'),
526 'counting' => __('Counting...', 'updraftplus'),
527 'updatequotacount' => __('Update quota count', 'updraftplus'),
528 'addingsite' => __('Adding...', 'updraftplus'),
529 'addsite' => __('Add site', 'updraftplus'),
530 // 'resetting' => __('Resetting...', 'updraftplus'),
531 'creating' => __('Creating...', 'updraftplus'),
532 'sendtosite' => __('Send to site:', 'updraftplus'),
533 'checkrpcsetup' => sprintf(__('You should check that the remote site is online, not firewalled, does not have security modules that may be blocking access, has UpdraftPlus version %s or later active and that the keys have been entered correctly.', 'updraftplus'), '2.10.3'),
534 'pleasenamekey' => __('Please give this key a name (e.g. indicate the site it is for):', 'updraftplus'),
535 'key' => __('Key', 'updraftplus'),
536 'nokeynamegiven' => sprintf(__("Failure: No %s was given.",'updraftplus'), __('key name','updraftplus')),
537 'deleting' => __('Deleting...', 'updraftplus'),
538 'enter_mothership_url' => __('Please enter a valid URL', 'updraftplus'),
539 'delete_response_not_understood' => __("We requested to delete the file, but could not understand the server's response", 'updraftplus'),
540 'testingconnection' => __('Testing connection...', 'updraftplus'),
541 'send' => __('Send', 'updraftplus'),
542 'migratemodalheight' => class_exists('UpdraftPlus_Addons_Migrator') ? 555 : 300,
543 'migratemodalwidth' => class_exists('UpdraftPlus_Addons_Migrator') ? 770 : 500,
544 'download' => _x('Download', '(verb)', 'updraftplus'),
545 'unsavedsettingsbackup' => __('You have made changes to your settings, and not saved.', 'updraftplus')."\n".__('You should save your changes to ensure that they are used for making your backup.','updraftplus'),
546 'dayselector' => $day_selector,
547 'mdayselector' => $mday_selector,
548 'day' => __('day', 'updraftplus'),
549 'inthemonth' => __('in the month', 'updraftplus'),
550 'days' => __('day(s)', 'updraftplus'),
551 'hours' => __('hour(s)', 'updraftplus'),
552 'weeks' => __('week(s)', 'updraftplus'),
553 'forbackupsolderthan' => __('For backups older than', 'updraftplus'),
554 'ud_url' => UPDRAFTPLUS_URL,
555 'processing' => __('Processing...', 'updraftplus'),
556 'pleasefillinrequired' => __('Please fill in the required information.', 'updraftplus'),
557 'test_settings' => __('Test %s Settings', 'updraftplus'),
558 'testing_settings' => __('Testing %s Settings...', 'updraftplus'),
559 'settings_test_result' => __('%s settings test result:', 'updraftplus'),
560 'nothing_yet_logged' => __('Nothing yet logged', 'updraftplus'),
561 ) );
562 }
563
564 // Despite the name, this fires irrespective of what capabilities the user has (even none - so be careful)
565 public function core_upgrade_preamble() {
566
567 // They need to be able to perform backups, and to perform updates
568 if (!UpdraftPlus_Options::user_can_manage() || (!current_user_can('update_core') && !current_user_can('update_plugins') && !current_user_can('update_themes'))) return;
569
570 if (!class_exists('UpdraftPlus_Addon_Autobackup')) {
571 if (defined('UPDRAFTPLUS_NOADS_B')) return;
572 $dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismissedautobackup', 0);
573 if ($dismissed_until > time()) return;
574 }
575
576 ?>
577 <div id="updraft-autobackup" class="updated autobackup">
578 <?php if (!class_exists('UpdraftPlus_Addon_Autobackup')) { ?>
579 <div style="float:right;"><a href="#" onclick="jQuery('#updraft-autobackup').slideUp(); jQuery.post(ajaxurl, {action: 'updraft_ajax', subaction: 'dismissautobackup', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce');?>' });"><?php echo sprintf(__('Dismiss (for %s weeks)', 'updraftplus'), 12); ?></a></div> <?php } ?>
580 <h3 style="margin-top: 0px;"><?php _e('Be safe with an automatic backup','updraftplus');?></h3>
581 <?php echo apply_filters('updraftplus_autobackup_blurb', __('UpdraftPlus Premium can <strong>automatically</strong> take a backup of your plugins or themes and database before you update.', 'updraftplus').' <a href="https://updraftplus.com/shop/autobackup/">'.__('Be safe every time, without needing to remember - follow this link to learn more.' ,'updraftplus').'</a>'); ?>
582 </div>
583 <script>
584 jQuery(document).ready(function() {
585 jQuery('#updraft-autobackup').appendTo('.wrap p:first');
586 });
587 </script>
588 <?php
589 }
590
591 public function admin_head() {
592
593 global $pagenow;
594
595 if ($pagenow != UpdraftPlus_Options::admin_page() || !isset($_REQUEST['page']) || 'updraftplus' != $_REQUEST['page'] || !UpdraftPlus_Options::user_can_manage()) return;
596
597 $chunk_size = min(wp_max_upload_size()-1024, 1048576*2);
598
599 # The multiple_queues argument is ignored in plupload 2.x (WP3.9+) - http://make.wordpress.org/core/2014/04/11/plupload-2-x-in-wordpress-3-9/
600 # max_file_size is also in filters as of plupload 2.x, but in its default position is still supported for backwards-compatibility. Likewise, our use of filters.extensions below is supported by a backwards-compatibility option (the current way is filters.mime-types.extensions
601
602 $plupload_init = array(
603 'runtimes' => 'html5,flash,silverlight,html4',
604 'browse_button' => 'plupload-browse-button',
605 'container' => 'plupload-upload-ui',
606 'drop_element' => 'drag-drop-area',
607 'file_data_name' => 'async-upload',
608 'multiple_queues' => true,
609 'max_file_size' => '100Gb',
610 'chunk_size' => $chunk_size.'b',
611 'url' => admin_url('admin-ajax.php', 'relative'),
612 'multipart' => true,
613 'multi_selection' => true,
614 'urlstream_upload' => true,
615 // additional post data to send to our ajax hook
616 'multipart_params' => array(
617 '_ajax_nonce' => wp_create_nonce('updraft-uploader'),
618 'action' => 'plupload_action'
619 )
620 );
621 // 'flash_swf_url' => includes_url('js/plupload/plupload.flash.swf'),
622 // 'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'),
623
624 // We want to receive -db files also...
625 // if (1) {
626 // $plupload_init['filters'] = array(array('title' => __('Allowed Files'), 'extensions' => 'zip,tar,gz,bz2,crypt,sql,txt'));
627 // } else {
628 // }
629
630 # WP 3.9 updated to plupload 2.0 - https://core.trac.wordpress.org/ticket/25663
631 if (is_file(ABSPATH.WPINC.'/js/plupload/Moxie.swf')) {
632 $plupload_init['flash_swf_url'] = includes_url('js/plupload/Moxie.swf');
633 } else {
634 $plupload_init['flash_swf_url'] = includes_url('js/plupload/plupload.flash.swf');
635 }
636
637 if (is_file(ABSPATH.WPINC.'/js/plupload/Moxie.xap')) {
638 $plupload_init['silverlight_xap_url'] = includes_url('js/plupload/Moxie.xap');
639 } else {
640 $plupload_init['silverlight_xap_url'] = includes_url('js/plupload/plupload.silverlight.swf');
641 }
642
643 ?><script type="text/javascript">
644 var updraft_credentialtest_nonce='<?php echo wp_create_nonce('updraftplus-credentialtest-nonce');?>';
645 var updraftplus_settings_nonce='<?php echo wp_create_nonce('updraftplus-settings-nonce');?>';
646 var updraft_siteurl = '<?php echo esc_js(site_url('', 'relative'));?>';
647 var updraft_plupload_config=<?php echo json_encode($plupload_init); ?>;
648 var updraft_download_nonce='<?php echo wp_create_nonce('updraftplus_download');?>';
649 var updraft_accept_archivename = <?php echo apply_filters('updraftplus_accept_archivename_js', "[]");?>;
650 <?php
651 $plupload_init['browse_button'] = 'plupload-browse-button2';
652 $plupload_init['container'] = 'plupload-upload-ui2';
653 $plupload_init['drop_element'] = 'drag-drop-area2';
654 $plupload_init['multipart_params']['action'] = 'plupload_action2';
655 $plupload_init['filters'] = array(array('title' => __('Allowed Files'), 'extensions' => 'crypt'));
656 ?>
657 var updraft_plupload_config2=<?php echo json_encode($plupload_init); ?>;
658 var updraft_downloader_nonce = '<?php wp_create_nonce("updraftplus_download"); ?>'
659 <?php
660 $overdue = $this->howmany_overdue_crons();
661 if ($overdue >= 4) { ?>
662 jQuery(document).ready(function(){
663 setTimeout(function(){updraft_check_overduecrons();}, 11000);
664 function updraft_check_overduecrons() {
665 jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'checkoverduecrons', nonce: updraft_credentialtest_nonce }, function(data, response) {
666 if ('success' == response) {
667 try {
668 resp = jQuery.parseJSON(data);
669 if (resp.m) {
670 jQuery('#updraft-insert-admin-warning').html(resp.m);
671 }
672 } catch(err) {
673 console.log(data);
674 }
675 }
676 });
677 }
678 });
679 <?php } ?>
680 </script>
681 <?php
682
683 }
684
685
686 private function disk_space_check($space) {
687 global $updraftplus;
688 $updraft_dir = $updraftplus->backups_dir_location();
689 $disk_free_space = @disk_free_space($updraft_dir);
690 if ($disk_free_space == false) return -1;
691 return ($disk_free_space > $space) ? true : false;
692 }
693
694 # Adds the settings link under the plugin on the plugin screen.
695 public function plugin_action_links($links, $file) {
696 if (is_array($links) && $file == 'updraftplus/updraftplus.php'){
697 $settings_link = '<a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__("Settings", "updraftplus").'</a>';
698 array_unshift($links, $settings_link);
699 // $settings_link = '<a href="http://david.dw-perspective.org.uk/donate">'.__("Donate","UpdraftPlus").'</a>';
700 // array_unshift($links, $settings_link);
701 $settings_link = '<a href="https://updraftplus.com">'.__("Add-Ons / Pro Support","updraftplus").'</a>';
702 array_unshift($links, $settings_link);
703 }
704 return $links;
705 }
706
707 public function admin_action_upgrade_pluginortheme() {
708
709 if (isset($_GET['action']) && ($_GET['action'] == 'upgrade-plugin' || $_GET['action'] == 'upgrade-theme') && !class_exists('UpdraftPlus_Addon_Autobackup') && !defined('UPDRAFTPLUS_NOADS_B')) {
710
711 if ($_GET['action'] == 'upgrade-plugin') {
712 if (!current_user_can('update_plugins')) return;
713 } else {
714 if (!current_user_can('update_themes')) return;
715 }
716
717 $dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismissedautobackup', 0);
718 if ($dismissed_until > time()) return;
719
720 if ( 'upgrade-plugin' == $_GET['action'] ) {
721 $title = __('Update Plugin');
722 $parent_file = 'plugins.php';
723 $submenu_file = 'plugins.php';
724 } else {
725 $title = __('Update Theme');
726 $parent_file = 'themes.php';
727 $submenu_file = 'themes.php';
728 }
729
730 require_once(ABSPATH.'wp-admin/admin-header.php');
731
732 ?>
733 <div id="updraft-autobackup" class="updated" style="float:left; padding: 6px; margin:8px 0px;">
734 <div style="float: right;"><a href="#" onclick="jQuery('#updraft-autobackup').slideUp(); jQuery.post(ajaxurl, {action: 'updraft_ajax', subaction: 'dismissautobackup', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce');?>' });"><?php echo sprintf(__('Dismiss (for %s weeks)', 'updraftplus'), 10); ?></a></div>
735 <h3 style="margin-top: 0px;"><?php _e('Be safe with an automatic backup','updraftplus');?></h3>
736 <p><?php echo __('UpdraftPlus Premium can <strong>automatically</strong> take a backup of your plugins or themes and database before you update.', 'updraftplus').' <a href="https://updraftplus.com/shop/autobackup/">'.__('Be safe every time, without needing to remember - follow this link to learn more.' ,'updraftplus').'</a>'; ?></p>
737 </div>
738 <?php
739 }
740 }
741
742 public function show_admin_warning($message, $class = "updated") {
743 echo '<div class="updraftmessage '.$class.'">'."<p>$message</p></div>";
744 }
745
746 //
747 public function show_admin_warning_unwritable(){
748 $unwritable_mess = htmlspecialchars(__("The 'Backup Now' button is disabled as your backup directory is not writable (go to the 'Settings' tab and find the relevant option).", 'updraftplus'));
749 $this->show_admin_warning($unwritable_mess, "error");
750 }
751
752 public function show_admin_nosettings_warning() {
753 $this->show_admin_warning('<strong>'.__('Welcome to UpdraftPlus!', 'updraftplus').'</strong> '.__('To make a backup, just press the Backup Now button.', 'updraftplus').' <a href="#" id="updraft-navtab-settings2">'.__('To change any of the default settings of what is backed up, to configure scheduled backups, to send your backups to remote storage (recommended), and more, go to the settings tab.', 'updraftplus').'</a>', 'updated notice is-dismissible');
754 }
755
756 public function show_admin_warning_execution_time() {
757 $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('The amount of time allowed for WordPress plugins to run is very low (%s seconds) - you should increase it to avoid backup failures due to time-outs (consult your web hosting company for more help - it is the max_execution_time PHP setting; the recommended value is %s seconds or more)', 'updraftplus'), (int)@ini_get('max_execution_time'), 90));
758 }
759
760 public function show_admin_warning_disabledcron() {
761 $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.__('The scheduler is disabled in your WordPress install, via the DISABLE_WP_CRON setting. No backups can run (even &quot;Backup Now&quot;) unless either you have set up a facility to call the scheduler manually, or until it is enabled.','updraftplus').' <a href="https://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/#disablewpcron">'.__('Go here for more information.','updraftplus').'</a>', 'updated updraftplus-disable-wp-cron-warning');
762 }
763
764 public function show_admin_warning_diskspace() {
765 $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('You have less than %s of free disk space on the disk which UpdraftPlus is configured to use to create backups. UpdraftPlus could well run out of space. Contact your the operator of your server (e.g. your web hosting company) to resolve this issue.','updraftplus'),'35 MB'));
766 }
767
768 public function show_admin_warning_wordpressversion() {
769 $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('UpdraftPlus does not officially support versions of WordPress before %s. It may work for you, but if it does not, then please be aware that no support is available until you upgrade WordPress.', 'updraftplus'), '3.2'));
770 }
771
772 public function show_admin_warning_litespeed() {
773 $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('Your website is hosted using the %s web server.','updraftplus'),'LiteSpeed').' <a href="https://updraftplus.com/faqs/i-am-having-trouble-backing-up-and-my-web-hosting-company-uses-the-litespeed-webserver/">'.__('Please consult this FAQ if you have problems backing up.', 'updraftplus').'</a>');
774 }
775
776 public function show_admin_debug_warning() {
777 $this->show_admin_warning('<strong>'.__('Notice','updraftplus').':</strong> '.__('UpdraftPlus\'s debug mode is on. You may see debugging notices on this page not just from UpdraftPlus, but from any other plugin installed. Please try to make sure that the notice you are seeing is from UpdraftPlus before you raise a support request.', 'updraftplus').'</a>');
778 }
779
780 public function show_admin_warning_overdue_crons($howmany) {
781 $ret = '<div class="updraftmessage updated"><p>';
782 $ret .= '<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('WordPress has a number (%d) of scheduled tasks which are overdue. Unless this is a development site, this probably means that the scheduler in your WordPress install is not working.', 'updraftplus'), $howmany).' <a href="https://updraftplus.com/faqs/scheduler-wordpress-installation-working/">'.__('Read this page for a guide to possible causes and how to fix it.', 'updraftplus').'</a>';
783 $ret .= '</p></div>';
784 return $ret;
785 }
786
787 public function show_admin_warning_dropbox() {
788 $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a class="updraft_authlink" href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraftmethod-dropbox-auth&updraftplus_dropboxauth=doit">'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'), 'Dropbox', 'Dropbox').'</a>');
789 }
790
791 public function show_admin_warning_bitcasa() {
792 $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a class="updraft_authlink" href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraftmethod-bitcasa-auth&updraftplus_bitcasaauth=doit">'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'), 'Bitcasa', 'Bitcasa').'</a>');
793 }
794
795 public function show_admin_warning_copycom() {
796 $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a class="updraft_authlink" href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraftmethod-copycom-auth&updraftplus_copycomauth=doit">'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'), 'Copy.Com', 'Copy').'</a>');
797 }
798
799 public function show_admin_warning_onedrive() {
800 $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a class="updraft_authlink" href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraftmethod-onedrive-auth&updraftplus_onedriveauth=doit">'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'), 'OneDrive', 'OneDrive').'</a>');
801 }
802
803 public function show_admin_warning_updraftvault() {
804 $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> '.sprintf(__('%s has been chosen for remote storage, but you are not currently connected.', 'updraftplus'), 'UpdraftPlus Vault').' '.__('Go to the remote storage settings in order to connect.', 'updraftplus'));
805 }
806
807 public function show_admin_warning_googledrive() {
808 $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a class="updraft_authlink" href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraftmethod-googledrive-auth&updraftplus_googleauth=doit">'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'), 'Google Drive', 'Google Drive').'</a>');
809 }
810
811 public function show_admin_warning_googlecloud() {
812 $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a class="updraft_authlink" href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraftmethod-googlecloud-auth&updraftplus_googleauth=doit">'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'), 'Google Cloud', 'Google Cloud').'</a>');
813 }
814
815
816 // This options filter removes ABSPATH off the front of updraft_dir, if it is given absolutely and contained within it
817 public function prune_updraft_dir_prefix($updraft_dir) {
818 if ('/' == substr($updraft_dir, 0, 1) || "\\" == substr($updraft_dir, 0, 1) || preg_match('/^[a-zA-Z]:/', $updraft_dir)) {
819 $wcd = trailingslashit(WP_CONTENT_DIR);
820 if (strpos($updraft_dir, $wcd) === 0) {
821 $updraft_dir = substr($updraft_dir, strlen($wcd));
822 }
823 # Legacy
824 // if (strpos($updraft_dir, ABSPATH) === 0) {
825 // $updraft_dir = substr($updraft_dir, strlen(ABSPATH));
826 // }
827 }
828 return $updraft_dir;
829 }
830
831 public function updraft_download_backup() {
832
833 if (empty($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'], 'updraftplus_download')) die;
834
835 if (empty($_REQUEST['timestamp']) || !is_numeric($_REQUEST['timestamp']) || empty($_REQUEST['type'])) exit;
836
837 $findex = empty($_REQUEST['findex']) ? 0 : (int)$_REQUEST['findex'];
838 $stage = empty($_REQUEST['stage']) ? '' : $_REQUEST['stage'];
839
840 // This call may not actually return, depending upon what mode it is called in
841 echo json_encode($this->do_updraft_download_backup($findex, $_REQUEST['type'], $_REQUEST['timestamp'], $stage));
842
843 die();
844 }
845
846 // This function may die(), depending on the request being made in $stage
847 public function do_updraft_download_backup($findex, $type, $timestamp, $stage, $close_connection_callable = false) {
848
849 @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
850
851 global $updraftplus;
852
853 // This is a bit ugly; these variables get placed back into $_POST (where they may possibly have come from), so that UpdraftPlus::log() can detect exactly where to log the download status.
854 $_POST['findex'] = $findex;
855 $_POST['type'] = $type;
856 $_POST['timestamp'] = $timestamp;
857
858 // Check that it is a known entity type; if not, die
859 if ('db' != substr($type, 0, 2)) {
860 $backupable_entities = $updraftplus->get_backupable_file_entities(true);
861 foreach ($backupable_entities as $t => $info) {
862 if ($type == $t) $type_match = true;
863 }
864 if (empty($type_match)) return array('result' => 'error', 'code' => 'no_such_type');
865 }
866
867 // We already know that no possible entities have an MD5 clash (even after 2 characters)
868 // Also, there's nothing enforcing a requirement that nonces are hexadecimal
869 $job_nonce = dechex($timestamp).$findex.substr(md5($type), 0, 3);
870
871 // You need a nonce before you can set job data. And we certainly don't yet have one.
872 $updraftplus->backup_time_nonce($job_nonce);
873
874 $debug_mode = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
875
876 // Set the job type before logging, as there can be different logging destinations
877 $updraftplus->jobdata_set('job_type', 'download');
878 $updraftplus->jobdata_set('job_time_ms', $updraftplus->job_time_ms);
879
880 // Retrieve the information from our backup history
881 $backup_history = $updraftplus->get_backup_history();
882 // Base name
883 $file = $backup_history[$timestamp][$type];
884
885 // Deal with multi-archive sets
886 if (is_array($file)) $file=$file[$findex];
887
888 // Where it should end up being downloaded to
889 $fullpath = $updraftplus->backups_dir_location().'/'.$file;
890
891 if (2 == $stage) {
892 $updraftplus->spool_file($fullpath);
893 // Do not return - we do not want the caller to add any output
894 die;
895 }
896
897 if ('delete' == $stage) {
898 @unlink($fullpath);
899 $updraftplus->log("The file has been deleted ($file)");
900 return array('result' => 'deleted');
901 }
902
903 // TODO: FIXME: Failed downloads may leave log files forever (though they are small)
904 if ($debug_mode) $updraftplus->logfile_open($updraftplus->nonce);
905
906 set_error_handler(array($updraftplus, 'php_error'), E_ALL & ~E_STRICT);
907
908 $updraftplus->log("Requested to obtain file: timestamp=$timestamp, type=$type, index=$findex");
909
910 $itext = empty($findex) ? '' : $findex;
911 $known_size = isset($backup_history[$timestamp][$type.$itext.'-size']) ? $backup_history[$timestamp][$type.$itext.'-size'] : 0;
912
913 $services = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
914 if (is_string($services)) $services = array($services);
915
916 $updraftplus->jobdata_set('service', $services);
917
918 // Fetch it from the cloud, if we have not already got it
919
920 $needs_downloading = false;
921
922 if (!file_exists($fullpath)) {
923 //if the file doesn't exist and they're using one of the cloud options, fetch it down from the cloud.
924 $needs_downloading = true;
925 $updraftplus->log('File does not yet exist locally - needs downloading');
926 } elseif ($known_size > 0 && filesize($fullpath) < $known_size) {
927 $updraftplus->log("The file was found locally (".filesize($fullpath).") but did not match the size in the backup history ($known_size) - will resume downloading");
928 $needs_downloading = true;
929 } elseif ($known_size > 0) {
930 $updraftplus->log('The file was found locally and matched the recorded size from the backup history ('.round($known_size/1024,1).' KB)');
931 } else {
932 $updraftplus->log('No file size was found recorded in the backup history. We will assume the local one is complete.');
933 $known_size = filesize($fullpath);
934 }
935
936 // The AJAX responder that updates on progress wants to see this
937 $updraftplus->jobdata_set('dlfile_'.$timestamp.'_'.$type.'_'.$findex, "downloading:$known_size:$fullpath");
938
939 if ($needs_downloading) {
940
941 $msg = array(
942 'result' => 'needs_download'
943 );
944
945 if ($close_connection_callable && is_callable($close_connection_callable)) {
946 call_user_func($close_connection_callable, $msg);
947 } else {
948 $updraftplus->close_browser_connection(json_encode($msg));
949 }
950
951 $is_downloaded = false;
952 add_action('http_request_args', array($updraftplus, 'modify_http_options'));
953 foreach ($services as $service) {
954 if ($is_downloaded) continue;
955 $download = $this->download_file($file, $service);
956 if (is_readable($fullpath) && $download !== false) {
957 clearstatcache();
958 $updraftplus->log('Remote fetch was successful (file size: '.round(filesize($fullpath)/1024,1).' KB)');
959 $is_downloaded = true;
960 } else {
961 clearstatcache();
962 if (0 === @filesize($fullpath)) @unlink($fullpath);
963 $updraftplus->log('Remote fetch failed');
964 }
965 }
966 remove_action('http_request_args', array($updraftplus, 'modify_http_options'));
967 }
968
969 // Now, be ready to spool the thing to the browser
970 if (is_file($fullpath) && is_readable($fullpath)) {
971
972 // That message is then picked up by the AJAX listener
973 $updraftplus->jobdata_set('dlfile_'.$timestamp.'_'.$type.'_'.$findex, 'downloaded:'.filesize($fullpath).":$fullpath");
974
975 $result = 'downloaded';
976
977 } else {
978
979 $updraftplus->jobdata_set('dlfile_'.$timestamp.'_'.$type.'_'.$findex, 'failed');
980 $updraftplus->jobdata_set('dlerrors_'.$timestamp.'_'.$type.'_'.$findex, $updraftplus->errors);
981 $updraftplus->log('Remote fetch failed. File '.$fullpath.' did not exist or was unreadable. If you delete local backups then remote retrieval may have failed.');
982
983 $result = 'download_failed';
984 }
985
986 restore_error_handler();
987
988 @fclose($updraftplus->logfile_handle);
989 if (!$debug_mode) @unlink($updraftplus->logfile_name);
990
991 // The browser connection was possibly already closed, but not necessarily
992 return array('result' => $result);
993
994 }
995
996 # Pass only a single service, as a string, into this function
997 private function download_file($file, $service) {
998
999 global $updraftplus;
1000
1001 @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
1002
1003 $updraftplus->log("Requested file from remote service: $service: $file");
1004
1005 $method_include = UPDRAFTPLUS_DIR.'/methods/'.$service.'.php';
1006 if (file_exists($method_include)) require_once($method_include);
1007
1008 $objname = "UpdraftPlus_BackupModule_${service}";
1009 if (method_exists($objname, "download")) {
1010 $remote_obj = new $objname;
1011 return $remote_obj->download($file);
1012 } else {
1013 $updraftplus->log("Automatic backup restoration is not available with the method: $service.");
1014 $updraftplus->log("$file: ".sprintf(__("The backup archive for this file could not be found. The remote storage method in use (%s) does not allow us to retrieve files. To perform any restoration using UpdraftPlus, you will need to obtain a copy of this file and place it inside UpdraftPlus's working folder", 'updraftplus'), $service)." (".$this->prune_updraft_dir_prefix($updraftplus->backups_dir_location()).")", 'error');
1015 return false;
1016 }
1017
1018 }
1019
1020 public function updraft_ajax_handler() {
1021
1022 global $updraftplus;
1023
1024 $nonce = (empty($_REQUEST['nonce'])) ? "" : $_REQUEST['nonce'];
1025
1026 if (!wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce') || empty($_REQUEST['subaction'])) die('Security check');
1027
1028 // Mitigation in case the nonce leaked to an unauthorised user
1029 if (isset($_REQUEST['subaction']) && 'dismissautobackup' == $_REQUEST['subaction']) {
1030 if (!current_user_can('update_plugins') && !current_user_can('update_themes')) return;
1031 } elseif (isset($_REQUEST['subaction']) && ('dismissexpiry' == $_REQUEST['subaction'] || 'dismissdashnotice' == $_REQUEST['subaction'])) {
1032 if (!current_user_can('update_plugins')) return;
1033 } else {
1034 if (!UpdraftPlus_Options::user_can_manage()) return;
1035 }
1036
1037 // Some of this checks that _REQUEST['subaction'] is set, which is redundant (done already in the nonce check)
1038 /*
1039 // This one is no longer used anywhere
1040 if (isset($_REQUEST['subaction']) && 'lastlog' == $_REQUEST['subaction']) {
1041
1042 $last_message = UpdraftPlus_Options::get_updraft_option('updraft_lastmessage');
1043
1044 echo htmlspecialchars( '('.__('Nothing yet logged', 'updraftplus').')'));
1045
1046 } else
1047 */
1048 if ('forcescheduledresumption' == $_REQUEST['subaction'] && !empty($_REQUEST['resumption']) && !empty($_REQUEST['job_id']) && is_numeric($_REQUEST['resumption'])) {
1049 // Casting $resumption to int is absolutely necessary, as the WP cron system uses a hashed serialisation of the parameters for identifying jobs. Different type => different hash => does not match
1050 $resumption = (int)$_REQUEST['resumption'];
1051 $job_id = $_REQUEST['job_id'];
1052 $get_cron = $this->get_cron($job_id);
1053 if (!is_array($get_cron)) {
1054 echo json_encode(array('r' => false));
1055 } else {
1056 $updraftplus->log("Forcing resumption: job id=$job_id, resumption=$resumption");
1057 $time = $get_cron[0];
1058 // wp_unschedule_event($time, 'updraft_backup_resume', array($resumption, $job_id));
1059 wp_clear_scheduled_hook('updraft_backup_resume', array($resumption, $job_id));
1060 $updraftplus->close_browser_connection(json_encode(array('r' => true)));
1061 $updraftplus->jobdata_set_from_array($get_cron[1]);
1062 $updraftplus->backup_resume($resumption, $job_id);
1063 }
1064 } elseif (isset($_GET['subaction']) && 'activejobs_list' == $_GET['subaction']) {
1065
1066 echo json_encode($this->get_activejobs_list($_GET));
1067
1068 } elseif (isset($_REQUEST['subaction']) && 'updraftcentral_delete_key' == $_REQUEST['subaction'] && isset($_REQUEST['key_id'])) {
1069
1070 global $updraftplus_updraftcentral_main;
1071 if (!is_a($updraftplus_updraftcentral_main, 'UpdraftPlus_UpdraftCentral_Main')) {
1072 echo json_encode(array('error' => 'UpdraftPlus_UpdraftCentral_Main object not found'));
1073 die;
1074 }
1075
1076 echo json_encode($updraftplus_updraftcentral_main->delete_key($_REQUEST['key_id']));
1077 die;
1078
1079 } elseif (isset($_REQUEST['subaction']) && ('updraftcentral_create_key' == $_REQUEST['subaction'] || 'updraftcentral_get_log' == $_REQUEST['subaction'])) {
1080
1081 global $updraftplus_updraftcentral_main;
1082 if (!is_a($updraftplus_updraftcentral_main, 'UpdraftPlus_UpdraftCentral_Main')) {
1083 echo json_encode(array('error' => 'UpdraftPlus_UpdraftCentral_Main object not found'));
1084 die;
1085 }
1086
1087 $call_method = substr($_REQUEST['subaction'], 15);
1088
1089 echo json_encode(call_user_func(array($updraftplus_updraftcentral_main, $call_method), $_REQUEST));
1090
1091 die;
1092
1093 } elseif (isset($_REQUEST['subaction']) && 'callwpaction' == $_REQUEST['subaction'] && !empty($_REQUEST['wpaction'])) {
1094
1095 ob_start();
1096
1097 $res = '<em>Request received: </em>';
1098
1099 if (preg_match('/^([^:]+)+:(.*)$/', stripslashes($_REQUEST['wpaction']), $matches)) {
1100 $action = $matches[1];
1101 if (null === ($args = json_decode($matches[2], true))) {
1102 $res .= "The parameters (should be JSON) could not be decoded";
1103 $action = false;
1104 } else {
1105 $res .= "Will despatch action: ".htmlspecialchars($action).", parameters: ".htmlspecialchars(implode(',', $args));
1106 }
1107 } else {
1108 $action = $_REQUEST['wpaction'];
1109 $res .= "Will despatch action: ".htmlspecialchars($action).", no parameters";
1110 }
1111
1112 echo json_encode(array('r' => $res));
1113 $ret = ob_get_clean();
1114 $updraftplus->close_browser_connection($ret);
1115 if (!empty($action)) {
1116 if (!empty($args)) {
1117 do_action_ref_array($action, $args);
1118 } else {
1119 do_action($action);
1120 }
1121 }
1122 die;
1123 } elseif (isset($_REQUEST['subaction']) && 'whichdownloadsneeded' == $_REQUEST['subaction'] && is_array($_REQUEST['downloads']) && isset($_REQUEST['timestamp']) && is_numeric($_REQUEST['timestamp'])) {
1124 // The purpose of this is to look at the list of indicated downloads, and indicate which are not already fully downloaded. i.e. Which need further action.
1125 $send_back = array();
1126
1127 $backup = $updraftplus->get_backup_history($_REQUEST['timestamp']);
1128 $updraft_dir = $updraftplus->backups_dir_location();
1129 $backupable_entities = $updraftplus->get_backupable_file_entities();
1130
1131 if (empty($backup)) {
1132 echo json_encode(array('result' => 'asyouwere'));
1133 } else {
1134 foreach ($_REQUEST['downloads'] as $i => $download) {
1135 if (is_array($download) && 2 == count($download) && isset($download[0]) && isset($download[1])) {
1136 $entity = $download[0];
1137 if (('db' == $entity || isset($backupable_entities[$entity])) && isset($backup[$entity])) {
1138 $indexes = explode(',', $download[1]);
1139 $retain_string = '';
1140 foreach ($indexes as $index) {
1141 $retain = true; // default
1142 $findex = (0 == $index) ? '' : (string)$index;
1143 $files = $backup[$entity];
1144 if (!is_array($files)) $files = array($files);
1145 $size_key = $entity.$findex.'-size';
1146 if (isset($files[$index]) && isset($backup[$size_key])) {
1147 $file = $updraft_dir.'/'.$files[$index];
1148 if (file_exists($file) && filesize($file) >= $backup[$size_key]) {
1149 $retain = false;
1150 }
1151 }
1152 if ($retain) {
1153 $retain_string .= ('' === $retain_string) ? $index : ','.$index;
1154 $send_back[$i][0] = $entity;
1155 $send_back[$i][1] = $retain_string;
1156 }
1157 }
1158 } else {
1159 $send_back[$i][0] = $entity;
1160 $send_back[$i][1] = $download[$i][1];
1161 }
1162 } else {
1163 // Format not understood. Just send it back as-is.
1164 $send_back[$i] = $download[$i];
1165 }
1166 }
1167 // Finally, renumber the keys (to usual PHP style - 0, 1, ...). Otherwise, in order to preserve the indexes, json_encode() will create an object instead of an array in the case where $send_back only has one element (and is indexed with an index > 0)
1168 $send_back = array_values($send_back);
1169 echo json_encode(array('downloads' => $send_back));
1170 }
1171 } elseif (isset($_REQUEST['subaction']) && 'httpget' == $_REQUEST['subaction']) {
1172 if (empty($_REQUEST['uri'])) {
1173 echo json_encode(array('r' => ''));
1174 die;
1175 }
1176 $uri = $_REQUEST['uri'];
1177 if (!empty($_REQUEST['curl'])) {
1178 if (!function_exists('curl_exec')) {
1179 echo json_encode(array('e' => 'No Curl installed'));
1180 die;
1181 }
1182 $ch = curl_init();
1183 curl_setopt($ch, CURLOPT_URL, $uri);
1184 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
1185 curl_setopt($ch, CURLOPT_FAILONERROR, true);
1186 curl_setopt($ch, CURLOPT_HEADER, true);
1187 curl_setopt($ch, CURLOPT_VERBOSE, true);
1188 curl_setopt($ch, CURLOPT_STDERR, $output=fopen('php://temp', "w+"));
1189 $response = curl_exec($ch);
1190 $error = curl_error($ch);
1191 $getinfo = curl_getinfo($ch);
1192 curl_close($ch);
1193 $resp = array();
1194 if (false === $response) {
1195 $resp['e'] = htmlspecialchars($error);
1196 # json_encode(array('e' => htmlspecialchars($error)));
1197 }
1198 $resp['r'] = (empty($response)) ? '' : htmlspecialchars(substr($response, 0, 2048));
1199 rewind($output);
1200 $verb = stream_get_contents($output);
1201 if (!empty($verb)) $resp['r'] = htmlspecialchars($verb)."\n\n".$resp['r'];
1202 echo json_encode($resp);
1203 // echo json_encode(array('r' => htmlspecialchars(substr($response, 0, 2048))));
1204 } else {
1205 $response = wp_remote_get($uri, array('timeout' => 10));
1206 if (is_wp_error($response)) {
1207 echo json_encode(array('e' => htmlspecialchars($response->get_error_message())));
1208 die;
1209 }
1210 echo json_encode(array('r' => $response['response']['code'].': '.htmlspecialchars(substr($response['body'], 0, 2048))));
1211 }
1212 die;
1213 } elseif (isset($_REQUEST['subaction']) && 'dismissautobackup' == $_REQUEST['subaction']) {
1214 UpdraftPlus_Options::update_updraft_option('updraftplus_dismissedautobackup', time() + 84*86400);
1215 } elseif (isset($_REQUEST['subaction']) && 'set_autobackup_default' == $_REQUEST['subaction']) {
1216 // This option when set should have integers, not bools
1217 $default = empty($_REQUEST['default']) ? 0 : 1;
1218 UpdraftPlus_Options::update_updraft_option('updraft_autobackup_default', $default);
1219 } elseif (isset($_REQUEST['subaction']) && 'dismissexpiry' == $_REQUEST['subaction']) {
1220 UpdraftPlus_Options::update_updraft_option('updraftplus_dismissedexpiry', time() + 14*86400);
1221 } elseif (isset($_REQUEST['subaction']) && 'dismissdashnotice' == $_REQUEST['subaction']) {
1222 UpdraftPlus_Options::update_updraft_option('updraftplus_dismisseddashnotice', time() + 366*86400);
1223 } elseif (isset($_REQUEST['subaction']) && 'poplog' == $_REQUEST['subaction']){
1224
1225 echo json_encode($this->fetch_log($_REQUEST['backup_nonce']));
1226
1227 } elseif (isset($_REQUEST['subaction']) && 'restore_alldownloaded' == $_REQUEST['subaction'] && isset($_REQUEST['restoreopts']) && isset($_REQUEST['timestamp'])) {
1228
1229 $backups = $updraftplus->get_backup_history();
1230 $updraft_dir = $updraftplus->backups_dir_location();
1231
1232 $timestamp = (int)$_REQUEST['timestamp'];
1233 if (!isset($backups[$timestamp])) {
1234 echo json_encode(array('m' => '', 'w' => '', 'e' => __('No such backup set exists', 'updraftplus')));
1235 die;
1236 }
1237
1238 $mess = array();
1239 parse_str(stripslashes($_REQUEST['restoreopts']), $res);
1240
1241 if (isset($res['updraft_restore'])) {
1242
1243 set_error_handler(array($this, 'get_php_errors'), E_ALL & ~E_STRICT);
1244
1245 $elements = array_flip($res['updraft_restore']);
1246
1247 $warn = array(); $err = array();
1248
1249 @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
1250 $max_execution_time = (int)@ini_get('max_execution_time');
1251
1252 if ($max_execution_time>0 && $max_execution_time<61) {
1253 $warn[] = sprintf(__('The PHP setup on this webserver allows only %s seconds for PHP to run, and does not allow this limit to be raised. If you have a lot of data to import, and if the restore operation times out, then you will need to ask your web hosting company for ways to raise this limit (or attempt the restoration piece-by-piece).', 'updraftplus'), $max_execution_time);
1254 }
1255
1256 if (isset($backups[$timestamp]['native']) && false == $backups[$timestamp]['native']) {
1257 $warn[] = __('This backup set was not known by UpdraftPlus to be created by the current WordPress installation, but was either found in remote storage, or was sent from a remote site.', 'updraftplus').' '.__('You should make sure that this really is a backup set intended for use on this website, before you restore (rather than a backup set of an unrelated website).', 'updraftplus');
1258 }
1259
1260 if (isset($elements['db'])) {
1261
1262 // Analyse the header of the database file + display results
1263 list ($mess2, $warn2, $err2, $info) = $updraftplus->analyse_db_file($timestamp, $res);
1264 $mess = array_merge($mess, $mess2);
1265 $warn = array_merge($warn, $warn2);
1266 $err = array_merge($err, $err2);
1267 foreach ($backups[$timestamp] as $bid => $bval) {
1268 if ('db' != $bid && 'db' == substr($bid, 0, 2) && '-size' != substr($bid, -5, 5)) {
1269 $warn[] = __('Only the WordPress database can be restored; you will need to deal with the external database manually.', 'updraftplus');
1270 break;
1271 }
1272 }
1273 }
1274
1275 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
1276 $backupable_plus_db = $backupable_entities;
1277 $backupable_plus_db['db'] = array('path' => 'path-unused', 'description' => __('Database', 'updraftplus'));
1278
1279 if (!empty($backups[$timestamp]['meta_foreign'])) {
1280 $foreign_known = apply_filters('updraftplus_accept_archivename', array());
1281 if (!is_array($foreign_known) || empty($foreign_known[$backups[$timestamp]['meta_foreign']])) {
1282 $err[] = sprintf(__('Backup created by unknown source (%s) - cannot be restored.', 'updraftplus'), $backups[$timestamp]['meta_foreign']);
1283 } else {
1284 // For some reason, on PHP 5.5 passing by reference in a single array stopped working with apply_filters_ref_array (though not with do_action_ref_array).
1285 $backupable_plus_db = apply_filters_ref_array("updraftplus_importforeign_backupable_plus_db", array($backupable_plus_db, array($foreign_known[$backups[$timestamp]['meta_foreign']], &$mess, &$warn, &$err)));
1286 }
1287 }
1288
1289 foreach ($backupable_plus_db as $type => $entity_info) {
1290 if (!isset($elements[$type])) continue;
1291 $whatwegot = $backups[$timestamp][$type];
1292 if (is_string($whatwegot)) $whatwegot = array($whatwegot);
1293 $expected_index = 0;
1294 $missing = '';
1295 ksort($whatwegot);
1296 $outof = false;
1297 foreach ($whatwegot as $index => $file) {
1298 if (preg_match('/\d+of(\d+)\.zip/', $file, $omatch)) { $outof = max($matches[1], 1); }
1299 if ($index != $expected_index) {
1300 $missing .= ($missing == '') ? (1+$expected_index) : ",".(1+$expected_index);
1301 }
1302 if (!file_exists($updraft_dir.'/'.$file)) {
1303 $err[] = sprintf(__('File not found (you need to upload it): %s', 'updraftplus'), $updraft_dir.'/'.$file);
1304 } elseif (filesize($updraft_dir.'/'.$file) == 0) {
1305 $err[] = sprintf(__('File was found, but is zero-sized (you need to re-upload it): %s', 'updraftplus'), $file);
1306 } else {
1307 $itext = (0 == $index) ? '' : $index;
1308 if (!empty($backups[$timestamp][$type.$itext.'-size']) && $backups[$timestamp][$type.$itext.'-size'] != filesize($updraft_dir.'/'.$file)) {
1309 if (empty($warn['doublecompressfixed'])) {
1310 $warn[] = sprintf(__('File (%s) was found, but has a different size (%s) from what was expected (%s) - it may be corrupt.', 'updraftplus'), $file, filesize($updraft_dir.'/'.$file), $backups[$timestamp][$type.$itext.'-size']);
1311 }
1312 }
1313 do_action_ref_array("updraftplus_checkzip_$type", array($updraft_dir.'/'.$file, &$mess, &$warn, &$err));
1314 }
1315 $expected_index++;
1316 }
1317 do_action_ref_array("updraftplus_checkzip_end_$type", array(&$mess, &$warn, &$err));
1318 // Detect missing archives where they are missing from the end of the set
1319 if ($outof>0 && $expected_index < $outof) {
1320 for ($j = $expected_index; $j<$outof; $j++) {
1321 $missing .= ($missing == '') ? (1+$j) : ",".(1+$j);
1322 }
1323 }
1324 if ('' != $missing) {
1325 $warn[] = sprintf(__("This multi-archive backup set appears to have the following archives missing: %s", 'updraftplus'), $missing.' ('.$entity_info['description'].')');
1326 }
1327 }
1328
1329 if (0 == count($err) && 0 == count($warn)) {
1330 $mess_first = __('The backup archive files have been successfully processed. Now press Restore again to proceed.', 'updraftplus');
1331 } elseif (0 == count($err)) {
1332 $mess_first = __('The backup archive files have been processed, but with some warnings. If all is well, then now press Restore again to proceed. Otherwise, cancel and correct any problems first.', 'updraftplus');
1333 } else {
1334 $mess_first = __('The backup archive files have been processed, but with some errors. You will need to cancel and correct any problems before retrying.', 'updraftplus');
1335 }
1336
1337 if (count($this->logged) >0) {
1338 foreach ($this->logged as $lwarn) $warn[] = $lwarn;
1339 }
1340 restore_error_handler();
1341
1342 // Get the info if it hasn't already come from the DB scan
1343 if (!isset($info) || !is_array($info)) $info = array();
1344
1345 // Not all chracters can be json-encoded, and we don't need this potentially-arbitrary user-supplied info.
1346 unset($info['label']);
1347
1348 if (!isset($info['created_by_version']) && !empty($backups[$timestamp]['created_by_version'])) $info['created_by_version'] = $backups[$timestamp]['created_by_version'];
1349 if (empty($info['multisite']) && !empty($backups[$timestamp]['is_multisite'])) $info['multisite'] = $backups[$timestamp]['is_multisite'];
1350
1351 do_action_ref_array('updraftplus_restore_all_downloaded_postscan', array($backups, $timestamp, $elements, &$info, &$mess, &$warn, &$err));
1352
1353 echo json_encode(array('m' => '<p>'.$mess_first.'</p>'.implode('<br>', $mess), 'w' => implode('<br>', $warn), 'e' => implode('<br>', $err), 'i' => json_encode($info)));
1354 }
1355 } elseif ('sid_reset' == $_REQUEST['subaction']) {
1356
1357 delete_site_option('updraftplus-addons_siteid');
1358 echo json_encode(array('newsid' => $updraftplus->siteid()));
1359
1360 } elseif (('vault_connect' == $_REQUEST['subaction'] && isset($_REQUEST['email']) && isset($_REQUEST['pass'])) || 'vault_disconnect' == $_REQUEST['subaction'] || 'vault_recountquota' == $_REQUEST['subaction']) {
1361
1362 require_once(UPDRAFTPLUS_DIR.'/methods/updraftvault.php');
1363 $vault = new UpdraftPlus_BackupModule_updraftvault();
1364 call_user_func(array($vault, 'ajax_'.$_REQUEST['subaction']));
1365
1366 } elseif (isset($_POST['backup_timestamp']) && 'deleteset' == $_REQUEST['subaction']) {
1367
1368 echo json_encode($this->delete_set($_POST));
1369
1370 } elseif ('rawbackuphistory' == $_REQUEST['subaction']) {
1371
1372 echo '<h3 id="ud-debuginfo-rawbackups">'.__('Known backups (raw)', 'updraftplus').'</h3><pre>';
1373 var_dump($updraftplus->get_backup_history());
1374 echo '</pre>';
1375
1376 echo '<h3 id="ud-debuginfo-files">Files</h3><pre>';
1377 $updraft_dir = $updraftplus->backups_dir_location();
1378 $raw_output = array();
1379 $d = dir($updraft_dir);
1380 while (false !== ($entry = $d->read())) {
1381 $fp = $updraft_dir.'/'.$entry;
1382 $mtime = filemtime($fp);
1383 if (is_dir($fp)) {
1384 $size = ' d';
1385 } elseif (is_link($fp)) {
1386 $size = ' l';
1387 } elseif (is_file($fp)) {
1388 $size = sprintf("%8.1f", round(filesize($fp)/1024, 1)).' '.gmdate('r', $mtime);
1389 } else {
1390 $size = ' ?';
1391 }
1392 if (preg_match('/^log\.(.*)\.txt$/', $entry, $lmatch)) $entry = '<a target="_top" href="?action=downloadlog&page=updraftplus&updraftplus_backup_nonce='.htmlspecialchars($lmatch[1]).'">'.$entry.'</a>';
1393 $raw_output[$mtime] = empty($raw_output[$mtime]) ? sprintf("%s %s\n", $size, $entry) : $raw_output[$mtime].sprintf("%s %s\n", $size, $entry);
1394 }
1395 @$d->close();
1396 krsort($raw_output, SORT_NUMERIC);
1397 foreach ($raw_output as $line) echo $line;
1398 echo '</pre>';
1399
1400 echo '<h3 id="ud-debuginfo-options">'.__('Options (raw)', 'updraftplus').'</h3>';
1401 $opts = $updraftplus->get_settings_keys();
1402 asort($opts);
1403 // <tr><th>'.__('Key','updraftplus').'</th><th>'.__('Value','updraftplus').'</th></tr>
1404 echo '<table><thead></thead><tbody>';
1405 foreach ($opts as $opt) {
1406 echo '<tr><td>'.htmlspecialchars($opt).'</td><td>'.htmlspecialchars(print_r(UpdraftPlus_Options::get_updraft_option($opt), true)).'</td>';
1407 }
1408 echo '</tbody></table>';
1409
1410 do_action('updraftplus_showrawinfo');
1411
1412
1413 } elseif ('countbackups' == $_REQUEST['subaction']) {
1414 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1415 $backup_history = (is_array($backup_history))?$backup_history:array();
1416 #echo sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history));
1417 echo __('Existing Backups', 'updraftplus').' ('.count($backup_history).')';
1418 } elseif ('ping' == $_REQUEST['subaction']) {
1419 // The purpose of this is to detect brokenness caused by extra line feeds in plugins/themes - before it breaks other AJAX operations and leads to support requests
1420 echo 'pong';
1421 } elseif ('checkoverduecrons' == $_REQUEST['subaction']) {
1422 $how_many_overdue = $this->howmany_overdue_crons();
1423 if ($how_many_overdue >= 4) echo json_encode(array('m' => $this->show_admin_warning_overdue_crons($how_many_overdue)));
1424 } elseif ('delete_old_dirs' == $_REQUEST['subaction']) {
1425 $this->delete_old_dirs_go(false);
1426 } elseif ('phpinfo' == $_REQUEST['subaction']) {
1427 phpinfo(INFO_ALL ^ (INFO_CREDITS | INFO_LICENSE));
1428
1429 echo '<h3 id="ud-debuginfo-constants">'.__('Constants', 'updraftplus').'</h3>';
1430 $opts = @get_defined_constants();
1431 ksort($opts);
1432 // <tr><th>'.__('Key','updraftplus').'</th><th>'.__('Value','updraftplus').'</th></tr>
1433 echo '<table><thead></thead><tbody>';
1434 foreach ($opts as $key => $opt) {
1435 echo '<tr><td>'.htmlspecialchars($key).'</td><td>'.htmlspecialchars(print_r($opt, true)).'</td>';
1436 }
1437 echo '</tbody></table>';
1438
1439 } elseif ('doaction' == $_REQUEST['subaction'] && !empty($_REQUEST['subsubaction']) && 'updraft_' == substr($_REQUEST['subsubaction'], 0, 8)) {
1440 do_action($_REQUEST['subsubaction']);
1441 } elseif ('backupnow' == $_REQUEST['subaction']) {
1442
1443 $this->request_backupnow($_REQUEST);
1444
1445 # Old-style: schedule an event in 5 seconds time. This has the advantage of testing out the scheduler, and alerting the user if it doesn't work... but has the disadvantage of not working in that case.
1446 # I don't think the </div>s should be here - in case this is ever re-activated
1447 // if (wp_schedule_single_event(time()+5, $event, array($backupnow_nocloud)) === false) {
1448 // $updraftplus->log("A backup run failed to schedule");
1449 // echo __("Failed.", 'updraftplus');
1450 // } else {
1451 // echo htmlspecialchars(__('OK. You should soon see activity in the "Last log message" field below.','updraftplus'))." <a href=\"https://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/\"><br>".__('Nothing happening? Follow this link for help.','updraftplus')."</a>";
1452 // $updraftplus->log("A backup run has been scheduled");
1453 // }
1454
1455 } elseif (isset($_GET['subaction']) && 'lastbackup' == $_GET['subaction']) {
1456 echo $this->last_backup_html();
1457 } elseif (isset($_GET['subaction']) && 'activejobs_delete' == $_GET['subaction'] && isset($_GET['jobid'])) {
1458
1459 echo json_encode($this->activejobs_delete((string)$_GET['jobid']));
1460
1461 } elseif (isset($_GET['subaction']) && 'diskspaceused' == $_GET['subaction'] && isset($_GET['entity'])) {
1462 $entity = $_GET['entity'];
1463 // This can count either the size of the Updraft directory, or of the data to be backed up
1464 echo $this->get_disk_space_used($entity);
1465 } elseif (isset($_GET['subaction']) && 'historystatus' == $_GET['subaction']) {
1466 $remotescan = !empty($_GET['remotescan']);
1467 $rescan = ($remotescan || !empty($_GET['rescan']));
1468
1469 $history_status = $this->get_history_status($rescan, $remotescan);
1470 echo @json_encode($history_status);
1471
1472 } elseif (isset($_POST['subaction']) && $_POST['subaction'] == 'credentials_test') {
1473
1474 $this->do_credentials_test($_POST);
1475 die;
1476
1477 }
1478 die;
1479
1480 }
1481
1482 // This echoes output; so, you will need to do output buffering if you want to capture it
1483 public function do_credentials_test($test_settings) {
1484
1485 $method = (!empty($test_settings['method']) && preg_match("/^[a-z0-9]+$/", $test_settings['method'])) ? $test_settings['method'] : "";
1486
1487 $objname = "UpdraftPlus_BackupModule_$method";
1488
1489 $this->logged = array();
1490 # TODO: Add action for WP HTTP SSL stuff
1491 set_error_handler(array($this, 'get_php_errors'), E_ALL & ~E_STRICT);
1492
1493 if (!class_exists($objname)) include_once(UPDRAFTPLUS_DIR."/methods/$method.php");
1494
1495 # TODO: Add action for WP HTTP SSL stuff
1496 if (method_exists($objname, "credentials_test")) {
1497 $obj = new $objname;
1498 $obj->credentials_test($test_settings);
1499 }
1500
1501 if (count($this->logged) >0) {
1502 echo "\n\n".__('Messages:', 'updraftplus')."\n";
1503 foreach ($this->logged as $err) {
1504 echo "* $err\n";
1505 }
1506 }
1507 restore_error_handler();
1508 }
1509
1510 // Relevant options (array keys): backup_timestamp, delete_remote,
1511 public function delete_set($opts) {
1512
1513 global $updraftplus;
1514
1515 $backups = $updraftplus->get_backup_history();
1516 $timestamps = (string)$opts['backup_timestamp'];
1517
1518 $timestamps = explode(',', $timestamps);
1519 $delete_remote = empty($opts['delete_remote']) ? false : true;
1520
1521 // You need a nonce before you can set job data. And we certainly don't yet have one.
1522 $updraftplus->backup_time_nonce();
1523 // Set the job type before logging, as there can be different logging destinations
1524 $updraftplus->jobdata_set('job_type', 'delete');
1525 $updraftplus->jobdata_set('job_time_ms', $updraftplus->job_time_ms);
1526
1527 if (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
1528 $updraftplus->logfile_open($updraftplus->nonce);
1529 set_error_handler(array($updraftplus, 'php_error'), E_ALL & ~E_STRICT);
1530 }
1531
1532 $updraft_dir = $updraftplus->backups_dir_location();
1533 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
1534
1535 $local_deleted = 0;
1536 $remote_deleted = 0;
1537 $sets_removed = 0;
1538
1539 foreach ($timestamps as $i => $timestamp) {
1540
1541 if (!isset($backups[$timestamp])) {
1542 echo json_encode(array('result' => 'error', 'message' => __('Backup set not found', 'updraftplus')));
1543 die;
1544 }
1545
1546 $nonce = isset($backups[$timestamp]['nonce']) ? $backups[$timestamp]['nonce'] : '';
1547
1548 $delete_from_service = array();
1549
1550 if ($delete_remote) {
1551 // Locate backup set
1552 if (isset($backups[$timestamp]['service'])) {
1553 $services = is_string($backups[$timestamp]['service']) ? array($backups[$timestamp]['service']) : $backups[$timestamp]['service'];
1554 if (is_array($services)) {
1555 foreach ($services as $service) {
1556 if ($service && $service != 'none' && $service != 'email') $delete_from_service[] = $service;
1557 }
1558 }
1559 }
1560 }
1561
1562 $files_to_delete = array();
1563 foreach ($backupable_entities as $key => $ent) {
1564 if (isset($backups[$timestamp][$key])) {
1565 $files_to_delete[$key] = $backups[$timestamp][$key];
1566 }
1567 }
1568 // Delete DB
1569 if (isset($backups[$timestamp]['db'])) $files_to_delete['db'] = $backups[$timestamp]['db'];
1570
1571 // Also delete the log
1572 if ($nonce && !UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
1573 $files_to_delete['log'] = "log.$nonce.txt";
1574 }
1575
1576 unset($backups[$timestamp]);
1577 $sets_removed++;
1578 UpdraftPlus_Options::update_updraft_option('updraft_backup_history', $backups);
1579
1580 add_action('http_request_args', array($updraftplus, 'modify_http_options'));
1581 foreach ($files_to_delete as $key => $files) {
1582 # Local deletion
1583 if (is_string($files)) $files=array($files);
1584 foreach ($files as $file) {
1585 if (is_file($updraft_dir.'/'.$file)) {
1586 if (@unlink($updraft_dir.'/'.$file)) $local_deleted++;
1587 }
1588 }
1589 if ('log' != $key && count($delete_from_service) > 0) {
1590 foreach ($delete_from_service as $service) {
1591 if ('email' == $service) continue;
1592 if (file_exists(UPDRAFTPLUS_DIR."/methods/$service.php")) require_once(UPDRAFTPLUS_DIR."/methods/$service.php");
1593 $objname = "UpdraftPlus_BackupModule_".$service;
1594 $deleted = -1;
1595 if (class_exists($objname)) {
1596 # TODO: Re-use the object (i.e. prevent repeated connection setup/teardown)
1597 $remote_obj = new $objname;
1598 $deleted = $remote_obj->delete($files);
1599 }
1600 if ($deleted === -1) {
1601 //echo __('Did not know how to delete from this cloud service.', 'updraftplus');
1602 } elseif ($deleted !== false) {
1603 $remote_deleted = $remote_deleted + count($files);
1604 } else {
1605 // Do nothing
1606 }
1607 }
1608 }
1609 }
1610 remove_action('http_request_args', array($updraftplus, 'modify_http_options'));
1611 }
1612
1613
1614 $message = sprintf(__('Backup sets removed: %d', 'updraftplus'),$sets_removed)."\n";
1615
1616 $message .= sprintf(__('Local archives deleted: %d', 'updraftplus'),$local_deleted)."\n";
1617 $message .= sprintf(__('Remote archives deleted: %d', 'updraftplus'),$remote_deleted)."\n";
1618
1619 $updraftplus->log("Local archives deleted: ".$local_deleted);
1620 $updraftplus->log("Remote archives deleted: ".$remote_deleted);
1621
1622 if (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
1623 restore_error_handler();
1624 }
1625
1626 return array('result' => 'success', 'message' => $message, 'removed' => array('sets' => $sets_removed, 'local' => $local_deleted, 'remote' => $remote_deleted));
1627
1628 }
1629
1630 public function get_history_status($rescan, $remotescan) {
1631
1632 global $updraftplus;
1633
1634 if ($rescan) $messages = $updraftplus->rebuild_backup_history($remotescan);
1635
1636 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1637 $backup_history = (is_array($backup_history)) ? $backup_history : array();
1638 $output = $this->existing_backup_table($backup_history);
1639
1640 if (!empty($messages) && is_array($messages)) {
1641 $noutput = '<div style="margin-left: 100px; margin-top: 10px;"><ul style="list-style: disc inside;">';
1642 foreach ($messages as $msg) {
1643 $noutput .= '<li>'.(($msg['desc']) ? $msg['desc'].': ' : '').'<em>'.$msg['message'].'</em></li>';
1644 }
1645 $noutput .= '</ul></div>';
1646 $output = $noutput.$output;
1647 }
1648
1649 $logs_exist = (false !== strpos($output, 'downloadlog'));
1650 if (!$logs_exist) {
1651 list($mod_time, $log_file, $nonce) = $updraftplus->last_modified_log();
1652 if ($mod_time) $logs_exist = true;
1653 }
1654
1655 return apply_filters('updraftplus_get_history_status_result', array(
1656 'n' => sprintf(__('Existing Backups', 'updraftplus').' (%d)', count($backup_history)),
1657 't' => $output,
1658 'cksum' => md5($output),
1659 'logs_exist' => $logs_exist,
1660 ));
1661 }
1662
1663 public function get_disk_space_used($entity) {
1664 global $updraftplus;
1665 if ('updraft' == $entity) {
1666 return $this->recursive_directory_size($updraftplus->backups_dir_location());
1667 } else {
1668 $backupable_entities = $updraftplus->get_backupable_file_entities(true, false);
1669 if ('all' == $entity) {
1670 $total_size = 0;
1671 foreach ($backupable_entities as $entity => $data) {
1672 # Might be an array
1673 $basedir = $backupable_entities[$entity];
1674 $dirs = apply_filters('updraftplus_dirlist_'.$entity, $basedir);
1675 $size = $this->recursive_directory_size($dirs, $updraftplus->get_exclude($entity), $basedir, 'numeric');
1676 if (is_numeric($size) && $size>0) $total_size += $size;
1677 }
1678 return $updraftplus->convert_numeric_size_to_text($total_size);
1679 } elseif (!empty($backupable_entities[$entity])) {
1680 # Might be an array
1681 $basedir = $backupable_entities[$entity];
1682 $dirs = apply_filters('updraftplus_dirlist_'.$entity, $basedir);
1683 return $this->recursive_directory_size($dirs, $updraftplus->get_exclude($entity), $basedir);
1684 }
1685 }
1686 return __('Error', 'updraftplus');
1687 }
1688
1689 public function activejobs_delete($job_id) {
1690
1691 if (preg_match("/^[0-9a-f]{12}$/", $job_id)) {
1692
1693 global $updraftplus;
1694 $cron = get_option('cron');
1695 $found_it = false;
1696
1697 $updraft_dir = $updraftplus->backups_dir_location();
1698 if (file_exists($updraft_dir.'/log.'.$job_id.'.txt')) touch($updraft_dir.'/deleteflag-'.$job_id.'.txt');
1699
1700 foreach ($cron as $time => $job) {
1701 if (isset($job['updraft_backup_resume'])) {
1702 foreach ($job['updraft_backup_resume'] as $hook => $info) {
1703 if (isset($info['args'][1]) && $info['args'][1] == $job_id) {
1704 $args = $cron[$time]['updraft_backup_resume'][$hook]['args'];
1705 wp_unschedule_event($time, 'updraft_backup_resume', $args);
1706 if (!$found_it) return array('ok' => 'Y', 'c' => 'deleted', 'm' => __('Job deleted', 'updraftplus'));
1707 $found_it = true;
1708 }
1709 }
1710 }
1711 }
1712 }
1713
1714 if (!$found_it) return array('ok' => 'N', 'c' => 'not_found', 'm' => __('Could not find that job - perhaps it has already finished?', 'updraftplus'));
1715
1716 }
1717
1718 // Input: an array of items
1719 // Each item is in the format: <base>,<timestamp>,<type>(,<findex>)
1720 // The 'base' is not for us: we just pass it straight back
1721 public function get_download_statuses($downloaders) {
1722 global $updraftplus;
1723 $download_status = array();
1724 foreach ($downloaders as $downloader) {
1725 # prefix, timestamp, entity, index
1726 if (preg_match('/^([^,]+),(\d+),([-a-z]+|db[0-9]+),(\d+)$/', $downloader, $matches)) {
1727 $findex = (empty($matches[4])) ? '0' : $matches[4];
1728 $updraftplus->nonce = dechex($matches[2]).$findex.substr(md5($matches[3]), 0, 3);
1729 $updraftplus->jobdata_reset();
1730 $status = $this->download_status($matches[2], $matches[3], $matches[4]);
1731 if (is_array($status)) {
1732 $status['base'] = $matches[1];
1733 $status['timestamp'] = $matches[2];
1734 $status['what'] = $matches[3];
1735 $status['findex'] = $findex;
1736 $download_status[] = $status;
1737 }
1738 }
1739 }
1740 return $download_status;
1741 }
1742
1743 public function get_activejobs_list($request) {
1744
1745 global $updraftplus;
1746
1747 $download_status = empty($request['downloaders']) ? array(): $this->get_download_statuses(explode(':', $request['downloaders']));
1748
1749 if (!empty($request['oneshot'])) {
1750 $job_id = get_site_option('updraft_oneshotnonce', false);
1751 // print_active_job() for one-shot jobs that aren't in cron
1752 $active_jobs = (false === $job_id) ? '' : $this->print_active_job($job_id, true);
1753 } elseif (!empty($request['thisjobonly'])) {
1754 // print_active_jobs() is for resumable jobs where we want the cron info to be included in the output
1755 $active_jobs = $this->print_active_jobs($request['thisjobonly']);
1756 } else {
1757 $active_jobs = $this->print_active_jobs();
1758 }
1759
1760 $logupdate_array = array();
1761 if (!empty($request['log_fetch'])) {
1762 if (isset($request['log_nonce'])) {
1763 $log_nonce = $request['log_nonce'];
1764 $log_pointer = isset($request['log_pointer']) ? absint($request['log_pointer']) : 0;
1765 $logupdate_array = $this->fetch_log($log_nonce, $log_pointer);
1766 }
1767 }
1768
1769 return array(
1770 // We allow the front-end to decide what to do if there's nothing logged - we used to (up to 1.11.29) send a pre-defined message
1771 'l' => htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', '')),
1772 'j' => $active_jobs,
1773 'ds' => $download_status,
1774 'u' => $logupdate_array
1775 );
1776
1777 }
1778
1779 public function request_backupnow($request, $close_connection_callable = false) {
1780 global $updraftplus;
1781
1782 $backupnow_nocloud = (empty($request['backupnow_nocloud'])) ? false : true;
1783 $event = (!empty($request['backupnow_nofiles'])) ? 'updraft_backupnow_backup_database' : ((!empty($request['backupnow_nodb'])) ? 'updraft_backupnow_backup' : 'updraft_backupnow_backup_all');
1784
1785 // The call to backup_time_nonce() allows us to know the nonce in advance, and return it
1786 $nonce = $updraftplus->backup_time_nonce();
1787
1788 $msg = array(
1789 'nonce' => $nonce,
1790 'm' => '<strong>'.__('Start backup', 'updraftplus').':</strong> '.htmlspecialchars(__('OK. You should soon see activity in the "Last log message" field below.','updraftplus'))
1791 );
1792
1793 if ($close_connection_callable && is_callable($close_connection_callable)) {
1794 call_user_func($close_connection_callable, $msg);
1795 } else {
1796 $updraftplus->close_browser_connection(json_encode($msg));
1797 }
1798
1799 $options = array('nocloud' => $backupnow_nocloud, 'use_nonce' => $nonce);
1800 if (!empty($request['onlythisfileentity']) && is_string($request['onlythisfileentity'])) {
1801 // Something to see in the 'last log' field when it first appears, before the backup actually starts
1802 $updraftplus->log(__('Start backup','updraftplus'));
1803 $options['restrict_files_to_override'] = explode(',', $request['onlythisfileentity']);
1804 }
1805
1806 if (!empty($request['extradata'])) {
1807 $options['extradata'] = $request['extradata'];
1808 }
1809
1810 do_action($event, apply_filters('updraft_backupnow_options', $options, $request));
1811 }
1812
1813 public function fetch_log($backup_nonce, $log_pointer=0) {
1814 global $updraftplus;
1815
1816 if (empty($backup_nonce)) {
1817 list($mod_time, $log_file, $nonce) = $updraftplus->last_modified_log();
1818 } else {
1819 $nonce = $backup_nonce;
1820 }
1821
1822 if (!preg_match('/^[0-9a-f]+$/', $nonce)) die('Security check');
1823
1824 $log_content = '';
1825 $new_pointer = $log_pointer;
1826
1827 if (!empty($nonce)) {
1828 $updraft_dir = $updraftplus->backups_dir_location();
1829
1830 $potential_log_file = $updraft_dir."/log.".$nonce.".txt";
1831
1832 if (is_readable($potential_log_file)){
1833
1834 $templog_array = array();
1835 $log_file = fopen($potential_log_file, "r");
1836 if ($log_pointer > 0) fseek($log_file, $log_pointer);
1837
1838 while (($buffer = fgets($log_file, 4096)) !== false) {
1839 $templog_array[] = $buffer;
1840 }
1841 if (!feof($log_file)) {
1842 $templog_array[] = __('Error: unexpected file read fail', 'updraftplus');
1843 }
1844
1845 $new_pointer = ftell($log_file);
1846 $log_content = implode("", $templog_array);
1847
1848 } else {
1849 $log_content .= __('The log file could not be read.','updraftplus');
1850 }
1851
1852 } else {
1853 $log_content .= __('The log file could not be read.','updraftplus');
1854 }
1855
1856 $ret_array = array(
1857 'html' => $log_content,
1858 'nonce' => $nonce,
1859 'pointer' => $new_pointer
1860 );
1861
1862 return $ret_array;
1863 }
1864
1865 public function howmany_overdue_crons() {
1866 $how_many_overdue = 0;
1867 if (function_exists('_get_cron_array') || (is_file(ABSPATH.WPINC.'/cron.php') && include_once(ABSPATH.WPINC.'/cron.php') && function_exists('_get_cron_array'))) {
1868 $crons = _get_cron_array();
1869 if (is_array($crons)) {
1870 $timenow = time();
1871 foreach ($crons as $jt => $job) {
1872 if ($jt < $timenow) {
1873 $how_many_overdue++;
1874 }
1875 }
1876 }
1877 }
1878 return $how_many_overdue;
1879 }
1880
1881 public function get_php_errors($errno, $errstr, $errfile, $errline) {
1882 global $updraftplus;
1883 if (0 == error_reporting()) return true;
1884 $logline = $updraftplus->php_error_to_logline($errno, $errstr, $errfile, $errline);
1885 if (false !== $logline) $this->logged[] = $logline;
1886 # Don't pass it up the chain (since it's going to be output to the user always)
1887 return true;
1888 }
1889
1890 private function download_status($timestamp, $type, $findex) {
1891 global $updraftplus;
1892 $response = array( 'm' => $updraftplus->jobdata_get('dlmessage_'.$timestamp.'_'.$type.'_'.$findex).'<br>' );
1893 if ($file = $updraftplus->jobdata_get('dlfile_'.$timestamp.'_'.$type.'_'.$findex)) {
1894 if ('failed' == $file) {
1895 $response['e'] = __('Download failed', 'updraftplus').'<br>';
1896 $response['failed'] = true;
1897 $errs = $updraftplus->jobdata_get('dlerrors_'.$timestamp.'_'.$type.'_'.$findex);
1898 if (is_array($errs) && !empty($errs)) {
1899 $response['e'] .= '<ul class="disc">';
1900 foreach ($errs as $err) {
1901 if (is_array($err)) {
1902 $response['e'] .= '<li>'.htmlspecialchars($err['message']).'</li>';
1903 } else {
1904 $response['e'] .= '<li>'.htmlspecialchars($err).'</li>';
1905 }
1906 }
1907 $response['e'] .= '</ul>';
1908 }
1909 } elseif (preg_match('/^downloaded:(\d+):(.*)$/', $file, $matches) && file_exists($matches[2])) {
1910 $response['p'] = 100;
1911 $response['f'] = $matches[2];
1912 $response['s'] = (int)$matches[1];
1913 $response['t'] = (int)$matches[1];
1914 $response['m'] = __('File ready.', 'updraftplus');
1915 } elseif (preg_match('/^downloading:(\d+):(.*)$/', $file, $matches) && file_exists($matches[2])) {
1916 // Convert to bytes
1917 $response['f'] = $matches[2];
1918 $total_size = (int)max($matches[1], 1);
1919 $cur_size = filesize($matches[2]);
1920 $response['s'] = $cur_size;
1921 $file_age = time() - filemtime($matches[2]);
1922 if ($file_age > 20) $response['a'] = time() - filemtime($matches[2]);
1923 $response['t'] = $total_size;
1924 $response['m'] .= __("Download in progress", 'updraftplus').' ('.round($cur_size/1024).' / '.round(($total_size/1024)).' KB)';
1925 $response['p'] = round(100*$cur_size/$total_size);
1926 } else {
1927 $response['m'] .= __('No local copy present.', 'updraftplus');
1928 $response['p'] = 0;
1929 $response['s'] = 0;
1930 $response['t'] = 1;
1931 }
1932 }
1933 return $response;
1934 }
1935
1936 public function upload_dir($uploads) {
1937 global $updraftplus;
1938 $updraft_dir = $updraftplus->backups_dir_location();
1939 if (is_writable($updraft_dir)) $uploads['path'] = $updraft_dir;
1940 return $uploads;
1941 }
1942
1943 // We do actually want to over-write
1944 public function unique_filename_callback($dir, $name, $ext) {
1945 return $name.$ext;
1946 }
1947
1948 public function sanitize_file_name($filename) {
1949 // WordPress 3.4.2 on multisite (at least) adds in an unwanted underscore
1950 return preg_replace('/-db(.*)\.gz_\.crypt$/', '-db$1.gz.crypt', $filename);
1951 }
1952
1953 public function plupload_action() {
1954 // check ajax nonce
1955
1956 global $updraftplus;
1957 @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
1958
1959 if (!UpdraftPlus_Options::user_can_manage()) exit;
1960 check_ajax_referer('updraft-uploader');
1961
1962 $updraft_dir = $updraftplus->backups_dir_location();
1963 if (!@$updraftplus->really_is_writable($updraft_dir)) {
1964 echo json_encode(array('e' => sprintf(__("Backup directory (%s) is not writable, or does not exist.", 'updraftplus'), $updraft_dir).' '.__('You will find more information about this in the Settings section.', 'updraftplus')));
1965 exit;
1966 }
1967
1968 add_filter('upload_dir', array($this, 'upload_dir'));
1969 add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
1970 // handle file upload
1971
1972 $farray = array('test_form' => true, 'action' => 'plupload_action');
1973
1974 $farray['test_type'] = false;
1975 $farray['ext'] = 'x-gzip';
1976 $farray['type'] = 'application/octet-stream';
1977
1978 if (!isset($_POST['chunks'])) {
1979 $farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
1980 }
1981
1982 $status = wp_handle_upload(
1983 $_FILES['async-upload'],
1984 $farray
1985 );
1986 remove_filter('upload_dir', array($this, 'upload_dir'));
1987 remove_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
1988
1989 if (isset($status['error'])) {
1990 echo json_encode(array('e' => $status['error']));
1991 exit;
1992 }
1993
1994 // If this was the chunk, then we should instead be concatenating onto the final file
1995 if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
1996 $final_file = basename($_POST['name']);
1997 if (!rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp')) {
1998 @unlink($status['file']);
1999 echo json_encode(array('e' => sprintf(__('Error: %s', 'updraftplus'), __('This file could not be uploaded', 'updraftplus'))));
2000 exit;
2001 }
2002 $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
2003
2004 // Final chunk? If so, then stich it all back together
2005 if ($_POST['chunk'] == $_POST['chunks']-1) {
2006 if ($wh = fopen($updraft_dir.'/'.$final_file, 'wb')) {
2007 for ($i=0 ; $i<$_POST['chunks']; $i++) {
2008 $rf = $updraft_dir.'/'.$final_file.'.'.$i.'.zip.tmp';
2009 if ($rh = fopen($rf, 'rb')) {
2010 while ($line = fread($rh, 32768)) fwrite($wh, $line);
2011 fclose($rh);
2012 @unlink($rf);
2013 }
2014 }
2015 fclose($wh);
2016 $status['file'] = $updraft_dir.'/'.$final_file;
2017 if ('.tar' == substr($final_file, -4, 4)) {
2018 if (file_exists($status['file'].'.gz')) unlink($status['file'].'.gz');
2019 if (file_exists($status['file'].'.bz2')) unlink($status['file'].'.bz2');
2020 } elseif ('.tar.gz' == substr($final_file, -7, 7)) {
2021 if (file_exists(substr($status['file'], 0, strlen($status['file'])-3))) unlink(substr($status['file'], 0, strlen($status['file'])-3));
2022 if (file_exists(substr($status['file'], 0, strlen($status['file'])-3).'.bz2')) unlink(substr($status['file'], 0, strlen($status['file'])-3).'.bz2');
2023 } elseif ('.tar.bz2' == substr($final_file, -8, 8)) {
2024 if (file_exists(substr($status['file'], 0, strlen($status['file'])-4))) unlink(substr($status['file'], 0, strlen($status['file'])-4));
2025 if (file_exists(substr($status['file'], 0, strlen($status['file'])-4).'.gz')) unlink(substr($status['file'], 0, strlen($status['file'])-3).'.gz');
2026 }
2027 }
2028 }
2029
2030 }
2031
2032 $response = array();
2033 if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
2034 $file = basename($status['file']);
2035 if (!preg_match('/^log\.[a-f0-9]{12}\.txt/i', $file) && !preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)([0-9]+)?(\.(zip|gz|gz\.crypt))?$/i', $file, $matches)) {
2036 $accept = apply_filters('updraftplus_accept_archivename', array());
2037 if (is_array($accept)) {
2038 foreach ($accept as $acc) {
2039 if (preg_match('/'.$acc['pattern'].'/i', $file)) $accepted = $acc['desc'];
2040 }
2041 }
2042 if (!empty($accepted)) {
2043 $response['dm'] = sprintf(__('This backup was created by %s, and can be imported.', 'updraftplus'), $accepted);
2044 } else {
2045 @unlink($status['file']);
2046 echo json_encode(array('e' => sprintf(__('Error: %s', 'updraftplus'),__('Bad filename format - this does not look like a file created by UpdraftPlus','updraftplus'))));
2047 exit;
2048 }
2049 } else {
2050 $backupable_entities = $updraftplus->get_backupable_file_entities(true);
2051 $type = isset($matches[3]) ? $matches[3] : '';
2052 if (!preg_match('/^log\.[a-f0-9]{12}\.txt/', $file) && 'db' != $type && !isset($backupable_entities[$type])) {
2053 @unlink($status['file']);
2054 echo json_encode(array('e' => sprintf(__('Error: %s', 'updraftplus'),sprintf(__('This looks like a file created by UpdraftPlus, but this install does not know about this type of object: %s. Perhaps you need to install an add-on?','updraftplus'), htmlspecialchars($type)))));
2055 exit;
2056 }
2057 }
2058 }
2059
2060 // send the uploaded file url in response
2061 $response['m'] = $status['url'];
2062 echo json_encode($response);
2063 exit;
2064 }
2065
2066 # Database decrypter
2067 public function plupload_action2() {
2068
2069 @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
2070 global $updraftplus;
2071
2072 if (!UpdraftPlus_Options::user_can_manage()) exit;
2073 check_ajax_referer('updraft-uploader');
2074
2075 $updraft_dir = $updraftplus->backups_dir_location();
2076 if (!is_writable($updraft_dir)) exit;
2077
2078 add_filter('upload_dir', array($this, 'upload_dir'));
2079 add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
2080 // handle file upload
2081
2082 $farray = array( 'test_form' => true, 'action' => 'plupload_action2' );
2083
2084 $farray['test_type'] = false;
2085 $farray['ext'] = 'crypt';
2086 $farray['type'] = 'application/octet-stream';
2087
2088 if (isset($_POST['chunks'])) {
2089 // $farray['ext'] = 'zip';
2090 // $farray['type'] = 'application/zip';
2091 } else {
2092 $farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
2093 }
2094
2095 $status = wp_handle_upload(
2096 $_FILES['async-upload'],
2097 $farray
2098 );
2099 remove_filter('upload_dir', array($this, 'upload_dir'));
2100 remove_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
2101
2102 if (isset($status['error'])) {
2103 echo 'ERROR:'.$status['error'];
2104 exit;
2105 }
2106
2107 // If this was the chunk, then we should instead be concatenating onto the final file
2108 if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
2109 $final_file = basename($_POST['name']);
2110 rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
2111 $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
2112
2113 // Final chunk? If so, then stich it all back together
2114 if ($_POST['chunk'] == $_POST['chunks']-1) {
2115 if ($wh = fopen($updraft_dir.'/'.$final_file, 'wb')) {
2116 for ($i=0 ; $i<$_POST['chunks']; $i++) {
2117 $rf = $updraft_dir.'/'.$final_file.'.'.$i.'.zip.tmp';
2118 if ($rh = fopen($rf, 'rb')) {
2119 while ($line = fread($rh, 32768)) fwrite($wh, $line);
2120 fclose($rh);
2121 @unlink($rf);
2122 }
2123 }
2124 fclose($wh);
2125 $status['file'] = $updraft_dir.'/'.$final_file;
2126 }
2127 }
2128
2129 }
2130
2131 if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
2132 $file = basename($status['file']);
2133 if (!preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-db([0-9]+)?\.(gz\.crypt)$/i', $file)) {
2134
2135 @unlink($status['file']);
2136 echo 'ERROR:'.__('Bad filename format - this does not look like an encrypted database file created by UpdraftPlus','updraftplus');
2137
2138 exit;
2139 }
2140 }
2141
2142 // send the uploaded file url in response
2143 // echo 'OK:'.$status['url'];
2144 echo 'OK:'.$file;
2145 exit;
2146 }
2147
2148 public function settings_header() {
2149 global $updraftplus;
2150 ?>
2151
2152 <div class="wrap" id="updraft-wrap">
2153 <h1><?php echo $updraftplus->plugin_title; ?></h1>
2154
2155 <a href="https://updraftplus.com">UpdraftPlus.Com</a> |
2156 <?php if (!defined('UPDRAFTPLUS_NOADS_B')) { ?><a href="https://updraftplus.com/shop/updraftplus-premium/"><?php _e("Premium",'updraftplus');?></a> | <?php } ?>
2157 <a href="https://updraftplus.com/news/"><?php _e('News','updraftplus');?></a> |
2158 <a href="https://twitter.com/updraftplus"><?php _e('Twitter', 'updraftplus');?></a> |
2159 <a href="https://updraftplus.com/support/"><?php _e("Support",'updraftplus');?></a> |
2160 <?php if (!is_file(UPDRAFTPLUS_DIR.'/udaddons/updraftplus-addons.php')) { ?><a href="https://updraftplus.com/newsletter-signup"><?php _e("Newsletter sign-up", 'updraftplus');?></a> | <?php } ?>
2161 <a href="http://david.dw-perspective.org.uk"><?php _e("Lead developer's homepage",'updraftplus');?></a> |
2162 <a href="https://updraftplus.com/support/frequently-asked-questions/">FAQs</a> | <a href="https://www.simbahosting.co.uk/s3/shop/"><?php _e('More plugins', 'updraftplus');?></a> - <?php _e('Version','updraftplus');?>: <?php echo $updraftplus->version; ?>
2163 <br>
2164 <?php
2165 }
2166
2167 public function settings_output() {
2168
2169 if (false == ($render = apply_filters('updraftplus_settings_page_render', true))) {
2170 do_action('updraftplus_settings_page_render_abort', $render);
2171 return;
2172 }
2173
2174 do_action('updraftplus_settings_page_init');
2175
2176 global $updraftplus;
2177
2178 /*
2179 we use request here because the initial restore is triggered by a POSTed form. we then may need to obtain credentials
2180 for the WP_Filesystem. to do this WP outputs a form, but we don't pass our parameters via that. So the values are
2181 passed back in as GET parameters.
2182 */
2183
2184 if (isset($_REQUEST['action']) && (($_REQUEST['action'] == 'updraft_restore' && isset($_REQUEST['backup_timestamp'])) || ('updraft_restore_continue' == $_REQUEST['action'] && !empty($_REQUEST['restoreid'])))) {
2185
2186 $is_continuation = ('updraft_restore_continue' == $_REQUEST['action']) ? true : false;
2187
2188 if ($is_continuation) {
2189 $restore_in_progress = get_site_option('updraft_restore_in_progress');
2190 if ($restore_in_progress != $_REQUEST['restoreid']) {
2191 $abort_restore_already = true;
2192 $updraftplus->log(__('Sufficient information about the in-progress restoration operation could not be found.', 'updraftplus').' (restoreid_mismatch)', 'error', 'restoreid_mismatch');
2193 } else {
2194
2195 $restore_jobdata = $updraftplus->jobdata_getarray($restore_in_progress);
2196 if (is_array($restore_jobdata) && isset($restore_jobdata['job_type']) && 'restore' == $restore_jobdata['job_type'] && isset($restore_jobdata['second_loop_entities']) && !empty($restore_jobdata['second_loop_entities']) && isset($restore_jobdata['job_time_ms']) && isset($restore_jobdata['backup_timestamp'])) {
2197 $backup_timestamp = $restore_jobdata['backup_timestamp'];
2198 $continuation_data = $restore_jobdata;
2199 } else {
2200 $abort_restore_already = true;
2201 $updraftplus->log(__('Sufficient information about the in-progress restoration operation could not be found.', 'updraftplus').' (restoreid_nojobdata)', 'error', 'restoreid_nojobdata');
2202 }
2203 }
2204
2205 } else {
2206 $backup_timestamp = $_REQUEST['backup_timestamp'];
2207 $continuation_data = null;
2208 }
2209
2210 if (empty($abort_restore_already)) {
2211 $backup_success = $this->restore_backup($backup_timestamp, $continuation_data);
2212 } else {
2213 $backup_success = false;
2214 }
2215
2216 if (empty($updraftplus->errors) && $backup_success === true) {
2217 // TODO: Deal with the case of some of the work having been deferred
2218 // If we restored the database, then that will have out-of-date information which may confuse the user - so automatically re-scan for them.
2219 $updraftplus->rebuild_backup_history();
2220 echo '<p><strong>';
2221 $updraftplus->log_e('Restore successful!');
2222 echo '</strong></p>';
2223 $updraftplus->log("Restore successful");
2224 $s_val = 1;
2225 if (!empty($this->entities_to_restore) && is_array($this->entities_to_restore)) {
2226 foreach ($this->entities_to_restore as $k => $v) {
2227 if ('db' != $v) $s_val = 2;
2228 }
2229 }
2230 $pval = ($updraftplus->have_addons) ? 1 : 0;
2231 echo '<strong>'.__('Actions','updraftplus').':</strong> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&updraft_restore_success='.$s_val.'&pval='.$pval.'">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
2232 return;
2233 } elseif (is_wp_error($backup_success)) {
2234 echo '<p>';
2235 $updraftplus->log_e('Restore failed...');
2236 echo '</p>';
2237 $updraftplus->log_wp_error($backup_success);
2238 $updraftplus->log("Restore failed");
2239 $updraftplus->list_errors();
2240 echo '<strong>'.__('Actions','updraftplus').':</strong> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
2241 return;
2242 } elseif (false === $backup_success) {
2243 # This means, "not yet - but stay on the page because we may be able to do it later, e.g. if the user types in the requested information"
2244 echo '<p>';
2245 $updraftplus->log_e('Restore failed...');
2246 echo '</p>';
2247 $updraftplus->log("Restore failed");
2248 $updraftplus->list_errors();
2249 echo '<strong>'.__('Actions','updraftplus').':</strong> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
2250 return;
2251 }
2252 }
2253
2254 if (isset($_REQUEST['action']) && 'updraft_delete_old_dirs' == $_REQUEST['action']) {
2255 $nonce = (empty($_REQUEST['_wpnonce'])) ? "" : $_REQUEST['_wpnonce'];
2256 if (!wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce')) die('Security check');
2257 $this->delete_old_dirs_go();
2258 return;
2259 }
2260
2261 if (!empty($_REQUEST['action']) && 'updraftplus_broadcastaction' == $_REQUEST['action'] && !empty($_REQUEST['subaction'])) {
2262 $nonce = (empty($_REQUEST['nonce'])) ? "" : $_REQUEST['nonce'];
2263 if (!wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce')) die('Security check');
2264 do_action($_REQUEST['subaction']);
2265 return;
2266 }
2267
2268 if (isset($_GET['error'])) {
2269 // This is used by Microsoft OneDrive authorisation failures (May 15). I am not sure what may have been using the 'error' GET parameter otherwise - but it is harmless.
2270 if (!empty($_GET['error_description'])) {
2271 $this->show_admin_warning(htmlspecialchars($_GET['error_description']).' ('.htmlspecialchars($_GET['error']).')', 'error');
2272 } else {
2273 $this->show_admin_warning(htmlspecialchars($_GET['error']), 'error');
2274 }
2275 }
2276
2277 if (isset($_GET['message'])) $this->show_admin_warning(htmlspecialchars($_GET['message']));
2278
2279 if (isset($_GET['action']) && $_GET['action'] == 'updraft_create_backup_dir' && isset($_GET['nonce']) && wp_verify_nonce($_GET['nonce'], 'create_backup_dir')) {
2280 $created = $this->create_backup_dir();
2281 if (is_wp_error($created)) {
2282 echo '<p>'.__('Backup directory could not be created', 'updraftplus').'...<br/>';
2283 echo '<ul class="disc">';
2284 foreach ($created->get_error_messages() as $key => $msg) {
2285 echo '<li>'.htmlspecialchars($msg).'</li>';
2286 }
2287 echo '</ul></p>';
2288 } elseif ($created !== false) {
2289 echo '<p>'.__('Backup directory successfully created.', 'updraftplus').'</p><br/>';
2290 }
2291 echo '<b>'.__('Actions','updraftplus').':</b> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__('Return to UpdraftPlus Configuration', 'updraftplus').'</a>';
2292 return;
2293 }
2294
2295 echo '<div id="updraft_backup_started" class="updated updraft-hidden" style="display:none;"></div>';
2296
2297 if (isset($_POST['action']) && 'updraft_backup_debug_all' == $_POST['action']) {
2298 $updraftplus->boot_backup(true,true);
2299 } elseif (isset($_POST['action']) && 'updraft_backup_debug_db' == $_POST['action']) {
2300 $updraftplus->boot_backup(false, true, false, true);
2301 } elseif (isset($_POST['action']) && 'updraft_wipesettings' == $_POST['action']) {
2302 $settings = $updraftplus->get_settings_keys();
2303 foreach ($settings as $s) UpdraftPlus_Options::delete_updraft_option($s);
2304
2305 // These aren't in get_settings_keys() because they are always in the options table, regardless of context
2306 global $wpdb;
2307 $wpdb->query("DELETE FROM $wpdb->options WHERE ( option_name LIKE 'updraftplus_unlocked_%' OR option_name LIKE 'updraftplus_locked_%' OR option_name LIKE 'updraftplus_last_lock_time_%' OR option_name LIKE 'updraftplus_semaphore_%' OR option_name LIKE 'updraft_jobdata_%' OR option_name LIKE 'updraft_last_scheduled_%' )");
2308
2309 $site_options = array('updraft_oneshotnonce');
2310 foreach ($site_options as $s) delete_site_option($s);
2311
2312 $this->show_admin_warning(__("Your settings have been wiped.", 'updraftplus'));
2313 }
2314
2315 // This opens a div
2316 $this->settings_header();
2317 ?>
2318
2319 <div id="updraft-hidethis">
2320 <p>
2321 <strong><?php _e('Warning:', 'updraftplus'); ?> <?php _e("If you can still read these words after the page finishes loading, then there is a JavaScript or jQuery problem in the site.", 'updraftplus'); ?></strong>
2322
2323 <?php if (false !== strpos(basename(UPDRAFTPLUS_URL), ' ')) { ?>
2324 <strong><?php _e('The UpdraftPlus directory in wp-content/plugins has white-space in it; WordPress does not like this. You should rename the directory to wp-content/plugins/updraftplus to fix this problem.', 'updraftplus');?></strong>
2325 <?php } else { ?>
2326 <a href="https://updraftplus.com/do-you-have-a-javascript-or-jquery-error/"><?php _e('Go here for more information.', 'updraftplus'); ?></a>
2327 <?php } ?>
2328 </p>
2329 </div>
2330
2331 <?php
2332
2333 $include_deleteform_div = true;
2334
2335 // Opens a div, which needs closing later
2336 if (isset($_GET['updraft_restore_success'])) {
2337 $success_advert = (isset($_GET['pval']) && 0 == $_GET['pval'] && !$updraftplus->have_addons) ? '<p>'.__('For even more features and personal support, check out ','updraftplus').'<strong><a href="https://updraftplus.com/shop/updraftplus-premium/" target="_blank">UpdraftPlus Premium</a>.</strong></p>' : "";
2338
2339 echo "<div class=\"updated backup-restored\"><span><strong>".__('Your backup has been restored.','updraftplus').'</strong></span><br>';
2340 // Unnecessary - will be advised of this below
2341 // if (2 == $_GET['updraft_restore_success']) echo ' '.__('Your old (themes, uploads, plugins, whatever) directories have been retained with "-old" appended to their name. Remove them when you are satisfied that the backup worked properly.');
2342 echo $success_advert;
2343 $include_deleteform_div = false;
2344
2345 }
2346
2347 // $this->print_restore_in_progress_box_if_needed();
2348
2349 if ($this->scan_old_dirs(true)) $this->print_delete_old_dirs_form(true, $include_deleteform_div);
2350
2351 // Close the div opened by the earlier section
2352 if (isset($_GET['updraft_restore_success'])) echo '</div>';
2353
2354 $ws_advert = $updraftplus->wordshell_random_advert(1);
2355 if ($ws_advert && empty($success_advert) && empty($this->no_settings_warning)) { echo '<div class="updated ws_advert" style="clear:left;">'.$ws_advert.'</div>'; }
2356
2357 if (!$updraftplus->memory_check(64)) {?>
2358 <div class="updated memory-limit"><?php _e("Your PHP memory limit (set by your web hosting company) is very low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may struggle with a memory limit of less than 64 Mb - especially if you have very large files uploaded (though on the other hand, many sites will be successful with a 32Mb limit - your experience may vary).",'updraftplus');?> <?php _e('Current limit is:','updraftplus');?> <?php echo $updraftplus->memory_check_current(); ?> MB</div>
2359 <?php
2360 }
2361
2362
2363 if (!empty($updraftplus->errors)) {
2364 echo '<div class="error updraft_list_errors">';
2365 $updraftplus->list_errors();
2366 echo '</div>';
2367 }
2368
2369 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
2370 if (empty($backup_history)) {
2371 $updraftplus->rebuild_backup_history();
2372 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
2373 }
2374 $backup_history = is_array($backup_history) ? $backup_history : array();
2375 ?>
2376
2377 <h2 class="nav-tab-wrapper">
2378 <?php
2379 $tabflag = 1;
2380 if (isset($_REQUEST['tab'])){
2381 switch($_REQUEST['tab']) {
2382 case 'status': $tabflag = 1; break;
2383 case 'backups': $tabflag = 2; break;
2384 case 'settings': $tabflag = 3; break;
2385 case 'expert': $tabflag = 4; break;
2386 case 'addons': $tabflag = 5; break;
2387 default : $tabflag = 1;
2388 }
2389 }
2390
2391 ?>
2392 <a class="nav-tab <?php if (1 == $tabflag) echo 'nav-tab-active'; ?>" id="updraft-navtab-status" href="#updraft-navtab-status-content" ><?php _e('Current Status', 'updraftplus');?> </span></a>
2393 <a class="nav-tab <?php if (2 == $tabflag) echo 'nav-tab-active'; ?>" id="updraft-navtab-backups" href="#updraft-navtab-backups-contents" ><?php echo __('Existing Backups', 'updraftplus').' ('.count($backup_history).')';?> </span></a>
2394 <a class="nav-tab <?php if (3 == $tabflag) echo 'nav-tab-active'; ?>" id="updraft-navtab-settings" href="#updraft-navtab-settings-content"><?php _e('Settings', 'updraftplus');?> </span></a>
2395 <a class="nav-tab<?php if (4 == $tabflag) echo ' nav-tab-active'; ?>" id="updraft-navtab-expert" href="#updraft-navtab-expert-content"><?php _e('Advanced Tools', 'updraftplus');?> </span></a>
2396 <a class="nav-tab<?php if (5 == $tabflag) echo ' nav-tab-active'; ?>" id="updraft-navtab-addons" href="#updraft-navtab-addons-content"><?php _e('Premium / Extensions', 'updraftplus');?> </span></a>
2397 <?php //do_action('updraftplus_settings_afternavtabs'); ?>
2398 </h2>
2399
2400 <?php
2401 $updraft_dir = $updraftplus->backups_dir_location();
2402 $backup_disabled = ($updraftplus->really_is_writable($updraft_dir)) ? '' : 'disabled="disabled"';
2403 ?>
2404
2405 <div id="updraft-poplog" >
2406 <pre id="updraft-poplog-content"></pre>
2407 </div>
2408
2409 <div id="updraft-navtab-status-content" class="<?php if (1 != $tabflag) echo 'updraft-hidden'; ?>" style="<?php if (1 != $tabflag) echo 'display:none;'; ?>">
2410
2411 <div id="updraft-insert-admin-warning"></div>
2412
2413 <table class="form-table" style="float:left; clear:both;">
2414 <noscript>
2415 <tr>
2416 <th><?php _e('JavaScript warning','updraftplus');?>:</th>
2417 <td style="color:red"><?php _e('This admin interface uses JavaScript heavily. You either need to activate it within your browser, or to use a JavaScript-capable browser.','updraftplus');?></td>
2418 </tr>
2419 </noscript>
2420
2421 <tr>
2422 <th></th>
2423 <td>
2424
2425 <?php
2426 if ($backup_disabled) {
2427 $unwritable_mess = htmlspecialchars(__("The 'Backup Now' button is disabled as your backup directory is not writable (go to the 'Settings' tab and find the relevant option).", 'updraftplus'));
2428 $this->show_admin_warning($unwritable_mess, "error");
2429 }
2430 ?>
2431 <button id="updraft-backupnow-button" type="button" <?php echo $backup_disabled ?> class="updraft-bigbutton button-primary" <?php if ($backup_disabled) echo 'title="'.esc_attr(__('This button is disabled because your backup directory is not writable (see the settings).', 'updraftplus')).'" ';?> onclick="updraft_backup_dialog_open();"><?php _e('Backup Now', 'updraftplus');?></button>
2432
2433 <button type="button" class="updraft-bigbutton button-primary" onclick="updraft_openrestorepanel();">
2434 <?php _e('Restore','updraftplus');?>
2435 </button>
2436
2437 <button type="button" class="updraft-bigbutton button-primary" onclick="updraft_migrate_dialog_open();"><?php _e('Clone/Migrate','updraftplus');?></button>
2438
2439 </td>
2440 </tr>
2441
2442 <?php
2443 $last_backup_html = $this->last_backup_html();
2444 $current_time = get_date_from_gmt(gmdate('Y-m-d H:i:s'), 'D, F j, Y H:i');
2445 // $current_time = date_i18n('D, F j, Y H:i');
2446
2447 ?>
2448
2449 <script>var lastbackup_laststatus = '<?php echo esc_js($last_backup_html);?>';</script>
2450
2451 <tr>
2452 <th><span title="<?php esc_attr_e("All the times shown in this section are using WordPress's configured time zone, which you can set in Settings -> General", 'updraftplus'); ?>"><?php _e('Next scheduled backups', 'updraftplus');?>:<br>
2453 <span style="font-weight:normal;"><em><?php _e('Now', 'updraftplus');?>: <?php echo $current_time; ?></span></span></em></th>
2454 <td>
2455 <table id="next-backup-table-inner" class="next-backup">
2456 <?php $this->next_scheduled_backups_output(); ?>
2457 </table>
2458 </td>
2459 </tr>
2460
2461 <tr>
2462 <th><?php _e('Last backup job run:','updraftplus');?></th>
2463 <td id="updraft_last_backup"><?php echo $last_backup_html ?></td>
2464 </tr>
2465 </table>
2466
2467 <br style="clear:both;" />
2468
2469 <?php $this->render_active_jobs_and_log_table(); ?>
2470
2471 <div id="updraft-migrate-modal" title="<?php _e('Migrate Site', 'updraftplus'); ?>" style="display:none;">
2472 <?php
2473 if (class_exists('UpdraftPlus_Addons_Migrator')) {
2474 do_action('updraftplus_migrate_modal_output');
2475 } else {
2476 echo '<p id="updraft_migrate_modal_main">'.__('Do you want to migrate or clone/duplicate a site?', 'updraftplus').'</p><p>'.__('Then, try out our "Migrator" add-on. After using it once, you\'ll have saved the purchase price compared to the time needed to copy a site by hand.', 'updraftplus').'</p><p><a href="https://updraftplus.com/shop/migrator/">'.__('Get it here.', 'updraftplus').'</a></p>';
2477 }
2478 ?>
2479 </div>
2480
2481 <div id="updraft-iframe-modal">
2482 <div id="updraft-iframe-modal-innards">
2483 </div>
2484 </div>
2485
2486 <div id="updraft-backupnow-modal" title="UpdraftPlus - <?php _e('Perform a one-time backup', 'updraftplus'); ?>">
2487 <!-- <p>
2488 <?php _e("To proceed, press 'Backup Now'. Then, watch the 'Last Log Message' field for activity.", 'updraftplus');?>
2489 </p>-->
2490
2491 <?php echo $this->backupnow_modal_contents(); ?>
2492 </div>
2493
2494 <?php
2495 if (is_multisite() && !file_exists(UPDRAFTPLUS_DIR.'/addons/multisite.php')) {
2496 ?>
2497 <h2>UpdraftPlus <?php _e('Multisite','updraftplus');?></h2>
2498 <table>
2499 <tr>
2500 <td>
2501 <p class="multisite-advert-width"><?php echo __('Do you need WordPress Multisite support?','updraftplus').' <a href="https://updraftplus.com/shop/updraftplus-premium/">'. __('Please check out UpdraftPlus Premium, or the stand-alone Multisite add-on.','updraftplus');?></a>.</p>
2502 </td>
2503 </tr>
2504 </table>
2505 <?php } ?>
2506
2507 </div>
2508
2509
2510
2511 <div id="updraft-navtab-backups-content" <?php if (2 != $tabflag) echo 'class="updraft-hidden"'; ?> style="<?php if (2 != $tabflag) echo 'display:none;'; ?>">
2512 <?php
2513 $is_opera = (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') || false !== strpos($_SERVER['HTTP_USER_AGENT'], 'OPR/'));
2514 $tmp_opts = array('include_opera_warning' => $is_opera);
2515 $this->settings_downloading_and_restoring($backup_history, false, $tmp_opts);
2516 $this->settings_delete_and_restore_modals();
2517 ?>
2518 </div>
2519
2520 <div id="updraft-navtab-settings-content" <?php if (3 != $tabflag) echo 'class="updraft-hidden"'; ?> style="<?php if (3 != $tabflag) echo 'display:none;'; ?>">
2521 <h2 class="updraft_settings_sectionheading"><?php _e('Backup Contents And Schedule','updraftplus');?></h2>
2522 <?php UpdraftPlus_Options::options_form_begin(); ?>
2523 <?php $this->settings_formcontents(); ?>
2524 </form>
2525 </div>
2526
2527 <div id="updraft-navtab-expert-content"<?php if (4 != $tabflag) echo ' class="updraft-hidden"'; ?> style="<?php if (4 != $tabflag) echo 'display:none;'; ?>">
2528 <?php $this->settings_expertsettings($backup_disabled); ?>
2529 </div>
2530
2531 <div id="updraft-navtab-addons-content"<?php if (5 != $tabflag) echo ' class="updraft-hidden"'; ?> style="<?php if (5 != $tabflag) echo 'display:none;'; ?>">
2532
2533 <?php
2534 $tick = UPDRAFTPLUS_URL.'/images/updraft_tick.png';
2535 $cross = UPDRAFTPLUS_URL.'/images/updraft_cross.png';
2536 $freev = UPDRAFTPLUS_URL.'/images/updraft_freev.png';
2537 $premv = UPDRAFTPLUS_URL.'/images/updraft_premv.png';
2538
2539 ob_start();
2540 ?>
2541 <div>
2542 <h2>UpdraftPlus Premium</h2>
2543 <p>
2544 <span class="premium-upgrade-prompt"><?php _e('You are currently using the free version of UpdraftPlus from wordpress.org.', 'updraftplus');?> <a href="https://updraftplus.com/support/installing-updraftplus-premium-your-add-on/"><br><?php echo __('If you have made a purchase from UpdraftPlus.Com, then follow this link to the instructions to install your purchase.', 'updraftplus').' '.__('The first step is to de-install the free version.', 'updraftplus')?></a></span>
2545 <ul class="updraft_premium_description_list">
2546 <li><a href="https://updraftplus.com/shop/updraftplus-premium/"><strong><?php _e('Get UpdraftPlus Premium', 'updraftplus');?></strong></a></li>
2547 <li><a href="https://updraftplus.com/updraftplus-full-feature-list/"><?php _e('Full feature list', 'updraftplus');?></a></li>
2548 <li><a href="https://updraftplus.com/faq-category/general-and-pre-sales-questions/"><?php _e('Pre-sales FAQs', 'updraftplus');?></a></li>
2549 <li class="last"><a href="https://updraftplus.com/ask-a-pre-sales-question/"><?php _e('Ask a pre-sales question', 'updraftplus');?></a> - <a href="https://updraftplus.com/support/"><?php _e('Support', 'updraftplus');?></a></li>
2550 </ul>
2551 </p>
2552 </div>
2553 <div>
2554 <table class="updraft_feat_table">
2555 <tr>
2556 <th class="updraft_feat_th" style="text-align:left;"></th>
2557 <th class="updraft_feat_th"><img src="<?php echo $freev;?>" height="120"></th>
2558 <th class="updraft_feat_th" style='background-color:#DF6926;'><a href="https://updraftplus.com/shop/updraftplus-premium/"><img src="<?php echo $premv;?>" height="120"></a></th>
2559 </tr>
2560 <tr>
2561 <td class="updraft_feature_cell"><?php _e('Get it from', 'updraftplus');?></td>
2562 <td class="updraft_tick_cell" style="vertical-align:top; line-height: 120%; margin-top:6px; padding-top:6px;">WordPress.Org</td>
2563 <td class="updraft_tick_cell" style="padding: 6px; line-height: 120%;">
2564 UpdraftPlus.Com<br>
2565 <a href="https://updraftplus.com/shop/updraftplus-premium/"><strong><?php _e('Buy It Now!', 'updraftplus');?></strong></a><br>
2566 </td>
2567 </tr>
2568 <tr>
2569 <td class="updraft_feature_cell"><?php _e('Backup WordPress files and database', 'updraftplus');?></td>
2570 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2571 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2572 </tr>
2573 <tr>
2574 <td class="updraft_feature_cell"><?php echo sprintf(__('Translated into over %s languages', 'updraftplus'), 16);?></td>
2575 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2576 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2577 </tr>
2578 <tr>
2579 <td class="updraft_feature_cell"><?php _e('Restore from backup', 'updraftplus');?></td>
2580 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2581 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2582 </tr>
2583 <tr>
2584 <td class="updraft_feature_cell"><?php _e('Backup to remote storage', 'updraftplus');?></td>
2585 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2586 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2587 </tr>
2588 <tr>
2589 <td class="updraft_feature_cell"><?php _e('Dropbox, Google Drive, FTP, S3, Rackspace, Email', 'updraftplus');?></td>
2590 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2591 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2592 </tr>
2593 <tr>
2594 <td class="updraft_feature_cell"><?php _e('WebDAV, Copy.Com, SFTP/SCP, encrypted FTP', 'updraftplus');?></td>
2595 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2596 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2597 </tr>
2598 <tr>
2599 <td class="updraft_feature_cell"><?php _e('Microsoft OneDrive, Microsoft Azure, Google Cloud Storage', 'updraftplus');?></td>
2600 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2601 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2602 </tr>
2603 <tr>
2604 <td class="updraft_feature_cell"><?php _e('Free 1GB for UpdraftPlus Vault', 'updraftplus');?></td>
2605 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2606 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2607 </tr>
2608 <tr>
2609 <td class="updraft_feature_cell"><?php _e('Backup extra files and databases', 'updraftplus');?></td>
2610 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2611 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2612 </tr>
2613 <tr>
2614 <td class="updraft_feature_cell"><?php _e('Migrate / clone (i.e. copy) websites', 'updraftplus');?></td>
2615 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2616 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2617 </tr>
2618 <tr>
2619 <td class="updraft_feature_cell"><?php _e('Basic email reporting', 'updraftplus');?></td>
2620 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2621 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2622 </tr>
2623 <tr>
2624 <td class="updraft_feature_cell"><?php _e('Advanced reporting features', 'updraftplus');?></td>
2625 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2626 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2627 </tr>
2628 <tr>
2629 <td class="updraft_feature_cell"><?php _e('Automatic backup when updating WP/plugins/themes', 'updraftplus');?></td>
2630 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2631 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2632 </tr>
2633 <tr>
2634 <td class="updraft_feature_cell"><?php _e('Send backups to multiple remote destinations', 'updraftplus');?></td>
2635 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2636 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2637 </tr>
2638 <tr>
2639 <td class="updraft_feature_cell"><?php _e('Database encryption', 'updraftplus');?></td>
2640 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2641 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2642 </tr>
2643 <tr>
2644 <td class="updraft_feature_cell"><?php _e('Restore backups from other plugins', 'updraftplus');?></td>
2645 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2646 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2647 </tr>
2648 <tr>
2649 <td class="updraft_feature_cell"><?php _e('No advertising links on UpdraftPlus settings page', 'updraftplus');?></td>
2650 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2651 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2652 </tr>
2653 <tr>
2654 <td class="updraft_feature_cell"><?php _e('Scheduled backups', 'updraftplus');?></td>
2655 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2656 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2657 </tr>
2658 <tr>
2659 <td class="updraft_feature_cell"><?php _e('Fix backup time', 'updraftplus');?></td>
2660 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2661 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2662 </tr>
2663 <tr>
2664 <td class="updraft_feature_cell"><?php _e('Network/Multisite support', 'updraftplus');?></td>
2665 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2666 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2667 </tr>
2668 <tr>
2669 <td class="updraft_feature_cell"><?php _e('Lock settings access', 'updraftplus');?></td>
2670 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2671 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2672 </tr>
2673 <tr>
2674 <td class="updraft_feature_cell"><?php _e('Personal support', 'updraftplus');?></td>
2675 <td class="updraft_tick_cell"><img src="<?php echo $cross;?>"></td>
2676 <td class="updraft_tick_cell"><img src="<?php echo $tick;?>"></td>
2677 </tr>
2678 </table>
2679 </div>
2680 <?php
2681
2682 echo apply_filters('updraftplus_addonstab_content', ob_get_clean());
2683
2684 // Close addons tab
2685 echo '</div>';
2686
2687 // settings_header() opens a div
2688 echo '</div>';
2689 }
2690
2691 private function print_restore_in_progress_box_if_needed() {
2692 $restore_in_progress = get_site_option('updraft_restore_in_progress');
2693 if (!empty($restore_in_progress)) {
2694 global $updraftplus;
2695 $restore_jobdata = $updraftplus->jobdata_getarray($restore_in_progress);
2696 if (is_array($restore_jobdata) && !empty($restore_jobdata)) {
2697 // Only print if within the last 24 hours; and only after 2 minutes
2698 if (isset($restore_jobdata['job_type']) && 'restore' == $restore_jobdata['job_type'] && isset($restore_jobdata['second_loop_entities']) && !empty($restore_jobdata['second_loop_entities']) && isset($restore_jobdata['job_time_ms']) && (time() - $restore_jobdata['job_time_ms'] > 120 || (defined('UPDRAFTPLUS_RESTORE_PROGRESS_ALWAYS_SHOW') && UPDRAFTPLUS_RESTORE_PROGRESS_ALWAYS_SHOW)) && time() - $restore_jobdata['job_time_ms'] < 86400 && (empty($_REQUEST['action']) || ('updraft_restore' != $_REQUEST['action'] && 'updraft_restore_continue' != $_REQUEST['action']))) {
2699 $restore_jobdata['jobid'] = $restore_in_progress;
2700 $this->restore_in_progress_jobdata = $restore_jobdata;
2701 add_action('all_admin_notices', array($this, 'show_admin_restore_in_progress_notice') );
2702 }
2703 }
2704 }
2705 }
2706
2707 public function show_admin_restore_in_progress_notice() {
2708
2709 if (isset($_REQUEST['action']) && 'updraft_restore_abort' == $_REQUEST['action'] && !empty($_REQUEST['restoreid'])) {
2710 delete_site_option('updraft_restore_in_progress');
2711 return;
2712 }
2713
2714 $restore_jobdata = $this->restore_in_progress_jobdata;
2715 $seconds_ago = time() - (int)$restore_jobdata['job_time_ms'];
2716 $minutes_ago = floor($seconds_ago/60);
2717 $seconds_ago = $seconds_ago - $minutes_ago*60;
2718 $time_ago = sprintf(__("%s minutes, %s seconds", 'updraftplus'), $minutes_ago, $seconds_ago);
2719 ?><div class="updated show_admin_restore_in_progress_notice">
2720 <span class="unfinished-restoration"><strong><?php echo 'UpdraftPlus: '.__('Unfinished restoration', 'updraftplus'); ?> </strong></span><br>
2721 <p><?php printf(__('You have an unfinished restoration operation, begun %s ago.', 'updraftplus'), $time_ago);?></p>
2722 <form method="post" action="<?php echo UpdraftPlus_Options::admin_page_url().'?page=updraftplus'; ?>">
2723 <?php wp_nonce_field('updraftplus-credentialtest-nonce'); ?>
2724 <input id="updraft_restore_continue_action" type="hidden" name="action" value="updraft_restore_continue">
2725 <input type="hidden" name="restoreid" value="<?php echo $restore_jobdata['jobid'];?>" value="<?php echo esc_attr($restore_jobdata['jobid']);?>">
2726 <button onclick="jQuery('#updraft_restore_continue_action').val('updraft_restore_continue'); jQuery(this).parent('form').submit();" type="submit" class="button-primary"><?php _e('Continue restoration', 'updraftplus'); ?></button>
2727 <button onclick="jQuery('#updraft_restore_continue_action').val('updraft_restore_abort'); jQuery(this).parent('form').submit();" class="button-secondary"><?php _e('Dismiss', 'updraftplus');?></button>
2728 </form><?php
2729 echo "</div>";
2730
2731 }
2732
2733 public function backupnow_modal_contents() {
2734
2735 $ret = $this->backup_now_widgetry();
2736
2737 // $ret .= '<p>'.__('Does nothing happen when you attempt backups?','updraftplus').' <a href="https://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/">'.__('Go here for help.', 'updraftplus').'</a></p>';
2738
2739 return $ret;
2740 }
2741
2742 private function backup_now_widgetry() {
2743
2744 $ret = '';
2745
2746 $ret .= '<p>
2747 <input type="checkbox" id="backupnow_includedb" checked="checked"> <label for="backupnow_includedb">'.__("Include the database in the backup", 'updraftplus').'</label><br>';
2748
2749 $ret .= '<input type="checkbox" id="backupnow_includefiles" checked="checked"> <label for="backupnow_includefiles">'.__("Include any files in the backup", 'updraftplus').'</label> (<a href="#" id="backupnow_includefiles_showmoreoptions">...</a>)<br>';
2750
2751 $ret .= '<div id="backupnow_includefiles_moreoptions" class="updraft-hidden" style="display:none;"><em>'.__('Your saved settings also affect what is backed up - e.g. files excluded.', 'updraftplus').'</em><br>'.$this->files_selector_widgetry('backupnow_files_', false, 'sometimes').'</div>';
2752
2753 $ret .= '<span id="backupnow_remote_container">'.$this->backup_now_remote_message().'</span>';
2754
2755 $ret .= '</p>';
2756
2757 $ret .= apply_filters('updraft_backupnow_modal_afteroptions', '', '');
2758
2759 return $ret;
2760 }
2761
2762 // Also used by the auto-backups add-on
2763 public function render_active_jobs_and_log_table($wide_format = false, $print_active_jobs = true) {
2764 ?>
2765 <table class="form-table" id="updraft_activejobs_table">
2766
2767 <?php $active_jobs = ($print_active_jobs) ? $this->print_active_jobs() : '';?>
2768 <tr id="updraft_activejobsrow" class="<?php
2769 if (!$active_jobs && !$wide_format) { echo 'hidden'; }
2770 if ($wide_format) { echo ".minimum-height"; }
2771 ?>">
2772 <?php if ($wide_format) { ?>
2773 <td id="updraft_activejobs" colspan="2">
2774 <?php echo $active_jobs;?>
2775 </td>
2776 <?php } else { ?>
2777 <th><?php _e('Backups in progress:', 'updraftplus');?></th>
2778 <td id="updraft_activejobs"><?php echo $active_jobs;?></td>
2779 <?php } ?>
2780 </tr>
2781
2782 <tr id="updraft_lastlogmessagerow">
2783 <?php if ($wide_format) {
2784 // Hide for now - too ugly
2785 ?>
2786 <td colspan="2" class="last-message"><strong><?php _e('Last log message','updraftplus');?>:</strong><br>
2787 <span id="updraft_lastlogcontainer"><?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', __('(Nothing yet logged)','updraftplus'))); ?></span><br>
2788 <?php $this->most_recently_modified_log_link(); ?>
2789 </td>
2790 <?php } else { ?>
2791 <th><?php _e('Last log message','updraftplus');?>:</th>
2792 <td>
2793 <span id="updraft_lastlogcontainer"><?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', __('(Nothing yet logged)','updraftplus'))); ?></span><br>
2794 <?php $this->most_recently_modified_log_link(); ?>
2795 </td>
2796 <?php } ?>
2797 </tr>
2798
2799 <?php
2800 # Currently disabled - not sure who we want to show this to
2801 if (1==0 && !defined('UPDRAFTPLUS_NOADS_B')) {
2802 $feed = $updraftplus->get_updraftplus_rssfeed();
2803 if (is_a($feed, 'SimplePie')) {
2804 echo '<tr><th style="vertical-align:top;">'.__('Latest UpdraftPlus.com news:', 'updraftplus').'</th><td class="updraft_simplepie">';
2805 echo '<ul class="disc;">';
2806 foreach ($feed->get_items(0, 5) as $item) {
2807 echo '<li>';
2808 echo '<a href="'.esc_attr($item->get_permalink()).'">';
2809 echo htmlspecialchars($item->get_title());
2810 # D, F j, Y H:i
2811 echo "</a> (".htmlspecialchars($item->get_date('j F Y')).")";
2812 echo '</li>';
2813 }
2814 echo '</ul></td></tr>';
2815 }
2816 }
2817 ?>
2818 </table>
2819 <?php
2820 }
2821
2822 private function most_recently_modified_log_link() {
2823
2824 global $updraftplus;
2825 list($mod_time, $log_file, $nonce) = $updraftplus->last_modified_log();
2826
2827 ?>
2828 <a href="?page=updraftplus&amp;action=downloadlatestmodlog&amp;wpnonce=<?php echo wp_create_nonce('updraftplus_download') ?>" <?php if (!$mod_time) echo 'style="display:none;"'; ?> class="updraft-log-link" onclick="event.preventDefault(); updraft_popuplog('');"><?php _e('Download most recently modified log file', 'updraftplus');?></a>
2829 <?php
2830 }
2831
2832 public function settings_downloading_and_restoring($backup_history = array(), $return_result = false, $options = array()) {
2833 global $updraftplus;
2834 if ($return_result) ob_start();
2835
2836 $default_options = array(
2837 'include_uploader' => true,
2838 'include_opera_warning' => false,
2839 'will_immediately_calculate_disk_space' => true,
2840 'include_whitespace_warning' => true,
2841 'include_header' => false,
2842 );
2843
2844 foreach ($default_options as $k => $v) {
2845 if (!isset($options[$k])) $options[$k] = $v;
2846 }
2847
2848 if (false === $backup_history) $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
2849 if (!is_array($backup_history)) $backup_history=array();
2850
2851 if (!empty($options['include_header'])) echo '<h2>'.__('Existing Backups', 'updraftplus').' ('.count($backup_history).')</h2>';
2852
2853 ?>
2854 <div class="download-backups form-table">
2855 <?php /* echo '<h2>'.__('Existing Backups: Downloading And Restoring', 'updraftplus').'</h2>'; */ ?>
2856 <?php if (!empty($options['include_whitespace_warning'])) { ?>
2857 <p class="ud-whitespace-warning updraft-hidden" style="display:none;">
2858 <?php echo '<strong>'.__('Warning','updraftplus').':</strong> '.__('Your WordPress installation has a problem with outputting extra whitespace. This can corrupt backups that you download from here.','updraftplus').' <a href="https://updraftplus.com/problems-with-extra-white-space/">'.__('Please consult this FAQ for help on what to do about it.', 'updraftplus').'</a>';?>
2859 </p>
2860 <?php } ?>
2861
2862 <ul>
2863 <li title="<?php esc_attr_e('This is a count of the contents of your Updraft directory', 'updraftplus');?>"><strong><?php _e('Web-server disk space in use by UpdraftPlus', 'updraftplus');?>:</strong> <span class="updraft_diskspaceused"><em><?php echo empty($options['will_immediately_calculate_disk_space']) ? '' : __('calculating...', 'updraftplus'); ?></em></span> <a class="updraft_diskspaceused_update" href="#"><?php echo empty($options['will_immediately_calculate_disk_space']) ? __('calculate', 'updraftplus') : __('refresh','updraftplus');?></a></li>
2864
2865 <li>
2866 <strong><?php _e('More tasks:', 'updraftplus');?></strong>
2867 <?php if (!empty($options['include_uploader'])) { ?><a class="updraft_uploader_toggle" href="#"><?php _e('Upload backup files', 'updraftplus');?></a> | <?php } ?>
2868 <a href="#" class="updraft_rescan_local" title="<?php echo __('Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded.', 'updraftplus').' '.__('The location of this directory is set in the expert settings, in the Settings tab.', 'updraftplus'); ?>"><?php _e('Rescan local folder for new backup sets', 'updraftplus');?></a>
2869 | <a href="#" class="updraft_rescan_remote" title="<?php _e('Press here to look inside your remote storage methods for any existing backup sets (from any site, if they are stored in the same folder).', 'updraftplus'); ?>"><?php _e('Rescan remote storage','updraftplus');?></a>
2870 </li>
2871 <?php if (!empty($options['include_opera_warning'])) { ?>
2872 <li><strong><?php _e('Opera web browser', 'updraftplus');?>:</strong> <?php _e('If you are using this, then turn Turbo/Road mode off.', 'updraftplus');?></li>
2873 <?php } ?>
2874
2875 </ul>
2876
2877 <?php if (!empty($options['include_uploader'])) { ?>
2878
2879 <div id="updraft-plupload-modal" style="display:none;" title="<?php _e('UpdraftPlus - Upload backup files','updraftplus'); ?>">
2880 <p class="upload"><em><?php _e("Upload files into UpdraftPlus." ,'updraftplus');?> <?php echo htmlspecialchars(__('Or, you can place them manually into your UpdraftPlus directory (usually wp-content/updraft), e.g. via FTP, and then use the "rescan" link above.', 'updraftplus'));?></em></p>
2881 <?php
2882 global $wp_version;
2883 if (version_compare($wp_version, '3.3', '<')) {
2884 echo '<em>'.sprintf(__('This feature requires %s version %s or later', 'updraftplus'), 'WordPress', '3.3').'</em>';
2885 } else {
2886 ?>
2887 <div id="plupload-upload-ui">
2888 <div id="drag-drop-area">
2889 <div class="drag-drop-inside">
2890 <p class="drag-drop-info"><?php _e('Drop backup files here', 'updraftplus'); ?></p>
2891 <p><?php _ex('or', 'Uploader: Drop backup files here - or - Select Files'); ?></p>
2892 <p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
2893 </div>
2894 </div>
2895 <div id="filelist">
2896 </div>
2897 </div>
2898 <?php
2899 }
2900 ?>
2901 </div>
2902 <?php } ?>
2903
2904 <div class="ud_downloadstatus"></div>
2905 <div class="updraft_existing_backups">
2906 <?php echo $this->existing_backup_table($backup_history); ?>
2907 </div>
2908
2909 </div>
2910 <?php
2911 if ($return_result) return ob_get_clean();
2912 }
2913
2914 public function settings_delete_and_restore_modals($return_result = false) {
2915 global $updraftplus;
2916 if ($return_result) ob_start();
2917 ?>
2918
2919 <div id="ud_massactions" class="updraft-hidden" style="display:none;">
2920 <strong><?php _e('Actions upon selected backups', 'updraftplus');?></strong> <br>
2921 <div class="updraftplus-remove" style="float: left;"><a href="#" onclick="updraft_deleteallselected(); return false;"><?php _e('Delete', 'updraftplus');?></a></div>
2922 <div class="updraft-viewlogdiv"><a href="#" onclick="jQuery('#updraft-navtab-backups-content .updraft_existing_backups .updraft_existing_backups_row').addClass('backuprowselected'); return false;"><?php _e('Select all', 'updraftplus');?></a></div>
2923 <div class="updraft-viewlogdiv"><a href="#" onclick="jQuery('#updraft-navtab-backups-content .updraft_existing_backups .updraft_existing_backups_row').removeClass('backuprowselected'); jQuery('#ud_massactions').hide(); return false;"><?php _e('Deselect', 'updraftplus');?></a></div>
2924 </div>
2925
2926 <div id="updraft-message-modal" title="UpdraftPlus">
2927 <div id="updraft-message-modal-innards">
2928 </div>
2929 </div>
2930
2931 <div id="updraft-delete-modal" title="<?php _e('Delete backup set', 'updraftplus');?>">
2932 <form id="updraft_delete_form" method="post">
2933 <p id="updraft_delete_question_singular">
2934 <?php echo sprintf(__('Are you sure that you wish to remove %s from UpdraftPlus?', 'updraftplus'), __('this backup set', 'updraftplus')); ?>
2935 </p>
2936 <p id="updraft_delete_question_plural" class="updraft-hidden" style="display:none;">
2937 <?php echo sprintf(__('Are you sure that you wish to remove %s from UpdraftPlus?', 'updraftplus'), __('these backup sets', 'updraftplus')); ?>
2938 </p>
2939 <fieldset>
2940 <input type="hidden" name="nonce" value="<?php echo wp_create_nonce('updraftplus-credentialtest-nonce');?>">
2941 <input type="hidden" name="action" value="updraft_ajax">
2942 <input type="hidden" name="subaction" value="deleteset">
2943 <input type="hidden" name="backup_timestamp" value="0" id="updraft_delete_timestamp">
2944 <input type="hidden" name="backup_nonce" value="0" id="updraft_delete_nonce">
2945 <div id="updraft-delete-remote-section"><input checked="checked" type="checkbox" name="delete_remote" id="updraft_delete_remote" value="1"> <label for="updraft_delete_remote"><?php _e('Also delete from remote storage', 'updraftplus');?></label><br>
2946 <p id="updraft-delete-waitwarning" class="updraft-hidden" style="display:none;"><em><?php _e('Deleting... please allow time for the communications with the remote storage to complete.', 'updraftplus');?></em></p>
2947 </div>
2948 </fieldset>
2949 </form>
2950 </div>
2951
2952 <div id="updraft-restore-modal" title="UpdraftPlus - <?php _e('Restore backup','updraftplus');?>">
2953 <p><strong><?php _e('Restore backup from','updraftplus');?>:</strong> <span class="updraft_restore_date"></span></p>
2954
2955 <div id="updraft-restore-modal-stage2">
2956
2957 <p><strong><?php _e('Retrieving (if necessary) and preparing backup files...', 'updraftplus');?></strong></p>
2958 <div id="ud_downloadstatus2"></div>
2959
2960 <div id="updraft-restore-modal-stage2a"></div>
2961
2962 </div>
2963
2964 <div id="updraft-restore-modal-stage1">
2965 <p><?php _e("Restoring will replace this site's themes, plugins, uploads, database and/or other content directories (according to what is contained in the backup set, and your selection).",'updraftplus');?> <?php _e('Choose the components to restore','updraftplus');?>:</p>
2966 <form id="updraft_restore_form" method="post">
2967 <fieldset>
2968 <input type="hidden" name="action" value="updraft_restore">
2969 <input type="hidden" name="backup_timestamp" value="0" id="updraft_restore_timestamp">
2970 <input type="hidden" name="meta_foreign" value="0" id="updraft_restore_meta_foreign">
2971 <input type="hidden" name="updraft_restorer_backup_info" value="" id="updraft_restorer_backup_info">
2972 <input type="hidden" name="updraft_restorer_restore_options" value="" id="updraft_restorer_restore_options">
2973 <?php
2974
2975 # The 'off' check is for badly configured setups - http://wordpress.org/support/topic/plugin-wp-super-cache-warning-php-safe-mode-enabled-but-safe-mode-is-off
2976 if ($updraftplus->detect_safe_mode()) {
2977 echo "<p><em>".__("Your web server has PHP's so-called safe_mode active.", 'updraftplus').' '.__('This makes time-outs much more likely. You are recommended to turn safe_mode off, or to restore only one entity at a time, <a href="https://updraftplus.com/faqs/i-want-to-restore-but-have-either-cannot-or-have-failed-to-do-so-from-the-wp-admin-console/">or to restore manually</a>.', 'updraftplus')."</em></p><br/>";
2978 }
2979
2980 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2981 foreach ($backupable_entities as $type => $info) {
2982 if (!isset($info['restorable']) || $info['restorable'] == true) {
2983 echo '<div><input id="updraft_restore_'.$type.'" type="checkbox" name="updraft_restore[]" value="'.$type.'"> <label id="updraft_restore_label_'.$type.'" for="updraft_restore_'.$type.'">'.$info['description'].'</label><br>';
2984
2985 do_action("updraftplus_restore_form_$type");
2986
2987 echo '</div>';
2988 } else {
2989 $sdescrip = isset($info['shortdescription']) ? $info['shortdescription'] : $info['description'];
2990 echo "<div class=\"cannot-restore\"><em>".htmlspecialchars(sprintf(__('The following entity cannot be restored automatically: "%s".', 'updraftplus'), $sdescrip))." ".__('You will need to restore it manually.', 'updraftplus')."</em><br>".'<input id="updraft_restore_'.$type.'" type="hidden" name="updraft_restore[]" value="'.$type.'">';
2991 echo '</div>';
2992 }
2993 }
2994 ?>
2995 <div><input id="updraft_restore_db" type="checkbox" name="updraft_restore[]" value="db"> <label for="updraft_restore_db"><?php _e('Database','updraftplus'); ?></label><br>
2996
2997 <div id="updraft_restorer_dboptions" class="updraft-hidden" style="display:none;"><h4><?php echo sprintf(__('%s restoration options:','updraftplus'),__('Database','updraftplus')); ?></h4>
2998
2999 <?php
3000
3001 do_action("updraftplus_restore_form_db");
3002
3003 if (!class_exists('UpdraftPlus_Addons_Migrator')) {
3004
3005 echo '<a href="https://updraftplus.com/faqs/tell-me-more-about-the-search-and-replace-site-location-in-the-database-option/">'.__('You can search and replace your database (for migrating a website to a new location/URL) with the Migrator add-on - follow this link for more information','updraftplus').'</a>';
3006
3007 }
3008
3009 ?>
3010
3011 </div>
3012
3013 </div>
3014 </fieldset>
3015 </form>
3016 <p><em><a href="https://updraftplus.com/faqs/what-should-i-understand-before-undertaking-a-restoration/" target="_blank"><?php _e('Do read this helpful article of useful things to know before restoring.','updraftplus');?></a></em></p>
3017 </div>
3018 </div>
3019
3020 <?php
3021 if ($return_result) return ob_get_clean();
3022 }
3023
3024 public function settings_debugrow($head, $content) {
3025 echo "<tr class=\"updraft_debugrow\"><th>$head</th><td>$content</td></tr>";
3026 }
3027
3028 private function settings_expertsettings($backup_disabled) {
3029 global $updraftplus, $wpdb;
3030 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
3031 ?>
3032 <div class="expertmode">
3033 <p><em><?php _e('Unless you have a problem, you can completely ignore everything here.', 'updraftplus');?></em></p>
3034 <table>
3035 <?php
3036
3037 // It appears (Mar 2015) that some mod_security distributions block the output of the string el6.x86_64 in PHP output, on the silly assumption that only hackers are interested in knowing what environment PHP is running on.
3038 // $uname_info = @php_uname();
3039 $uname_info = @php_uname('s').' '.@php_uname('n').' ';
3040
3041 $release_name = @php_uname('r');
3042 if (preg_match('/^(.*)\.(x86_64|[3456]86)$/', $release_name, $matches)) {
3043 $release_name = $matches[1].' ';
3044 } else {
3045 $release_name = '';
3046 }
3047
3048 // In case someone does something similar with just the processor type string
3049 $mtype = @php_uname('m');
3050 if ('x86_64' == $mtype) {
3051 $mtype = '64-bit';
3052 } elseif (preg_match('/^i([3456]86)$/', $mtype, $matches)) {
3053 $mtype = $matches[1];
3054 }
3055
3056 $uname_info .= $release_name.$mtype.' '.@php_uname('v');
3057
3058 $this->settings_debugrow(__('Web server:','updraftplus'), htmlspecialchars($_SERVER["SERVER_SOFTWARE"]).' ('.htmlspecialchars($uname_info).')');
3059
3060 $this->settings_debugrow('ABSPATH:', htmlspecialchars(ABSPATH));
3061 $this->settings_debugrow('WP_CONTENT_DIR:', htmlspecialchars(WP_CONTENT_DIR));
3062 $this->settings_debugrow('WP_PLUGIN_DIR:', htmlspecialchars(WP_PLUGIN_DIR));
3063 $this->settings_debugrow('Table prefix:', htmlspecialchars($updraftplus->get_table_prefix()));
3064
3065 $peak_memory_usage = memory_get_peak_usage(true)/1024/1024;
3066 $memory_usage = memory_get_usage(true)/1024/1024;
3067 $this->settings_debugrow(__('Peak memory usage','updraftplus').':', $peak_memory_usage.' MB');
3068 $this->settings_debugrow(__('Current memory usage','updraftplus').':', $memory_usage.' MB');
3069 $this->settings_debugrow(__('Memory limit', 'updraftplus').':', htmlspecialchars(ini_get('memory_limit')));
3070 $this->settings_debugrow(sprintf(__('%s version:','updraftplus'), 'PHP'), htmlspecialchars(phpversion()).' - <a href="admin-ajax.php?page=updraftplus&action=updraft_ajax&subaction=phpinfo&nonce='.wp_create_nonce('updraftplus-credentialtest-nonce').'" id="updraftplus-phpinfo">'.__('show PHP information (phpinfo)', 'updraftplus').'</a>');
3071 $this->settings_debugrow(sprintf(__('%s version:','updraftplus'), 'MySQL'), htmlspecialchars($wpdb->db_version()));
3072 if (function_exists('curl_version') && function_exists('curl_exec')) {
3073 $cv = curl_version();
3074 $cvs = $cv['version'].' / SSL: '.$cv['ssl_version'].' / libz: '.$cv['libz_version'];
3075 } else {
3076 $cvs = __('Not installed', 'updraftplus').' ('.__('required for some remote storage providers', 'updraftplus').')';
3077 }
3078 $this->settings_debugrow(sprintf(__('%s version:', 'updraftplus'), 'Curl'), htmlspecialchars($cvs));
3079 $this->settings_debugrow(sprintf(__('%s version:', 'updraftplus'), 'OpenSSL'), defined('OPENSSL_VERSION_TEXT') ? OPENSSL_VERSION_TEXT : '-');
3080 $this->settings_debugrow('MCrypt:', function_exists('mcrypt_encrypt') ? __('Yes') : __('No'));
3081
3082 if (version_compare(phpversion(), '5.2.0', '>=') && extension_loaded('zip')) {
3083 $ziparchive_exists = __('Yes', 'updraftplus');
3084 } else {
3085 # First do class_exists, because method_exists still sometimes segfaults due to a rare PHP bug
3086 $ziparchive_exists = (class_exists('ZipArchive') && method_exists('ZipArchive', 'addFile')) ? __('Yes', 'updraftplus') : __('No', 'updraftplus');
3087 }
3088 $this->settings_debugrow('ZipArchive::addFile:', $ziparchive_exists);
3089 $binzip = $updraftplus->find_working_bin_zip(false, false);
3090 $this->settings_debugrow(__('zip executable found:', 'updraftplus'), ((is_string($binzip)) ? __('Yes').': '.$binzip : __('No')));
3091 $hosting_bytes_free = $updraftplus->get_hosting_disk_quota_free();
3092 if (is_array($hosting_bytes_free)) {
3093 $perc = round(100*$hosting_bytes_free[1]/(max($hosting_bytes_free[2], 1)), 1);
3094 $this->settings_debugrow(__('Free disk space in account:', 'updraftplus'), sprintf(__('%s (%s used)', 'updraftplus'), round($hosting_bytes_free[3]/1048576, 1)." MB", "$perc %"));
3095 }
3096
3097 $this->settings_debugrow(__('Plugins for debugging:', 'updraftplus'),'<a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=wp-crontrol'), 'install-plugin_wp-crontrol').'">WP Crontrol</a> | <a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=sql-executioner'), 'install-plugin_sql-executioner').'">SQL Executioner</a> | <a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=advanced-code-editor'), 'install-plugin_advanced-code-editor').'">Advanced Code Editor</a> '.(current_user_can('edit_plugins') ? '<a href="'.self_admin_url('plugin-editor.php?file=updraftplus/updraftplus.php').'">(edit UpdraftPlus)</a>' : '').' | <a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=wp-filemanager'), 'install-plugin_wp-filemanager').'">WP Filemanager</a>');
3098
3099 $this->settings_debugrow("HTTP Get: ", '<input id="updraftplus_httpget_uri" type="text" class="call-action"> <a href="#" id="updraftplus_httpget_go">'.__('Fetch', 'updraftplus').'</a> <a href="#" id="updraftplus_httpget_gocurl">'.__('Fetch', 'updraftplus').' (Curl)</a><p id="updraftplus_httpget_results"></p>');
3100
3101 $this->settings_debugrow(__("Call WordPress action:", 'updraftplus'), '<input id="updraftplus_callwpaction" type="text" class="call-action"> <a href="#" id="updraftplus_callwpaction_go">'.__('Call', 'updraftplus').'</a><div id="updraftplus_callwpaction_results"></div>');
3102
3103 $this->settings_debugrow('Site ID:', '(used to identify any Vault connections) <span id="updraft_show_sid">'.htmlspecialchars($updraftplus->siteid()).'</span> - <a href="#" id="updraft_reset_sid">'.__('reset', 'updraftplus')."</a>");
3104
3105 $this->settings_debugrow('', '<a href="admin-ajax.php?page=updraftplus&action=updraft_ajax&subaction=backuphistoryraw&nonce='.wp_create_nonce('updraftplus-credentialtest-nonce').'" id="updraftplus-rawbackuphistory">'.__('Show raw backup and file list', 'updraftplus').'</a>');
3106
3107 echo '</table>';
3108
3109 do_action('updraftplus_debugtools_dashboard');
3110
3111 if (!class_exists('UpdraftPlus_Addon_LockAdmin')) {
3112 echo '<p class="updraftplus-lock-advert"><a href="https://updraftplus.com/shop/updraftplus-premium/"><em>'.__('For the ability to lock access to UpdraftPlus settings with a password, upgrade to UpdraftPlus Premium.', 'updraftplus').'</em></a></p>';
3113 }
3114
3115 echo '<h3>'.__('Total (uncompressed) on-disk data:','updraftplus').'</h3>';
3116 echo '<p class="uncompressed-data"><em>'.__('N.B. This count is based upon what was, or was not, excluded the last time you saved the options.', 'updraftplus').'</em></p><table>';
3117
3118 foreach ($backupable_entities as $key => $info) {
3119
3120 $sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']);
3121 if (strlen($sdescrip) > 20 && isset($info['shortdescription'])) $sdescrip = $info['shortdescription'];
3122
3123 // echo '<div style="clear: left;float:left; width:150px;">'.ucfirst($sdescrip).':</strong></div><div style="float:left;"><span id="updraft_diskspaceused_'.$key.'"><em></em></span> <a href="#" onclick="updraftplus_diskspace_entity(\''.$key.'\'); return false;">'.__('count','updraftplus').'</a></div>';
3124 $this->settings_debugrow(ucfirst($sdescrip).':', '<span id="updraft_diskspaceused_'.$key.'"><em></em></span> <a href="#" onclick="updraftplus_diskspace_entity(\''.$key.'\'); return false;">'.__('count','updraftplus').'</a>');
3125 }
3126
3127 ?>
3128
3129 </table>
3130 <p class="immediate-run"><?php _e('The buttons below will immediately execute a backup run, independently of WordPress\'s scheduler. If these work whilst your scheduled backups do absolutely nothing (i.e. not even produce a log file), then it means that your scheduler is broken.','updraftplus');?> <a href="https://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/"><?php _e('Go here for more information.', 'updraftplus'); ?></a></p>
3131
3132 <table border="0" class="debug-table">
3133 <tbody>
3134 <tr>
3135 <td>
3136 <form method="post" action="<?php echo esc_url(add_query_arg(array('error' => false, 'updraft_restore_success' => false, 'action' => false, 'page' => 'updraftplus'))); ?>">
3137 <input type="hidden" name="action" value="updraft_backup_debug_all" />
3138 <p><input type="submit" class="button-primary" <?php echo $backup_disabled ?> value="<?php _e('Debug Full Backup','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will cause an immediate backup. The page will stall loading until it finishes (ie, unscheduled).','updraftplus'));?>'))" /></p>
3139 </form>
3140 </td><td>
3141 <form method="post" action="<?php echo esc_url(add_query_arg(array('error' => false, 'updraft_restore_success' => false, 'action' => false, 'page' => 'updraftplus'))); ?>">
3142 <input type="hidden" name="action" value="updraft_backup_debug_db" />
3143 <p><input type="submit" class="button-primary" <?php echo $backup_disabled ?> value="<?php _e('Debug Database Backup','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will cause an immediate DB backup. The page will stall loading until it finishes (ie, unscheduled). The backup may well run out of time; really this button is only helpful for checking that the backup is able to get through the initial stages, or for small WordPress sites..','updraftplus'));?>'))" /></p>
3144 </form>
3145 </td>
3146 </tr>
3147 </tbody>
3148 </table>
3149 <h3><?php _e('Wipe settings', 'updraftplus');?></h3>
3150 <p class="max-width-600"><?php echo __('This button will delete all UpdraftPlus settings and progress information for in-progress backups (but not any of your existing backups from your cloud storage).', 'updraftplus').' '.__('You will then need to enter all your settings again. You can also do this before deactivating/deinstalling UpdraftPlus if you wish.','updraftplus');?></p>
3151 <form method="post" action="<?php echo esc_url(add_query_arg(array('error' => false, 'updraft_restore_success' => false, 'action' => false, 'page' => 'updraftplus'))); ?>">
3152 <input type="hidden" name="action" value="updraft_wipesettings" />
3153 <p><input type="submit" class="button-primary" value="<?php _e('Wipe settings','updraftplus'); ?>" onclick="return(confirm('<?php echo esc_js(__('This will delete all your UpdraftPlus settings - are you sure you want to do this?', 'updraftplus'));?>'))" /></p>
3154 </form>
3155 </div>
3156 <?php
3157 }
3158
3159 private function print_delete_old_dirs_form($include_blurb = true, $include_div = true) {
3160 if ($include_blurb) {
3161 if ($include_div) {
3162 echo '<div id="updraft_delete_old_dirs_pagediv" class="updated delete-old-directories">';
3163 }
3164 echo '<p>'.__('Your WordPress install has old directories from its state before you restored/migrated (technical information: these are suffixed with -old). You should press this button to delete them as soon as you have verified that the restoration worked.','updraftplus').'</p>';
3165 }
3166 ?>
3167 <form method="post" onsubmit="return updraft_delete_old_dirs();" action="<?php echo esc_url(add_query_arg(array('error' => false, 'updraft_restore_success' => false, 'action' => false, 'page' => 'updraftplus'))); ?>">
3168 <?php wp_nonce_field('updraftplus-credentialtest-nonce'); ?>
3169 <input type="hidden" name="action" value="updraft_delete_old_dirs">
3170 <input type="submit" class="button-primary" value="<?php echo esc_attr(__('Delete Old Directories', 'updraftplus'));?>" />
3171 </form>
3172 <?php
3173 if ($include_blurb && $include_div) echo '</div>';
3174 }
3175
3176 private function get_cron($job_id = false) {
3177
3178 $cron = get_option('cron');
3179 if (!is_array($cron)) $cron = array();
3180 if (false === $job_id) return $cron;
3181
3182 foreach ($cron as $time => $job) {
3183 if (isset($job['updraft_backup_resume'])) {
3184 foreach ($job['updraft_backup_resume'] as $hook => $info) {
3185 if (isset($info['args'][1]) && $job_id == $info['args'][1]) {
3186 global $updraftplus;
3187 $jobdata = $updraftplus->jobdata_getarray($job_id);
3188 return (!is_array($jobdata)) ? false : array($time, $jobdata);
3189 }
3190 }
3191 }
3192 }
3193 }
3194
3195 // A value for $this_job_only also causes something to always be returned (to allow detection of the job having started on the front-end)
3196 private function print_active_jobs($this_job_only = false) {
3197 $cron = $this->get_cron();
3198 // $found_jobs = 0;
3199 $ret = '';
3200
3201 foreach ($cron as $time => $job) {
3202 if (isset($job['updraft_backup_resume'])) {
3203 foreach ($job['updraft_backup_resume'] as $hook => $info) {
3204 if (isset($info['args'][1])) {
3205 // $found_jobs++;
3206 $job_id = $info['args'][1];
3207 if (false === $this_job_only || $job_id == $this_job_only) {
3208 $ret .= $this->print_active_job($job_id, false, $time, $info['args'][0]);
3209 }
3210 }
3211 }
3212 }
3213 }
3214
3215 // A value for $this_job_only implies that output is required
3216 if (false !== $this_job_only && !$ret) {
3217 $ret = $this->print_active_job($this_job_only);
3218 if ('' == $ret) {
3219 // The presence of the exact ID matters to the front-end - indicates that the backup job has at least begun
3220 $ret = '<div class="active-jobs updraft_finished" id="updraft-jobid-'.$this_job_only.'"><em>'.__('The backup has finished running', 'updraftplus').'</em> - <a class="updraft-log-link" data-jobid="'.$this_job_only.'">'.__('View Log', 'updraftplus').'</a></div>';
3221 }
3222 }
3223
3224 // if (0 == $found_jobs) $ret .= '<p><em>'.__('(None)', 'updraftplus').'</em></p>';
3225 return $ret;
3226 }
3227
3228 private function print_active_job($job_id, $is_oneshot = false, $time = false, $next_resumption = false) {
3229
3230 $ret = '';
3231
3232 global $updraftplus;
3233 $jobdata = $updraftplus->jobdata_getarray($job_id);
3234
3235 if (false == apply_filters('updraftplus_print_active_job_continue', true, $is_oneshot, $next_resumption, $jobdata)) return '';
3236
3237 #if (!is_array($jobdata)) $jobdata = array();
3238 if (!isset($jobdata['backup_time'])) return '';
3239
3240 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
3241
3242 $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') : '?';
3243
3244 $jobstatus = empty($jobdata['jobstatus']) ? 'unknown' : $jobdata['jobstatus'];
3245 $stage = 0;
3246 switch ($jobstatus) {
3247 # Stage 0
3248 case 'begun':
3249 $curstage = __('Backup begun', 'updraftplus');
3250 break;
3251 # Stage 1
3252 case 'filescreating':
3253 $stage = 1;
3254 $curstage = __('Creating file backup zips', 'updraftplus');
3255 if (!empty($jobdata['filecreating_substatus']) && isset($backupable_entities[$jobdata['filecreating_substatus']['e']]['description'])) {
3256
3257 $sdescrip = preg_replace('/ \(.*\)$/', '', $backupable_entities[$jobdata['filecreating_substatus']['e']]['description']);
3258 if (strlen($sdescrip) > 20 && isset($jobdata['filecreating_substatus']['e']) && is_array($jobdata['filecreating_substatus']['e']) && isset($backupable_entities[$jobdata['filecreating_substatus']['e']]['shortdescription'])) $sdescrip = $backupable_entities[$jobdata['filecreating_substatus']['e']]['shortdescription'];
3259 $curstage .= ' ('.$sdescrip.')';
3260 if (isset($jobdata['filecreating_substatus']['i']) && isset($jobdata['filecreating_substatus']['t'])) {
3261 $stage = min(2, 1 + ($jobdata['filecreating_substatus']['i']/max($jobdata['filecreating_substatus']['t'],1)));
3262 }
3263 }
3264 break;
3265 case 'filescreated':
3266 $stage = 2;
3267 $curstage = __('Created file backup zips', 'updraftplus');
3268 break;
3269
3270 # Stage 4
3271 case 'clouduploading':
3272 $stage = 4;
3273 $curstage = __('Uploading files to remote storage', 'updraftplus');
3274 if (isset($jobdata['uploading_substatus']['t']) && isset($jobdata['uploading_substatus']['i'])) {
3275 $t = max((int)$jobdata['uploading_substatus']['t'], 1);
3276 $i = min($jobdata['uploading_substatus']['i']/$t, 1);
3277 $p = min($jobdata['uploading_substatus']['p'], 1);
3278 $pd = $i + $p/$t;
3279 $stage = 4 + $pd;
3280 $curstage .= ' '.sprintf(__('(%s%%, file %s of %s)', 'updraftplus'), floor(100*$pd), $jobdata['uploading_substatus']['i']+1, $t);
3281 }
3282 break;
3283 case 'pruning':
3284 $stage = 5;
3285 $curstage = __('Pruning old backup sets', 'updraftplus');
3286 break;
3287 case 'resumingforerrors':
3288 $stage = -1;
3289 $curstage = __('Waiting until scheduled time to retry because of errors', 'updraftplus');
3290 break;
3291 # Stage 6
3292 case 'finished':
3293 $stage = 6;
3294 $curstage = __('Backup finished', 'updraftplus');
3295 break;
3296 default:
3297
3298 # Database creation and encryption occupies the space from 2 to 4. Databases are created then encrypted, then the next databae is created/encrypted, etc.
3299 if ('dbcreated' == substr($jobstatus, 0, 9)) {
3300 $jobstatus = 'dbcreated';
3301 $whichdb = substr($jobstatus, 9);
3302 if (!is_numeric($whichdb)) $whichdb = 0;
3303 $howmanydbs = max((empty($jobdata['backup_database']) || !is_array($jobdata['backup_database'])) ? 1 : count($jobdata['backup_database']), 1);
3304 $perdbspace = 2/$howmanydbs;
3305
3306 $stage = min(4, 2 + ($whichdb+2)*$perdbspace);
3307
3308 $curstage = __('Created database backup', 'updraftplus');
3309
3310 } elseif ('dbcreating' == substr($jobstatus, 0, 10)) {
3311 $whichdb = substr($jobstatus, 10);
3312 if (!is_numeric($whichdb)) $whichdb = 0;
3313 $howmanydbs = (empty($jobdata['backup_database']) || !is_array($jobdata['backup_database'])) ? 1 : count($jobdata['backup_database']);
3314 $perdbspace = 2/$howmanydbs;
3315 $jobstatus = 'dbcreating';
3316
3317 $stage = min(4, 2 + $whichdb*$perdbspace);
3318
3319 $curstage = __('Creating database backup', 'updraftplus');
3320 if (!empty($jobdata['dbcreating_substatus']['t'])) {
3321 $curstage .= ' ('.sprintf(__('table: %s', 'updraftplus'), $jobdata['dbcreating_substatus']['t']).')';
3322 if (!empty($jobdata['dbcreating_substatus']['i']) && !empty($jobdata['dbcreating_substatus']['a'])) {
3323 $substage = max(0.001, ($jobdata['dbcreating_substatus']['i'] / max($jobdata['dbcreating_substatus']['a'],1)));
3324 $stage += $substage * $perdbspace * 0.5;
3325 }
3326 }
3327 } elseif ('dbencrypting' == substr($jobstatus, 0, 12)) {
3328 $whichdb = substr($jobstatus, 12);
3329 if (!is_numeric($whichdb)) $whichdb = 0;
3330 $howmanydbs = (empty($jobdata['backup_database']) || !is_array($jobdata['backup_database'])) ? 1 : count($jobdata['backup_database']);
3331 $perdbspace = 2/$howmanydbs;
3332 $stage = min(4, 2 + $whichdb*$perdbspace + $perdbspace*0.5);
3333 $jobstatus = 'dbencrypting';
3334 $curstage = __('Encrypting database', 'updraftplus');
3335 } elseif ('dbencrypted' == substr($jobstatus, 0, 11)) {
3336 $whichdb = substr($jobstatus, 11);
3337 if (!is_numeric($whichdb)) $whichdb = 0;
3338 $howmanydbs = (empty($jobdata['backup_database']) || !is_array($jobdata['backup_database'])) ? 1 : count($jobdata['backup_database']);
3339 $jobstatus = 'dbencrypted';
3340 $perdbspace = 2/$howmanydbs;
3341 $stage = min(4, 2 + $whichdb*$perdbspace + $perdbspace);
3342 $curstage = __('Encrypted database', 'updraftplus');
3343 } else {
3344 $curstage = __('Unknown', 'updraftplus');
3345 }
3346 }
3347
3348 $runs_started = (empty($jobdata['runs_started'])) ? array() : $jobdata['runs_started'];
3349 $time_passed = (empty($jobdata['run_times'])) ? array() : $jobdata['run_times'];
3350 $last_checkin_ago = -1;
3351 if (is_array($time_passed)) {
3352 foreach ($time_passed as $run => $passed) {
3353 if (isset($runs_started[$run])) {
3354 $time_ago = microtime(true) - ($runs_started[$run] + $time_passed[$run]);
3355 if ($time_ago < $last_checkin_ago || $last_checkin_ago == -1) $last_checkin_ago = $time_ago;
3356 }
3357 }
3358 }
3359
3360 $next_res_after = (int)$time-time();
3361 $next_res_txt = ($is_oneshot) ? '' : ' - '.sprintf(__("next resumption: %d (after %ss)", 'updraftplus'), $next_resumption, $next_res_after). ' ';
3362 $last_activity_txt = ($last_checkin_ago >= 0) ? ' - '.sprintf(__('last activity: %ss ago', 'updraftplus'), floor($last_checkin_ago)).' ' : '';
3363
3364 if (($last_checkin_ago < 50 && $next_res_after>30) || $is_oneshot) {
3365 $show_inline_info = $last_activity_txt;
3366 $title_info = $next_res_txt;
3367 } else {
3368 $show_inline_info = $next_res_txt;
3369 $title_info = $last_activity_txt;
3370 }
3371
3372 // Existence of the 'updraft-jobid-(id)' id is checked for in other places, so do not modify this
3373 $ret .= '<div class="job-id" id="updraft-jobid-'.$job_id.'"><span class="updraft_jobtimings next-resumption';
3374
3375 if (!empty($jobdata['is_autobackup'])) $ret .= ' isautobackup';
3376
3377 $ret .= '" data-jobid="'.$job_id.'" data-lastactivity="'.(int)$last_checkin_ago.'" data-nextresumption="'.$next_resumption.'" data-nextresumptionafter="'.$next_res_after.'" title="'.esc_attr(sprintf(__('Job ID: %s', 'updraftplus'), $job_id)).$title_info.'">'.$began_at.'</span> ';
3378
3379 $ret .= $show_inline_info;
3380 $ret .= '- <a data-jobid="'.$job_id.'" href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=downloadlog&updraftplus_backup_nonce='.$job_id.'" class="updraft-log-link">'.__('show log', 'updraftplus').'</a>';
3381
3382 if (!$is_oneshot) $ret .=' - <a href="#" data-jobid="'.$job_id.'" title="'.esc_attr(__('Note: the progress bar below is based on stages, NOT time. Do not stop the backup simply because it seems to have remained in the same place for a while - that is normal.', 'updraftplus')).'" class="updraft_jobinfo_delete">'.__('stop', 'updraftplus').'</a>';
3383
3384 $ret .= apply_filters('updraft_printjob_beforewarnings', '', $jobdata, $job_id);
3385
3386 if (!empty($jobdata['warnings']) && is_array($jobdata['warnings'])) {
3387 $ret .= '<ul class="disc">';
3388 foreach ($jobdata['warnings'] as $warning) {
3389 $ret .= '<li>'.sprintf(__('Warning: %s', 'updraftplus'), make_clickable(htmlspecialchars($warning))).'</li>';
3390 }
3391 $ret .= '</ul>';
3392 }
3393
3394 $ret .= '<div class="curstage">';
3395 $ret .= htmlspecialchars($curstage);
3396 $ret .= '<div class="updraft_percentage" style="height: 100%; width:'.(($stage>0) ? (ceil((100/6)*$stage)) : '0').'%"></div>';
3397 $ret .= '</div></div>';
3398
3399 $ret .= '</div>';
3400
3401 return $ret;
3402
3403 }
3404
3405 private function delete_old_dirs_go($show_return = true) {
3406 echo ($show_return) ? '<h1>UpdraftPlus - '.__('Remove old directories', 'updraftplus').'</h1>' : '<h2>'.__('Remove old directories', 'updraftplus').'</h2>';
3407
3408 if ($this->delete_old_dirs()) {
3409 echo '<p>'.__('Old directories successfully removed.','updraftplus').'</p><br/>';
3410 } else {
3411 echo '<p>',__('Old directory removal failed for some reason. You may want to do this manually.','updraftplus').'</p><br/>';
3412 }
3413 if ($show_return) echo '<b>'.__('Actions','updraftplus').':</b> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
3414 }
3415
3416 //deletes the -old directories that are created when a backup is restored.
3417 private function delete_old_dirs() {
3418 global $wp_filesystem, $updraftplus;
3419 $credentials = request_filesystem_credentials(wp_nonce_url(UpdraftPlus_Options::admin_page_url()."?page=updraftplus&action=updraft_delete_old_dirs", 'updraftplus-credentialtest-nonce'));
3420 WP_Filesystem($credentials);
3421 if ($wp_filesystem->errors->get_error_code()) {
3422 foreach ($wp_filesystem->errors->get_error_messages() as $message)
3423 show_message($message);
3424 exit;
3425 }
3426 // From WP_CONTENT_DIR - which contains 'themes'
3427 $ret = $this->delete_old_dirs_dir($wp_filesystem->wp_content_dir());
3428
3429 $updraft_dir = $updraftplus->backups_dir_location();
3430 if ($updraft_dir) {
3431 $ret4 = ($updraft_dir) ? $this->delete_old_dirs_dir($updraft_dir, false) : true;
3432 } else {
3433 $ret4 = true;
3434 }
3435
3436 // $ret2 = $this->delete_old_dirs_dir($wp_filesystem->abspath());
3437 $plugs = untrailingslashit($wp_filesystem->wp_plugins_dir());
3438 if ($wp_filesystem->is_dir($plugs.'-old')) {
3439 print "<strong>".__('Delete','updraftplus').": </strong>plugins-old: ";
3440 if (!$wp_filesystem->delete($plugs.'-old', true)) {
3441 $ret3 = false;
3442 print "<strong>".__('Failed', 'updraftplus')."</strong><br>";
3443 } else {
3444 $ret3 = true;
3445 print "<strong>".__('OK', 'updraftplus')."</strong><br>";
3446 }
3447 } else {
3448 $ret3 = true;
3449 }
3450
3451 return $ret && $ret3 && $ret4;
3452 }
3453
3454 private function delete_old_dirs_dir($dir, $wpfs = true) {
3455
3456 $dir = trailingslashit($dir);
3457
3458 global $wp_filesystem, $updraftplus;
3459
3460 if ($wpfs) {
3461 $list = $wp_filesystem->dirlist($dir);
3462 } else {
3463 $list = scandir($dir);
3464 }
3465 if (!is_array($list)) return false;
3466
3467 $ret = true;
3468 foreach ($list as $item) {
3469 $name = (is_array($item)) ? $item['name'] : $item;
3470 if ("-old" == substr($name, -4, 4)) {
3471 //recursively delete
3472 print "<strong>".__('Delete','updraftplus').": </strong>".htmlspecialchars($name).": ";
3473
3474 if ($wpfs) {
3475 if (!$wp_filesystem->delete($dir.$name, true)) {
3476 $ret = false;
3477 echo "<strong>".__('Failed', 'updraftplus')."</strong><br>";
3478 } else {
3479 echo "<strong>".__('OK', 'updraftplus')."</strong><br>";
3480 }
3481 } else {
3482 if ($updraftplus->remove_local_directory($dir.$name)) {
3483 echo "<strong>".__('OK', 'updraftplus')."</strong><br>";
3484 } else {
3485 $ret = false;
3486 echo "<strong>".__('Failed', 'updraftplus')."</strong><br>";
3487 }
3488 }
3489 }
3490 }
3491 return $ret;
3492 }
3493
3494 // The aim is to get a directory that is writable by the webserver, because that's the only way we can create zip files
3495 private function create_backup_dir() {
3496
3497 global $wp_filesystem, $updraftplus;
3498
3499 if (false === ($credentials = request_filesystem_credentials(UpdraftPlus_Options::admin_page().'?page=updraftplus&action=updraft_create_backup_dir&nonce='.wp_create_nonce('create_backup_dir')))) {
3500 return false;
3501 }
3502
3503 if ( ! WP_Filesystem($credentials) ) {
3504 // our credentials were no good, ask the user for them again
3505 request_filesystem_credentials(UpdraftPlus_Options::admin_page().'?page=updraftplus&action=updraft_create_backup_dir&nonce='.wp_create_nonce('create_backup_dir'), '', true);
3506 return false;
3507 }
3508
3509 $updraft_dir = $updraftplus->backups_dir_location();
3510
3511 $default_backup_dir = $wp_filesystem->find_folder(dirname($updraft_dir)).basename($updraft_dir);
3512
3513 $updraft_dir = ($updraft_dir) ? $wp_filesystem->find_folder(dirname($updraft_dir)).basename($updraft_dir) : $default_backup_dir;
3514
3515 if (!$wp_filesystem->is_dir($default_backup_dir) && !$wp_filesystem->mkdir($default_backup_dir, 0775)) {
3516 $wperr = new WP_Error;
3517 if ( $wp_filesystem->errors->get_error_code() ) {
3518 foreach ( $wp_filesystem->errors->get_error_messages() as $message ) {
3519 $wperr->add('mkdir_error', $message);
3520 }
3521 return $wperr;
3522 } else {
3523 return new WP_Error('mkdir_error', __('The request to the filesystem to create the directory failed.', 'updraftplus'));
3524 }
3525 }
3526
3527 if ($wp_filesystem->is_dir($default_backup_dir)) {
3528
3529 if ($updraftplus->really_is_writable($updraft_dir)) return true;
3530
3531 @$wp_filesystem->chmod($default_backup_dir, 0775);
3532 if ($updraftplus->really_is_writable($updraft_dir)) return true;
3533
3534 @$wp_filesystem->chmod($default_backup_dir, 0777);
3535
3536 if ($updraftplus->really_is_writable($updraft_dir)) {
3537 echo '<p>'.__('The folder was created, but we had to change its file permissions to 777 (world-writable) to be able to write to it. You should check with your hosting provider that this will not cause any problems', 'updraftplus').'</p>';
3538 return true;
3539 } else {
3540 @$wp_filesystem->chmod($default_backup_dir, 0775);
3541 $show_dir = (0 === strpos($default_backup_dir, ABSPATH)) ? substr($default_backup_dir, strlen(ABSPATH)) : $default_backup_dir;
3542 return new WP_Error('writable_error', __('The folder exists, but your webserver does not have permission to write to it.', 'updraftplus').' '.__('You will need to consult with your web hosting provider to find out how to set permissions for a WordPress plugin to write to the directory.', 'updraftplus').' ('.$show_dir.')');
3543 }
3544 }
3545
3546 return true;
3547 }
3548
3549 //scans the content dir to see if any -old dirs are present
3550 private function scan_old_dirs($print_as_comment = false) {
3551 global $updraftplus;
3552 $dirs = scandir(untrailingslashit(WP_CONTENT_DIR));
3553 if (!is_array($dirs)) $dirs = array();
3554 $dirs_u = @scandir($updraftplus->backups_dir_location());
3555 if (!is_array($dirs_u)) $dirs_u = array();
3556 foreach (array_merge($dirs, $dirs_u) as $dir) {
3557 if (preg_match('/-old$/', $dir)) {
3558 if ($print_as_comment) echo '<!--'.htmlspecialchars($dir).'-->';
3559 return true;
3560 }
3561 }
3562 # No need to scan ABSPATH - we don't backup there
3563 if (is_dir(untrailingslashit(WP_PLUGIN_DIR).'-old')) {
3564 if ($print_as_comment) echo '<!--'.htmlspecialchars(untrailingslashit(WP_PLUGIN_DIR).'-old').'-->';
3565 return true;
3566 }
3567 return false;
3568 }
3569
3570 public function storagemethod_row($method, $header, $contents) {
3571 ?>
3572 <tr class="updraftplusmethod <?php echo $method;?>">
3573 <th><?php echo $header;?></th>
3574 <td><?php echo $contents;?></td>
3575 </tr>
3576 <?php
3577 }
3578
3579 private function last_backup_html() {
3580
3581 global $updraftplus;
3582
3583 $updraft_last_backup = UpdraftPlus_Options::get_updraft_option('updraft_last_backup');
3584
3585 if ($updraft_last_backup) {
3586
3587 // Convert to GMT, then to blog time
3588 $backup_time = (int)$updraft_last_backup['backup_time'];
3589
3590 $print_time = get_date_from_gmt(gmdate('Y-m-d H:i:s', $backup_time), 'D, F j, Y H:i');
3591 // $print_time = date_i18n('D, F j, Y H:i', $backup_time);
3592
3593 if (empty($updraft_last_backup['backup_time_incremental'])) {
3594 $last_backup_text = "<span style=\"color:".(($updraft_last_backup['success']) ? 'green' : 'black').";\">".$print_time.'</span>';
3595 } else {
3596 $inc_time = get_date_from_gmt(gmdate('Y-m-d H:i:s', $updraft_last_backup['backup_time_incremental']), 'D, F j, Y H:i');
3597 // $inc_time = date_i18n('D, F j, Y H:i', $updraft_last_backup['backup_time_incremental']);
3598 $last_backup_text = "<span style=\"color:".(($updraft_last_backup['success']) ? 'green' : 'black').";\">$inc_time</span> (".sprintf(__('incremental backup; base backup: %s', 'updraftplus'), $print_time).')';
3599 }
3600
3601 $last_backup_text .= '<br>';
3602
3603 // Show errors + warnings
3604 if (is_array($updraft_last_backup['errors'])) {
3605 foreach ($updraft_last_backup['errors'] as $err) {
3606 $level = (is_array($err)) ? $err['level'] : 'error';
3607 $message = (is_array($err)) ? $err['message'] : $err;
3608 $last_backup_text .= ('warning' == $level) ? "<span style=\"color:orange;\">" : "<span style=\"color:red;\">";
3609 if ('warning' == $level) {
3610 $message = sprintf(__("Warning: %s", 'updraftplus'), make_clickable(htmlspecialchars($message)));
3611 } else {
3612 $message = htmlspecialchars($message);
3613 }
3614 $last_backup_text .= $message;
3615 $last_backup_text .= '</span><br>';
3616 }
3617 }
3618
3619 // Link log
3620 if (!empty($updraft_last_backup['backup_nonce'])) {
3621 $updraft_dir = $updraftplus->backups_dir_location();
3622
3623 $potential_log_file = $updraft_dir."/log.".$updraft_last_backup['backup_nonce'].".txt";
3624 if (is_readable($potential_log_file)) $last_backup_text .= "<a href=\"?page=updraftplus&action=downloadlog&updraftplus_backup_nonce=".$updraft_last_backup['backup_nonce']."\" class=\"updraft-log-link\" onclick=\"event.preventDefault(); updraft_popuplog('".$updraft_last_backup['backup_nonce']."');\">".__('Download log file','updraftplus')."</a>";
3625 }
3626
3627 } else {
3628 $last_backup_text = "<span style=\"color:blue;\">".__('No backup has been completed','updraftplus')."</span>";
3629 }
3630
3631 return $last_backup_text;
3632
3633 }
3634
3635 public function get_intervals() {
3636 return apply_filters('updraftplus_backup_intervals', array(
3637 'manual' => _x("Manual", 'i.e. Non-automatic', 'updraftplus'),
3638 'every4hours' => sprintf(__("Every %s hours", 'updraftplus'), '4'),
3639 'every8hours' => sprintf(__("Every %s hours", 'updraftplus'), '8'),
3640 'twicedaily' => sprintf(__("Every %s hours", 'updraftplus'), '12'),
3641 'daily' => __("Daily", 'updraftplus'),
3642 'weekly' => __("Weekly", 'updraftplus'),
3643 'fortnightly' => __("Fortnightly", 'updraftplus'),
3644 'monthly' => __("Monthly", 'updraftplus')
3645 ));
3646 }
3647
3648 private function really_writable_message($really_is_writable, $updraft_dir){
3649 if ($really_is_writable) {
3650 $dir_info = '<span style="color:green;">'.__('Backup directory specified is writable, which is good.','updraftplus').'</span>';
3651 } else {
3652 $dir_info = '<span style="color:red;">';
3653 if (!is_dir($updraft_dir)) {
3654 $dir_info .= __('Backup directory specified does <b>not</b> exist.','updraftplus');
3655 } else {
3656 $dir_info .= __('Backup directory specified exists, but is <b>not</b> writable.','updraftplus');
3657 }
3658 $dir_info .= '<span class="updraft-directory-not-writable-blurb"><span class="directory-permissions"><a class="updraft_create_backup_dir" href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraft_create_backup_dir&nonce='.wp_create_nonce('create_backup_dir').'">'.__('Click here to attempt to create the directory and set the permissions','updraftplus').'</a></span>, '.__('or, to reset this option','updraftplus').' <a href="#" class="updraft_backup_dir_reset">'.__('click here','updraftplus').'</a>. '.__('If that is unsuccessful check the permissions on your server or change it to another directory that is writable by your web server process.','updraftplus').'</span>';
3659 }
3660 return $dir_info;
3661 }
3662
3663 public function settings_formcontents($options = array()) {
3664
3665 global $updraftplus;
3666
3667 $updraft_dir = $updraftplus->backups_dir_location();
3668 $really_is_writable = $updraftplus->really_is_writable($updraft_dir);
3669
3670 $default_options = array(
3671 'include_database_decrypter' => true,
3672 'include_adverts' => true,
3673 'include_save_button' => true
3674 );
3675 foreach ($default_options as $k => $v) {
3676 if (!isset($options[$k])) $options[$k] = $v;
3677 }
3678
3679 ?>
3680 <table class="form-table">
3681 <tr>
3682 <th><?php _e('Files backup schedule','updraftplus'); ?>:</th>
3683 <td>
3684 <div style="float:left; clear:both;">
3685 <select class="updraft_interval" name="updraft_interval">
3686 <?php
3687 $intervals = $this->get_intervals();
3688 $selected_interval = UpdraftPlus_Options::get_updraft_option('updraft_interval', 'manual');
3689 foreach ($intervals as $cronsched => $descrip) {
3690 echo "<option value=\"$cronsched\" ";
3691 if ($cronsched == $selected_interval) echo 'selected="selected"';
3692 echo ">".htmlspecialchars($descrip)."</option>\n";
3693 }
3694 ?>
3695 </select> <span class="updraft_files_timings"><?php echo apply_filters('updraftplus_schedule_showfileopts', '<input type="hidden" name="updraftplus_starttime_files" value="">', $selected_interval); ?></span>
3696
3697
3698 <?php
3699
3700 $updraft_retain = max((int)UpdraftPlus_Options::get_updraft_option('updraft_retain', 2), 1);
3701
3702 $retain_files_config = __('and retain this many scheduled backups', 'updraftplus').': <input type="number" min="1" step="1" name="updraft_retain" value="'.$updraft_retain.'" class="retain-files" />';
3703
3704 // echo apply_filters('updraftplus_retain_files_intervalline', $retain_files_config, $updraft_retain);
3705 echo $retain_files_config;
3706
3707 ?>
3708 </div>
3709 <?php do_action('updraftplus_after_filesconfig'); ?>
3710 </td>
3711 </tr>
3712
3713 <?php if (defined('UPDRAFTPLUS_EXPERIMENTAL') && UPDRAFTPLUS_EXPERIMENTAL) { ?>
3714 <tr class="updraft_incremental_row">
3715 <th><?php _e('Incremental file backup schedule', 'updraftplus'); ?>:</th>
3716 <td>
3717 <?php do_action('updraftplus_incremental_cell', $selected_interval); ?>
3718 <a href="https://updraftplus.com/support/tell-me-more-about-incremental-backups/"><em><?php _e('Tell me more about incremental backups', 'updraftplus'); ?><em></a>
3719 </td>
3720 </tr>
3721 <?php } ?>
3722
3723 <?php apply_filters('updraftplus_after_file_intervals', false, $selected_interval); ?>
3724 <tr>
3725 <th><?php _e('Database backup schedule','updraftplus'); ?>:</th>
3726 <td>
3727 <div style="float:left; clear:both;">
3728 <select class="updraft_interval_database" name="updraft_interval_database">
3729 <?php
3730 $selected_interval_db = UpdraftPlus_Options::get_updraft_option('updraft_interval_database', UpdraftPlus_Options::get_updraft_option('updraft_interval'));
3731 foreach ($intervals as $cronsched => $descrip) {
3732 echo "<option value=\"$cronsched\" ";
3733 if ($cronsched == $selected_interval_db) echo 'selected="selected"';
3734 echo ">$descrip</option>\n";
3735 }
3736 ?>
3737 </select> <span class="updraft_same_schedules_message"><?php echo apply_filters('updraftplus_schedule_sametimemsg', '');?></span><span class="updraft_db_timings"><?php echo apply_filters('updraftplus_schedule_showdbopts', '<input type="hidden" name="updraftplus_starttime_db" value="">', $selected_interval_db); ?></span>
3738
3739 <?php
3740 $updraft_retain_db = max((int)UpdraftPlus_Options::get_updraft_option('updraft_retain_db', $updraft_retain), 1);
3741 $retain_dbs_config = __('and retain this many scheduled backups', 'updraftplus').': <input type="number" min="1" step="1" name="updraft_retain_db" value="'.$updraft_retain_db.'" class="retain-files" />';
3742
3743 // echo apply_filters('updraftplus_retain_db_intervalline', $retain_dbs_config, $updraft_retain_db);
3744 echo $retain_dbs_config;
3745 ?>
3746 </div>
3747 <?php do_action('updraftplus_after_dbconfig'); ?>
3748 </td>
3749 </tr>
3750 <tr class="backup-interval-description">
3751 <th></th>
3752 <td><div>
3753 <?php
3754 echo apply_filters('updraftplus_fixtime_ftinfo', '<p>'.__('To fix the time at which a backup should take place,','updraftplus').' ('.__('e.g. if your server is busy at day and you want to run overnight','updraftplus').'), '.__('or to configure more complex schedules', 'updraftplus').', <a href="https://updraftplus.com/shop/updraftplus-premium/">'.htmlspecialchars(__('use UpdraftPlus Premium', 'updraftplus')).'</a></p>');
3755 ?>
3756 </div></td>
3757 </tr>
3758 </table>
3759
3760 <h2 class="updraft_settings_sectionheading"><?php _e('Sending Your Backup To Remote Storage','updraftplus');?></h2>
3761
3762 <?php
3763 $debug_mode = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode') ? 'checked="checked"' : "";
3764 $active_service = UpdraftPlus_Options::get_updraft_option('updraft_service');
3765 ?>
3766
3767 <table class="form-table width-900">
3768 <tr>
3769 <th><?php
3770 echo __('Choose your remote storage','updraftplus').'<br>'.apply_filters('updraftplus_after_remote_storage_heading_message', '<em>'.__('(tap on an icon to select or unselect)', 'updraftplus').'</em>');
3771 ?>:</th>
3772 <td>
3773 <div id="remote-storage-container">
3774 <?php
3775 if (is_array($active_service)) $active_service = $updraftplus->just_one($active_service);
3776
3777 //Change this to give a class that we can exclude
3778 $multi = apply_filters('updraftplus_storage_printoptions_multi', '');
3779
3780 foreach($updraftplus->backup_methods as $method => $description) {
3781 echo "<input name=\"updraft_service[]\" class=\"updraft_servicecheckbox $method $multi\" id=\"updraft_servicecheckbox_$method\" type=\"checkbox\" value=\"$method\"";
3782 if ($active_service === $method || (is_array($active_service) && in_array($method, $active_service))) echo ' checked="checked"';
3783 echo " data-labelauty=\"".esc_attr($description)."\">";
3784 }
3785 ?>
3786
3787
3788 <?php
3789 if (false === apply_filters('updraftplus_storage_printoptions', false, $active_service)) {
3790
3791 echo '</div>';
3792 echo '<p><a href="https://updraftplus.com/shop/morestorage/">'.htmlspecialchars(__('You can send a backup to more than one destination with an add-on.','updraftplus')).'</a></p>';
3793 echo '</td></tr>';
3794 }
3795 ?>
3796
3797
3798 <tr class="updraftplusmethod none ud_nostorage" style="display:none;">
3799 <td></td>
3800 <td><em><?php echo htmlspecialchars(__('If you choose no remote storage, then the backups remain on the web-server. This is not recommended (unless you plan to manually copy them to your computer), as losing the web-server would mean losing both your website and the backups in one event.', 'updraftplus'));?></em></td>
3801 </tr>
3802
3803 <?php
3804 $method_objects = array();
3805 foreach ($updraftplus->backup_methods as $method => $description) {
3806 do_action('updraftplus_config_print_before_storage', $method);
3807 require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
3808 $call_method = 'UpdraftPlus_BackupModule_'.$method;
3809 $method_objects[$method] = new $call_method;
3810 $method_objects[$method]->config_print();
3811 do_action('updraftplus_config_print_after_storage', $method);
3812 }
3813 ?>
3814
3815 </table>
3816
3817 <hr style="width:900px; float:left;">
3818
3819 <h2 class="updraft_settings_sectionheading"><?php _e('File Options', 'updraftplus');?></h2>
3820
3821 <table class="form-table" >
3822 <tr>
3823 <th><?php _e('Include in files backup', 'updraftplus');?>:</th>
3824 <td>
3825 <?php echo $this->files_selector_widgetry(); ?>
3826 <p><?php echo apply_filters('updraftplus_admin_directories_description', __('The above directories are everything, except for WordPress core itself which you can download afresh from WordPress.org.', 'updraftplus').' <a href="https://updraftplus.com/shop/">'.htmlspecialchars(__('See also the "More Files" add-on from our shop.', 'updraftplus')).'</a>'); ?></p>
3827 </td>
3828 </tr>
3829 </table>
3830
3831 <h2 class="updraft_settings_sectionheading"><?php _e('Database Options','updraftplus');?></h2>
3832
3833 <table class="form-table width-900">
3834
3835 <tr>
3836 <th><?php _e('Database encryption phrase', 'updraftplus');?>:</th>
3837
3838 <td>
3839 <?php
3840 echo apply_filters('updraft_database_encryption_config', '<a href="https://updraftplus.com/shop/updraftplus-premium/">'.__("Don't want to be spied on? UpdraftPlus Premium can encrypt your database backup.", 'updraftplus').'</a> '.__('It can also backup external databases.', 'updraftplus'));
3841 ?>
3842 </td>
3843 </tr>
3844
3845 <?php if (!empty($options['include_database_decrypter'])) { ?>
3846
3847 <tr class="backup-crypt-description">
3848 <td></td>
3849
3850 <td>
3851
3852 <a href="#" class="updraft_show_decryption_widget"><?php _e('You can manually decrypt an encrypted database here.','updraftplus');?></a>
3853
3854 <div id="updraft-manualdecrypt-modal" class="updraft-hidden" style="display:none;">
3855 <p><h3><?php _e("Manually decrypt a database backup file" ,'updraftplus');?></h3></p>
3856
3857 <?php
3858 global $wp_version;
3859 if (version_compare($wp_version, '3.3', '<')) {
3860 echo '<em>'.sprintf(__('This feature requires %s version %s or later', 'updraftplus'), 'WordPress', '3.3').'</em>';
3861 } else {
3862 ?>
3863
3864 <div id="plupload-upload-ui2">
3865 <div id="drag-drop-area2">
3866 <div class="drag-drop-inside">
3867 <p class="drag-drop-info"><?php _e('Drop encrypted database files (db.gz.crypt files) here to upload them for decryption', 'updraftplus'); ?></p>
3868 <p><?php _ex('or', 'Uploader: Drop db.gz.crypt files here to upload them for decryption - or - Select Files', 'updraftplus'); ?></p>
3869 <p class="drag-drop-buttons"><input id="plupload-browse-button2" type="button" value="<?php esc_attr_e('Select Files', 'updraftplus'); ?>" class="button" /></p>
3870 <p style="margin-top: 18px;"><?php _e('First, enter the decryption key','updraftplus')?>: <input id="updraftplus_db_decrypt" type="text" size="12"></input></p>
3871 </div>
3872 </div>
3873 <div id="filelist2">
3874 </div>
3875 </div>
3876
3877 <?php } ?>
3878
3879 </div>
3880
3881
3882 </td>
3883 </tr>
3884
3885 <?php } ?>
3886
3887 <?php
3888 #'<a href="https://updraftplus.com/shop/updraftplus-premium/">'.__("This feature is part of UpdraftPlus Premium.", 'updraftplus').'</a>'
3889 $moredbs_config = apply_filters('updraft_database_moredbs_config', false);
3890 if (!empty($moredbs_config)) {
3891 ?>
3892
3893 <tr>
3894 <th><?php _e('Back up more databases', 'updraftplus');?>:</th>
3895 <td><?php echo $moredbs_config; ?>
3896 </td>
3897 </tr>
3898
3899 <?php } ?>
3900
3901 </table>
3902
3903 <h2 class="updraft_settings_sectionheading"><?php _e('Reporting','updraftplus');?></h2>
3904
3905 <table class="form-table" style="width:900px;">
3906
3907 <?php
3908 $report_rows = apply_filters('updraftplus_report_form', false);
3909 if (is_string($report_rows)) {
3910 echo $report_rows;
3911 } else {
3912 ?>
3913
3914 <tr>
3915 <th><?php _e('Email', 'updraftplus'); ?>:</th>
3916 <td>
3917 <?php
3918 $updraft_email = UpdraftPlus_Options::get_updraft_option('updraft_email');
3919 ?>
3920 <input type="checkbox" id="updraft_email" name="updraft_email" value="<?php esc_attr_e(get_bloginfo('admin_email')); ?>"<?php if (!empty($updraft_email)) echo ' checked="checked"';?> > <br><label for="updraft_email"><?php echo __("Check this box to have a basic report sent to", 'updraftplus').' <a href="'.admin_url('options-general.php').'">'.__("your site's admin address", 'updraftplus').'</a> ('.htmlspecialchars(get_bloginfo('admin_email')).")."; ?></label>
3921 <?php
3922 if (!class_exists('UpdraftPlus_Addon_Reporting')) echo '<a href="https://updraftplus.com/shop/reporting/">'.__('For more reporting features, use the Reporting add-on.', 'updraftplus').'</a>';
3923 ?>
3924 </td>
3925 </tr>
3926
3927 <?php } ?>
3928
3929 </table>
3930
3931 <script type="text/javascript">
3932 /* <![CDATA[ */
3933 <?php echo $this->get_settings_js($method_objects, $really_is_writable, $updraft_dir); ?>
3934 /* ]]> */
3935 </script>
3936 <table class="form-table width-900">
3937 <tr>
3938 <td colspan="2"><h2 class="updraft_settings_sectionheading"><?php _e('Advanced / Debugging Settings','updraftplus'); ?></h2></td>
3939 </tr>
3940
3941 <tr>
3942 <th><?php _e('Expert settings','updraftplus');?>:</th>
3943 <td><a class="enableexpertmode" href="#enableexpertmode"><?php _e('Show expert settings','updraftplus');?></a> - <?php _e("click this to show some further options; don't bother with this unless you have a problem or are curious.",'updraftplus');?> <?php do_action('updraftplus_expertsettingsdescription'); ?></td>
3944 </tr>
3945 <?php
3946 $delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
3947 $split_every_mb = UpdraftPlus_Options::get_updraft_option('updraft_split_every', 400);
3948 if (!is_numeric($split_every_mb)) $split_every_mb = 400;
3949 if ($split_every_mb < UPDRAFTPLUS_SPLIT_MIN) $split_every_mb = UPDRAFTPLUS_SPLIT_MIN;
3950 ?>
3951
3952 <tr class="expertmode updraft-hidden" style="display:none;">
3953 <th><?php _e('Debug mode','updraftplus');?>:</th>
3954 <td><input type="checkbox" id="updraft_debug_mode" name="updraft_debug_mode" value="1" <?php echo $debug_mode; ?> /> <br><label for="updraft_debug_mode"><?php _e('Check this to receive more information and emails on the backup process - useful if something is going wrong.','updraftplus');?> <?php _e('This will also cause debugging output from all plugins to be shown upon this screen - please do not be surprised to see these.', 'updraftplus');?></label></td>
3955 </tr>
3956
3957 <tr class="expertmode updraft-hidden" style="display:none;">
3958 <th><?php _e('Split archives every:','updraftplus');?></th>
3959 <td><input type="text" name="updraft_split_every" class="updraft_split_every" value="<?php echo $split_every_mb ?>" size="5" /> MB<br><?php echo sprintf(__('UpdraftPlus will split up backup archives when they exceed this file size. The default value is %s megabytes. Be careful to leave some margin if your web-server has a hard size limit (e.g. the 2 GB / 2048 MB limit on some 32-bit servers/file systems).','updraftplus'), 400); ?></td>
3960 </tr>
3961
3962 <tr class="deletelocal expertmode updraft-hidden" style="display:none;">
3963 <th><?php _e('Delete local backup','updraftplus');?>:</th>
3964 <td><input type="checkbox" id="updraft_delete_local" name="updraft_delete_local" value="1" <?php if ($delete_local) echo 'checked="checked"'; ?>> <br><label for="updraft_delete_local"><?php _e('Check this to delete any superfluous backup files from your server after the backup run finishes (i.e. if you uncheck, then any files despatched remotely will also remain locally, and any files being kept locally will not be subject to the retention limits).','updraftplus');?></label></td>
3965 </tr>
3966
3967 <tr class="expertmode backupdirrow updraft-hidden" style="display:none;">
3968 <th><?php _e('Backup directory','updraftplus');?>:</th>
3969 <td><input type="text" name="updraft_dir" id="updraft_dir" style="width:525px" value="<?php echo htmlspecialchars($this->prune_updraft_dir_prefix($updraft_dir)); ?>" /></td>
3970 </tr>
3971 <tr class="expertmode backupdirrow updraft-hidden" style="display:none;">
3972 <td></td>
3973 <td>
3974 <span id="updraft_writable_mess">
3975 <?php
3976 $dir_info = $this->really_writable_message($really_is_writable, $updraft_dir);
3977 echo $dir_info;
3978 ?>
3979 </span>
3980 <?php
3981 echo __("This is where UpdraftPlus will write the zip files it creates initially. This directory must be writable by your web server. It is relative to your content directory (which by default is called wp-content).", 'updraftplus').' '.__("<b>Do not</b> place it inside your uploads or plugins directory, as that will cause recursion (backups of backups of backups of...).", 'updraftplus');
3982 ?>
3983 </td>
3984 </tr>
3985
3986 <tr class="expertmode updraft-hidden" style="display:none;">
3987 <th><?php _e("Use the server's SSL certificates", 'updraftplus');?>:</th>
3988 <td><input data-updraft_settings_test="useservercerts" type="checkbox" id="updraft_ssl_useservercerts" name="updraft_ssl_useservercerts" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_useservercerts')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_useservercerts"><?php _e('By default UpdraftPlus uses its own store of SSL certificates to verify the identity of remote sites (i.e. to make sure it is talking to the real Dropbox, Amazon S3, etc., and not an attacker). We keep these up to date. However, if you get an SSL error, then choosing this option (which causes UpdraftPlus to use your web server\'s collection instead) may help.','updraftplus');?></label></td>
3989 </tr>
3990
3991 <tr class="expertmode updraft-hidden" style="display:none;">
3992 <th><?php _e('Do not verify SSL certificates','updraftplus');?>:</th>
3993 <td><input data-updraft_settings_test="disableverify" type="checkbox" id="updraft_ssl_disableverify" name="updraft_ssl_disableverify" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_disableverify')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_disableverify"><?php _e('Choosing this option lowers your security by stopping UpdraftPlus from verifying the identity of encrypted sites that it connects to (e.g. Dropbox, Google Drive). It means that UpdraftPlus will be using SSL only for encryption of traffic, and not for authentication.','updraftplus');?> <?php _e('Note that not all cloud backup methods are necessarily using SSL authentication.', 'updraftplus');?></label></td>
3994 </tr>
3995
3996 <tr class="expertmode updraft-hidden" style="display:none;">
3997 <th><?php _e('Disable SSL entirely where possible', 'updraftplus');?>:</th>
3998 <td><input data-updraft_settings_test="nossl" type="checkbox" id="updraft_ssl_nossl" name="updraft_ssl_nossl" value="1" <?php if (UpdraftPlus_Options::get_updraft_option('updraft_ssl_nossl')) echo 'checked="checked"'; ?>> <br><label for="updraft_ssl_nossl"><?php _e('Choosing this option lowers your security by stopping UpdraftPlus from using SSL for authentication and encrypted transport at all, where possible. Note that some cloud storage providers do not allow this (e.g. Dropbox), so with those providers this setting will have no effect.','updraftplus');?> <a href="https://updraftplus.com/faqs/i-get-ssl-certificate-errors-when-backing-up-andor-restoring/"><?php _e('See this FAQ also.', 'updraftplus');?></a></label></td>
3999 </tr>
4000
4001 <?php do_action('updraftplus_configprint_expertoptions'); ?>
4002
4003 <tr>
4004 <td></td>
4005 <td>
4006 <?php
4007 $ws_ad = empty($options['include_adverts']) ? false : $updraftplus->wordshell_random_advert(1);
4008 if ($ws_ad) {
4009 ?>
4010 <p class="wordshell-advert">
4011 <?php echo $ws_ad; ?>
4012 </p>
4013 <?php } ?>
4014 </td>
4015 </tr>
4016 <?php if (!empty($options['include_save_button'])) { ?>
4017 <tr>
4018 <td></td>
4019 <td>
4020 <input type="hidden" name="action" value="update" />
4021 <input type="submit" class="button-primary" id="updraftplus-settings-save" value="<?php _e('Save Changes','updraftplus');?>" />
4022 </td>
4023 </tr>
4024 <?php } ?>
4025 </table>
4026 <?php
4027 }
4028
4029 private function get_settings_js($method_objects, $really_is_writable, $updraft_dir) {
4030
4031 global $updraftplus;
4032
4033 ob_start();
4034 ?>
4035 jQuery(document).ready(function() {
4036 <?php
4037 if (!$really_is_writable) echo "jQuery('.backupdirrow').show();\n";
4038 ?>
4039 <?php
4040 if (!empty($active_service)) {
4041 if (is_array($active_service)) {
4042 foreach ($active_service as $serv) {
4043 echo "jQuery('.${serv}').show();\n";
4044 }
4045 } else {
4046 echo "jQuery('.${active_service}').show();\n";
4047 }
4048 } else {
4049 echo "jQuery('.none').show();\n";
4050 }
4051 foreach ($updraftplus->backup_methods as $method => $description) {
4052 // already done: require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
4053 $call_method = "UpdraftPlus_BackupModule_$method";
4054 if (method_exists($call_method, 'config_print_javascript_onready')) {
4055 $method_objects[$method]->config_print_javascript_onready();
4056 }
4057 }
4058 ?>
4059 });
4060 <?php
4061 $ret = ob_get_contents();
4062 ob_end_clean();
4063 return $ret;
4064 }
4065
4066 // $include_more can be (bool) or (string)"sometimes"
4067 public function files_selector_widgetry($prefix = '', $show_exclusion_options = true, $include_more = true) {
4068
4069 $ret = '';
4070
4071 global $updraftplus;
4072 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
4073 # The true (default value if non-existent) here has the effect of forcing a default of on.
4074 $include_more_paths = UpdraftPlus_Options::get_updraft_option('updraft_include_more_path');
4075 foreach ($backupable_entities as $key => $info) {
4076 $included = (UpdraftPlus_Options::get_updraft_option("updraft_include_$key", apply_filters("updraftplus_defaultoption_include_".$key, true))) ? 'checked="checked"' : "";
4077 if ('others' == $key || 'uploads' == $key) {
4078
4079 $data_toggle_exclude_field = $show_exclusion_options ? 'data-toggle_exclude_field="'.$key.'"' : '';
4080
4081 $ret .= '<input class="updraft_include_entity" id="'.$prefix.'updraft_include_'.$key.'" '.$data_toggle_exclude_field.' type="checkbox" name="updraft_include_'.$key.'" value="1" '.$included.'> <label '.(('others' == $key) ? 'title="'.sprintf(__('Your wp-content directory server path: %s', 'updraftplus'), WP_CONTENT_DIR).'" ' : '').' for="'.$prefix.'updraft_include_'.$key.'">'.(('others' == $key) ? __('Any other directories found inside wp-content', 'updraftplus') : htmlspecialchars($info['description'])).'</label><br>';
4082
4083 if ($show_exclusion_options) {
4084 $include_exclude = UpdraftPlus_Options::get_updraft_option('updraft_include_'.$key.'_exclude', ('others' == $key) ? UPDRAFT_DEFAULT_OTHERS_EXCLUDE : UPDRAFT_DEFAULT_UPLOADS_EXCLUDE);
4085
4086 $display = ($included) ? '' : 'class="updraft-hidden" style="display:none;"';
4087
4088 $ret .= "<div id=\"".$prefix."updraft_include_".$key."_exclude\" $display>";
4089
4090 $ret .= '<label for="'.$prefix.'updraft_include_'.$key.'_exclude">'.__('Exclude these:', 'updraftplus').'</label>';
4091
4092 $ret .= '<input title="'.__('If entering multiple files/directories, then separate them with commas. For entities at the top level, you can use a * at the start or end of the entry as a wildcard.', 'updraftplus').'" type="text" id="'.$prefix.'updraft_include_'.$key.'_exclude" name="updraft_include_'.$key.'_exclude" size="54" value="'.htmlspecialchars($include_exclude).'" />';
4093
4094 $ret .= '<br></div>';
4095 }
4096
4097 } else {
4098
4099 if ($key != 'more' || true === $include_more || ('sometimes' === $include_more && !empty($include_more_paths))) {
4100
4101 $data_toggle_exclude_field = $show_exclusion_options ? 'data-toggle_exclude_field="'.$key.'"' : '';
4102
4103 $ret .= "<input class=\"updraft_include_entity\" $data_toggle_exclude_field id=\"".$prefix."updraft_include_$key\" type=\"checkbox\" name=\"updraft_include_$key\" value=\"1\" $included /><label for=\"".$prefix."updraft_include_$key\"".((isset($info['htmltitle'])) ? ' title="'.htmlspecialchars($info['htmltitle']).'"' : '')."> ".htmlspecialchars($info['description']);
4104
4105 $ret .= "</label><br>";
4106 $ret .= apply_filters("updraftplus_config_option_include_$key", '', $prefix);
4107 }
4108 }
4109 }
4110
4111 return $ret;
4112 }
4113
4114 public function show_double_warning($text, $extraclass = '', $echo = true) {
4115
4116 $ret = "<div class=\"error updraftplusmethod $extraclass\"><p>$text</p></div>";
4117 $ret .= "<p class=\"double-warning\">$text</p>";
4118
4119 if ($echo) echo $ret;
4120 return $ret;
4121
4122 }
4123
4124 public function optionfilter_split_every($value) {
4125 $value = absint($value);
4126 if ($value < UPDRAFTPLUS_SPLIT_MIN) $value = UPDRAFTPLUS_SPLIT_MIN;
4127 return $value;
4128 }
4129
4130 public function curl_check($service, $has_fallback = false, $extraclass = '', $echo = true) {
4131
4132 $ret = '';
4133
4134 // Check requirements
4135 if (!function_exists("curl_init") || !function_exists('curl_exec')) {
4136
4137 $ret .= $this->show_double_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__("Your web server's PHP installation does not included a <strong>required</strong> (for %s) module (%s). Please contact your web hosting provider's support and ask for them to enable it.", 'updraftplus'), $service, 'Curl').' ', $extraclass, false);
4138
4139 } else {
4140 $curl_version = curl_version();
4141 $curl_ssl_supported= ($curl_version['features'] & CURL_VERSION_SSL);
4142 if (!$curl_ssl_supported) {
4143 if ($has_fallback) {
4144 $ret .= '<p><strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__("Your web server's PHP/Curl installation does not support https access. Communications with %s will be unencrypted. ask your web host to install Curl/SSL in order to gain the ability for encryption (via an add-on).",'updraftplus'),$service).'</p>';
4145 } else {
4146 $ret .= $this->show_double_warning('<p><strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__("Your web server's PHP/Curl installation does not support https access. We cannot access %s without this support. Please contact your web hosting provider's support. %s <strong>requires</strong> Curl+https. Please do not file any support requests; there is no alternative.",'updraftplus'),$service).'</p>', $extraclass, false);
4147 }
4148 } else {
4149 $ret .= '<p><em>'.sprintf(__("Good news: Your site's communications with %s can be encrypted. If you see any errors to do with encryption, then look in the 'Expert Settings' for more help.", 'updraftplus'),$service).'</em></p>';
4150 }
4151 }
4152 if ($echo) {
4153 echo $ret;
4154 } else {
4155 return $ret;
4156 }
4157 }
4158
4159 # If $basedirs is passed as an array, then $directorieses must be too
4160 private function recursive_directory_size($directorieses, $exclude = array(), $basedirs = '', $format='text') {
4161
4162 $size = 0;
4163
4164 if (is_string($directorieses)) {
4165 $basedirs = $directorieses;
4166 $directorieses = array($directorieses);
4167 }
4168
4169 if (is_string($basedirs)) $basedirs = array($basedirs);
4170
4171 foreach ($directorieses as $ind => $directories) {
4172 if (!is_array($directories)) $directories=array($directories);
4173
4174 $basedir = empty($basedirs[$ind]) ? $basedirs[0] : $basedirs[$ind];
4175
4176 foreach ($directories as $dir) {
4177 if (is_file($dir)) {
4178 $size += @filesize($dir);
4179 } else {
4180 $suffix = ('' != $basedir) ? ((0 === strpos($dir, $basedir.'/')) ? substr($dir, 1+strlen($basedir)) : '') : '';
4181 $size += $this->recursive_directory_size_raw($basedir, $exclude, $suffix);
4182 }
4183 }
4184
4185 }
4186
4187 if ('numeric' == $format) return $size;
4188
4189 global $updraftplus;
4190 return $updraftplus->convert_numeric_size_to_text($size);
4191
4192 }
4193
4194 private function recursive_directory_size_raw($prefix_directory, &$exclude = array(), $suffix_directory = '') {
4195
4196 $directory = $prefix_directory.('' == $suffix_directory ? '' : '/'.$suffix_directory);
4197 $size = 0;
4198 if (substr($directory, -1) == '/') $directory = substr($directory,0,-1);
4199
4200 if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) return -1;
4201 if (file_exists($directory.'/.donotbackup')) return 0;
4202
4203 if ($handle = opendir($directory)) {
4204 while (($file = readdir($handle)) !== false) {
4205 if ($file != '.' && $file != '..') {
4206 $spath = ('' == $suffix_directory) ? $file : $suffix_directory.'/'.$file;
4207 if (false !== ($fkey = array_search($spath, $exclude))) {
4208 unset($exclude[$fkey]);
4209 continue;
4210 }
4211 $path = $directory.'/'.$file;
4212 if (is_file($path)) {
4213 $size += filesize($path);
4214 } elseif (is_dir($path)) {
4215 $handlesize = $this->recursive_directory_size_raw($prefix_directory, $exclude, $suffix_directory.('' == $suffix_directory ? '' : '/').$file);
4216 if ($handlesize >= 0) { $size += $handlesize; }# else { return -1; }
4217 }
4218 }
4219 }
4220 closedir($handle);
4221 }
4222
4223 return $size;
4224
4225 }
4226
4227 private function raw_backup_info($backup_history, $key, $nonce) {
4228
4229 global $updraftplus;
4230
4231 $backup = $backup_history[$key];
4232
4233 $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', (int)$key), 'M d, Y G:i');
4234
4235 $rawbackup = "<h2 title=\"$key\">$pretty_date</h2>";
4236
4237 if (!empty($backup['label'])) $rawbackup .= '<span class="raw-backup-info">'.$backup['label'].'</span>';
4238
4239 $rawbackup .= '<hr><p>';
4240
4241 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
4242
4243 if (!empty($nonce)) {
4244 $jd = $updraftplus->jobdata_getarray($nonce);
4245 } else {
4246 $jd = array();
4247 }
4248
4249 foreach ($backupable_entities as $type => $info) {
4250 if (!isset($backup[$type])) continue;
4251
4252 $rawbackup .= $updraftplus->printfile($info['description'], $backup, $type, array('sha1'), $jd, true);
4253
4254 // $rawbackup .= '<h3>'.$info['description'].'</h3>';
4255 // $files = is_string($backup[$type]) ? array($backup[$type]) : $backup[$type];
4256 // foreach ($files as $index => $file) {
4257 // $rawbackup .= $file.'<br>';
4258 // }
4259 }
4260
4261 $total_size = 0;
4262 foreach ($backup as $ekey => $files) {
4263 if ('db' == strtolower(substr($ekey, 0, 2)) && '-size' != substr($ekey, -5, 5)) {
4264 $rawbackup .= $updraftplus->printfile(__('Database', 'updraftplus'), $backup, $ekey, array('sha1'), $jd, true);
4265 }
4266 if (!isset($backupable_entities[$ekey]) && ('db' != substr($ekey, 0, 2) || '-size' == substr($ekey, -5, 5))) continue;
4267 if (is_string($files)) $files = array($files);
4268 foreach ($files as $findex => $file) {
4269 $size_key = (0 == $findex) ? $ekey.'-size' : $ekey.$findex.'-size';
4270 $total_size = (false === $total_size || !isset($backup[$size_key]) || !is_numeric($backup[$size_key])) ? false : $total_size + $backup[$size_key];
4271 }
4272 }
4273
4274 $services = empty($backup['service']) ? array('none') : $backup['service'];
4275 if (!is_array($services)) $services = array('none');
4276
4277 $rawbackup .= '<strong>'.__('Uploaded to:', 'updraftplus').'</strong> ';
4278
4279 $show_services = '';
4280 foreach ($services as $serv) {
4281 if ('none' == $serv || '' == $serv) {
4282 $add_none = true;
4283 } elseif (isset($updraftplus->backup_methods[$serv])) {
4284 $show_services .= ($show_services) ? ', '.$updraftplus->backup_methods[$serv] : $updraftplus->backup_methods[$serv];
4285 } else {
4286 $show_services .= ($show_services) ? ', '.$serv : $serv;
4287 }
4288 }
4289 if ('' == $show_services && $add_none) $show_services .= __('None', 'updraftplus');
4290
4291 $rawbackup .= $show_services;
4292
4293 if ($total_size !== false) {
4294 $rawbackup .= '</p><strong>'.__('Total backup size:', 'updraftplus').'</strong> '.$updraftplus->convert_numeric_size_to_text($total_size).'<p>';
4295 }
4296
4297
4298
4299 $rawbackup .= '</p><hr><p><pre>'.print_r($backup, true).'</p></pre>';
4300
4301 if (!empty($jd) && is_array($jd)) {
4302 $rawbackup .= '<p><pre>'.print_r($jd, true).'</pre></p>';
4303 }
4304
4305 return esc_attr($rawbackup);
4306 }
4307
4308 private function existing_backup_table($backup_history = false) {
4309
4310 global $updraftplus;
4311
4312 if (false === $backup_history) $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
4313 if (!is_array($backup_history)) $backup_history=array();
4314 if (empty($backup_history)) return "<p><em>".__('You have not yet made any backups.', 'updraftplus')."</em></p>";
4315
4316 $updraft_dir = $updraftplus->backups_dir_location();
4317 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
4318
4319 $accept = apply_filters('updraftplus_accept_archivename', array());
4320 if (!is_array($accept)) $accept = array();
4321
4322 $ret = '<table class="existing-backups-table">';
4323
4324 //".__('Actions', 'updraftplus')."
4325 $ret .= "<thead>
4326 <tr style=\"margin-bottom: 4px;\">
4327 <th class=\"backup-date\">".__('Backup date', 'updraftplus')."</th>
4328 <th class=\"backup-data\">".__('Backup data (click to download)', 'updraftplus')."</th>
4329 <th class=\"updraft_backup_actions\">".__('Actions', 'updraftplus')."</th>
4330 </tr>
4331 <tr style=\"height:2px; padding:1px; margin:0px;\">
4332 <td colspan=\"4\" style=\"margin:0; padding:0\"><div style=\"height: 2px; background-color:#888888;\">&nbsp;</div></td>
4333 </tr>
4334 </thead>
4335 <tbody>";
4336 // $ret .= "<thead>
4337 // </thead>
4338 // <tbody>";
4339
4340 krsort($backup_history);
4341 foreach ($backup_history as $key => $backup) {
4342
4343 $remote_sent = (!empty($backup['service']) && ((is_array($backup['service']) && in_array('remotesend', $backup['service'])) || 'remotesend' === $backup['service'])) ? true : false;
4344
4345 # https://core.trac.wordpress.org/ticket/25331 explains why the following line is wrong
4346 # $pretty_date = date_i18n('Y-m-d G:i',$key);
4347 // Convert to blog time zone
4348 // $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', (int)$key), 'Y-m-d G:i');
4349 $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', (int)$key), 'M d, Y G:i');
4350
4351 $esc_pretty_date = esc_attr($pretty_date);
4352 $entities = '';
4353
4354 $non = $backup['nonce'];
4355 $rawbackup = $this->raw_backup_info($backup_history, $key, $non);
4356
4357 $jobdata = $updraftplus->jobdata_getarray($non);
4358
4359 $delete_button = $this->delete_button($key, $non, $backup);
4360
4361 $date_label = $this->date_label($pretty_date, $key, $backup, $jobdata, $non);
4362
4363 $log_button = $this->log_button($backup);
4364
4365 // Remote backups with no log result in useless empty rows
4366 // However, not showing anything messes up the "Existing Backups (14)" display, until we tweak that code to count differently
4367 // if ($remote_sent && !$log_button) continue;
4368
4369 $ret .= <<<ENDHERE
4370 <tr class="updraft_existing_backups_row updraft_existing_backups_row_$key" data-key="$key" data-nonce="$non">
4371
4372 <td class="updraft_existingbackup_date " data-rawbackup="$rawbackup">
4373 $date_label
4374 </td>
4375 ENDHERE;
4376
4377 $ret .= "<td>";
4378
4379 if ($remote_sent) {
4380
4381 $ret .= __('Backup sent to remote site - not available for download.', 'updraftplus');
4382 if (!empty($backup['remotesend_url'])) $ret .= '<br>'.__('Site', 'updraftplus').': '.htmlspecialchars($backup['remotesend_url']);
4383
4384 } else {
4385
4386 if (empty($backup['meta_foreign']) || !empty($accept[$backup['meta_foreign']]['separatedb'])) {
4387
4388 if (isset($backup['db'])) {
4389 $entities .= '/db=0/';
4390
4391 // Set a flag according to whether or not $backup['db'] ends in .crypt, then pick this up in the display of the decrypt field.
4392 $db = is_array($backup['db']) ? $backup['db'][0] : $backup['db'];
4393 if ($updraftplus->is_db_encrypted($db)) $entities .= '/dbcrypted=1/';
4394
4395 $ret .= $this->download_db_button('db', $key, $esc_pretty_date, $backup, $accept);
4396 } else {
4397 // $ret .= sprintf(_x('(No %s)','Message shown when no such object is available','updraftplus'), __('database', 'updraftplus'));
4398 }
4399
4400 # External databases
4401 foreach ($backup as $bkey => $binfo) {
4402 if ('db' == $bkey || 'db' != substr($bkey, 0, 2) || '-size' == substr($bkey, -5, 5)) continue;
4403 $ret .= $this->download_db_button($bkey, $key, $esc_pretty_date, $backup);
4404 }
4405
4406 } else {
4407 # Foreign without separate db
4408 $entities = '/db=0/meta_foreign=1/';
4409 }
4410
4411 if (!empty($backup['meta_foreign']) && !empty($accept[$backup['meta_foreign']]) && !empty($accept[$backup['meta_foreign']]['separatedb'])) {
4412 $entities .= '/meta_foreign=2/';
4413 }
4414
4415 $download_buttons = $this->download_buttons($backup, $key, $accept, $entities, $esc_pretty_date);
4416
4417 $ret .= $download_buttons;
4418
4419 // $ret .="</td>";
4420
4421 // No logs expected for foreign backups
4422 if (empty($backup['meta_foreign'])) {
4423 // $ret .= '<td>'.$this->log_button($backup)."</td>";
4424 }
4425 }
4426
4427 $ret .= "</td>";
4428
4429 $ret .= '<td class="before-restore-button">';
4430 $ret .= $this->restore_button($backup, $key, $pretty_date, $entities);
4431 $ret .= $delete_button;
4432 if (empty($backup['meta_foreign'])) $ret .= $log_button;
4433 $ret .= '</td>';
4434
4435 $ret .= '</tr>';
4436
4437 $ret .= "<tr style=\"height:2px; padding:1px; margin:0px;\"><td colspan=\"4\" style=\"margin:0; padding:0\"><div style=\"height: 2px; background-color:#aaaaaa;\">&nbsp;</div></td></tr>";
4438
4439 }
4440
4441 $ret .= '</tbody></table>';
4442 return $ret;
4443 }
4444
4445 private function download_db_button($bkey, $key, $esc_pretty_date, $backup, $accept = array()) {
4446
4447 if (!empty($backup['meta_foreign']) && isset($accept[$backup['meta_foreign']])) {
4448 $desc_source = $accept[$backup['meta_foreign']]['desc'];
4449 } else {
4450 $desc_source = __('unknown source', 'updraftplus');
4451 }
4452
4453 $ret = '';
4454
4455 if ('db' == $bkey) {
4456 $dbt = empty($backup['meta_foreign']) ? esc_attr(__('Database','updraftplus')) : esc_attr(sprintf(__('Database (created by %s)', 'updraftplus'), $desc_source));
4457 } else {
4458 $dbt = __('External database','updraftplus').' ('.substr($bkey, 2).')';
4459 }
4460
4461 $ret .= $this->download_button($bkey, $key, 0, null, '', $dbt, $esc_pretty_date, '0');
4462
4463 return $ret;
4464 }
4465
4466 // Go through each of the file entities
4467 private function download_buttons($backup, $key, $accept, &$entities, $esc_pretty_date) {
4468 global $updraftplus;
4469 $ret = '';
4470 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
4471
4472 // $colspan = 1;
4473 // if (!empty($backup['meta_foreign'])) {
4474 // $colspan = 2;
4475 // if (empty($accept[$backup['meta_foreign']]['separatedb'])) $colspan++;
4476 // }
4477 // $ret .= (1 == $colspan) ? '<td>' : '<td colspan="'.$colspan.'">';
4478
4479 $first_entity = true;
4480
4481 foreach ($backupable_entities as $type => $info) {
4482 if (!empty($backup['meta_foreign']) && 'wpcore' != $type) continue;
4483 // $colspan = 1;
4484 // if (!empty($backup['meta_foreign'])) {
4485 // $colspan = (1+count($backupable_entities));
4486 // if (empty($accept[$backup['meta_foreign']]['separatedb'])) $colspan++;
4487 // }
4488 // $ret .= (1 == $colspan) ? '<td>' : '<td colspan="'.$colspan.'">';
4489 $ide = '';
4490 if ('wpcore' == $type) $wpcore_restore_descrip = $info['description'];
4491 if (empty($backup['meta_foreign'])) {
4492 $sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']);
4493 if (strlen($sdescrip) > 20 && isset($info['shortdescription'])) $sdescrip = $info['shortdescription'];
4494 } else {
4495 $info['description'] = 'WordPress';
4496
4497 if (isset($accept[$backup['meta_foreign']])) {
4498 $desc_source = $accept[$backup['meta_foreign']]['desc'];
4499 $ide .= sprintf(__('Backup created by: %s.', 'updraftplus'), $accept[$backup['meta_foreign']]['desc']).' ';
4500 } else {
4501 $desc_source = __('unknown source', 'updraftplus');
4502 $ide .= __('Backup created by unknown source (%s) - cannot be restored.', 'updraftplus').' ';
4503 }
4504
4505 $sdescrip = (empty($accept[$backup['meta_foreign']]['separatedb'])) ? sprintf(__('Files and database WordPress backup (created by %s)', 'updraftplus'), $desc_source) : sprintf(__('Files backup (created by %s)', 'updraftplus'), $desc_source);
4506 if ('wpcore' == $type) $wpcore_restore_descrip = $sdescrip;
4507 }
4508 if (isset($backup[$type])) {
4509 if (!is_array($backup[$type])) $backup[$type]=array($backup[$type]);
4510 $howmanyinset = count($backup[$type]);
4511 $expected_index = 0;
4512 $index_missing = false;
4513 $set_contents = '';
4514 $entities .= "/$type=";
4515 $whatfiles = $backup[$type];
4516 ksort($whatfiles);
4517 foreach ($whatfiles as $findex => $bfile) {
4518 $set_contents .= ($set_contents == '') ? $findex : ",$findex";
4519 if ($findex != $expected_index) $index_missing = true;
4520 $expected_index++;
4521 }
4522 $entities .= $set_contents.'/';
4523 if (!empty($backup['meta_foreign'])) {
4524 $entities .= '/plugins=0//themes=0//uploads=0//others=0/';
4525 }
4526 $first_printed = true;
4527 foreach ($whatfiles as $findex => $bfile) {
4528 $ide .= __('Press here to download', 'updraftplus').' '.strtolower($info['description']);
4529 $pdescrip = ($findex > 0) ? $sdescrip.' ('.($findex+1).')' : $sdescrip;
4530 if (!$first_printed) {
4531 $ret .= '<div class="updraft-hidden" style="display:none;">';
4532 }
4533 if (count($backup[$type]) >0) {
4534 $ide .= ' '.sprintf(__('(%d archive(s) in set).', 'updraftplus'), $howmanyinset);
4535 }
4536 if ($index_missing) {
4537 $ide .= ' '.__('You appear to be missing one or more archives from this multi-archive set.', 'updraftplus');
4538 }
4539
4540 if (!$first_entity) {
4541 // $ret .= ', ';
4542 } else {
4543 $first_entity = false;
4544 }
4545
4546 $ret .= $this->download_button($type, $key, $findex, $info, $ide, $pdescrip, $esc_pretty_date, $set_contents);
4547
4548 if (!$first_printed) {
4549 $ret .= '</div>';
4550 } else {
4551 $first_printed = false;
4552 }
4553 }
4554 } else {
4555 // $ret .= sprintf(_x('(No %s)','Message shown when no such object is available','updraftplus'), preg_replace('/\s\(.{12,}\)/', '', strtolower($sdescrip)));
4556 }
4557 // $ret .= '</td>';
4558 }
4559 // $ret .= '</td>';
4560 return $ret;
4561 }
4562
4563 public function date_label($pretty_date, $key, $backup, $jobdata, $nonce, $simple_format = false) {
4564 // $ret = apply_filters('updraftplus_showbackup_date', '<strong>'.$pretty_date.'</strong>', $backup, $jobdata, (int)$key);
4565 $ret = apply_filters('updraftplus_showbackup_date', $pretty_date, $backup, $jobdata, (int)$key, $simple_format);
4566 if (is_array($jobdata) && !empty($jobdata['resume_interval']) && (empty($jobdata['jobstatus']) || 'finished' != $jobdata['jobstatus'])) {
4567 if ($simple_format) {
4568 $ret .= ' '.__('(Not finished)', 'updraftplus');
4569 } else {
4570 $ret .= apply_filters('updraftplus_msg_unfinishedbackup', "<br><span title=\"".esc_attr(__('If you are seeing more backups than you expect, then it is probably because the deletion of old backup sets does not happen until a fresh backup completes.', 'updraftplus'))."\">".__('(Not finished)', 'updraftplus').'</span>', $jobdata, $nonce);
4571 }
4572 }
4573 return $ret;
4574 }
4575
4576 private function download_button($type, $backup_timestamp, $findex, $info, $ide, $pdescrip, $esc_pretty_date, $set_contents) {
4577
4578 $ret = '';
4579
4580 $wp_nonce = wp_create_nonce('updraftplus_download');
4581
4582 // updraft_downloader(base, backup_timestamp, what, whicharea, set_contents, prettydate, async)
4583 $ret .= '<button data-wp_nonce="'.esc_attr($wp_nonce).'" data-backup_timestamp="'.esc_attr($backup_timestamp).'" data-what="'.esc_attr($type).'" data-set_contents="'.esc_attr($set_contents).'" data-prettydate="'.esc_attr($esc_pretty_date).'" type="button" class="updraft_download_button '."uddownloadform_${type}_${backup_timestamp}_${findex}".'" title="'.$ide.'">'.$pdescrip.'</button>';
4584 // onclick="'."return updraft_downloader('uddlstatus_', '$backup_timestamp', '$type', '.ud_downloadstatus', '$set_contents', '$esc_pretty_date', true)".'"
4585
4586
4587 // Pre 1.11.24
4588 // $nonce_field = wp_nonce_field('updraftplus_download', '_wpnonce', true, false);
4589 // $ret .= <<<ENDHERE
4590 // <form class="uddownloadform_${type}_${backup_timestamp}_${findex}" action="admin-ajax.php" onsubmit="return updraft_downloader('uddlstatus_', '$backup_timestamp', '$type', '.ud_downloadstatus', '$set_contents', '$esc_pretty_date', true)" method="post">
4591 // $nonce_field
4592 // <input type="hidden" name="action" value="updraft_download_backup" />
4593 // <input type="hidden" name="type" value="$type" />
4594 // <input type="hidden" name="timestamp" value="$backup_timestamp" />
4595 // <input type="hidden" name="findex" value="$findex" />
4596 // <input type="submit" class="updraft-backupentitybutton" title="$ide" value="$pdescrip" />
4597 // </form>
4598 // </div>
4599 // ENDHERE;
4600 return $ret;
4601 }
4602
4603 private function restore_button($backup, $key, $pretty_date, $entities = '') {
4604 $ret = '<div class="restore-button">';
4605
4606 if ($entities) {
4607 $show_data = $pretty_date;
4608 if (isset($backup['native']) && false == $backup['native']) {
4609 $show_data .= ' '.__('(backup set imported from remote location)', 'updraftplus');
4610 }
4611
4612 $ret .= '<button data-showdata="'.esc_attr($show_data).'" data-backup_timestamp="'.$key.'" data-entities="'.esc_attr($entities).'" title="'.__('After pressing this button, you will be given the option to choose which components you wish to restore','updraftplus').'" type="button" style="float:left; clear:none;" class="button-primary choose-components-button">'.__('Restore', 'updraftplus').'</button>';
4613 }
4614 $ret .= "</div>\n";
4615 return $ret;
4616 }
4617
4618 private function delete_button($key, $nonce, $backup) {
4619 $sval = ((isset($backup['service']) && $backup['service'] != 'email' && $backup['service'] != 'none')) ? '1' : '0';
4620 return '<div class="updraftplus-remove" style="float: left; clear: none;" data-hasremote="'.$sval.'">
4621 <a data-hasremote="'.$sval.'" data-nonce="'.$nonce.'" data-key="'.$key.'" class="no-decoration updraft-delete-link" href="#" title="'.esc_attr(__('Delete this backup set', 'updraftplus')).'">'.__('Delete', 'updraftplus').'</a>
4622 </div>';
4623 }
4624
4625 private function log_button($backup) {
4626 global $updraftplus;
4627 $updraft_dir = $updraftplus->backups_dir_location();
4628 $ret = '';
4629 if (isset($backup['nonce']) && preg_match("/^[0-9a-f]{12}$/",$backup['nonce']) && is_readable($updraft_dir.'/log.'.$backup['nonce'].'.txt')) {
4630 $nval = $backup['nonce'];
4631 // $lt = esc_attr(__('View Log','updraftplus'));
4632 $lt = __('View Log', 'updraftplus');
4633 $url = esc_attr(UpdraftPlus_Options::admin_page()."?page=updraftplus&action=downloadlog&amp;updraftplus_backup_nonce=$nval");
4634 $ret .= <<<ENDHERE
4635 <div style="clear:none;" class="updraft-viewlogdiv">
4636 <a class="no-decoration updraft-log-link" href="$url" data-jobid="$nval">
4637 $lt
4638 </a>
4639 <!--
4640 <form action="$url" method="get">
4641 <input type="hidden" name="action" value="downloadlog" />
4642 <input type="hidden" name="page" value="updraftplus" />
4643 <input type="hidden" name="updraftplus_backup_nonce" value="$nval" />
4644 <input type="submit" value="$lt" class="updraft-log-link" onclick="event.preventDefault(); updraft_popuplog('$nval');" />
4645 </form>
4646 -->
4647 </div>
4648 ENDHERE;
4649 return $ret;
4650 } else {
4651 // return str_replace(' ', '&nbsp;', '('.__('No backup log)', 'updraftplus').')');
4652 }
4653 }
4654
4655 // Return values: false = 'not yet' (not necessarily terminal); WP_Error = terminal failure; true = success
4656 private function restore_backup($timestamp, $continuation_data = null) {
4657
4658 @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
4659
4660 global $wp_filesystem, $updraftplus;
4661 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
4662 if (!isset($backup_history[$timestamp]) || !is_array($backup_history[$timestamp])) {
4663 echo '<p>'.__('This backup does not exist in the backup history - restoration aborted. Timestamp:','updraftplus')." $timestamp</p><br/>";
4664 return new WP_Error('does_not_exist', __('Backup does not exist in the backup history', 'updraftplus'));
4665 }
4666
4667 // request_filesystem_credentials passes on fields just via hidden name/value pairs.
4668 // Build array of parameters to be passed via this
4669 $extra_fields = array();
4670 if (isset($_POST['updraft_restore']) && is_array($_POST['updraft_restore'])) {
4671 foreach ($_POST['updraft_restore'] as $entity) {
4672 $_POST['updraft_restore_'.$entity] = 1;
4673 $extra_fields[] = 'updraft_restore_'.$entity;
4674 }
4675 }
4676
4677 if (is_array($continuation_data)) {
4678 foreach ($continuation_data['second_loop_entities'] as $type => $files) {
4679 $_POST['updraft_restore_'.$type] = 1;
4680 if (!in_array('updraft_restore_'.$type, $extra_fields)) $extra_fields[] = 'updraft_restore_'.$type;
4681 }
4682 if (!empty($continuation_data['restore_options'])) $restore_options = $continuation_data['restore_options'];
4683 }
4684
4685 // Now make sure that updraft_restorer_ option fields get passed along to request_filesystem_credentials
4686 foreach ($_POST as $key => $value) {
4687 if (0 === strpos($key, 'updraft_restorer_')) $extra_fields[] = $key;
4688 }
4689
4690 $credentials = request_filesystem_credentials(UpdraftPlus_Options::admin_page()."?page=updraftplus&action=updraft_restore&backup_timestamp=$timestamp", '', false, false, $extra_fields);
4691 WP_Filesystem($credentials);
4692 if ( $wp_filesystem->errors->get_error_code() ) {
4693 echo '<p><em><a href="https://updraftplus.com/faqs/asked-ftp-details-upon-restorationmigration-updates/">'.__('Why am I seeing this?', 'updraftplus').'</a></em></p>';
4694 foreach ( $wp_filesystem->errors->get_error_messages() as $message ) show_message($message);
4695 exit;
4696 }
4697
4698 // If we make it this far then WP_Filesystem has been instantiated and is functional
4699
4700 # Set up logging
4701 $updraftplus->backup_time_nonce();
4702 $updraftplus->jobdata_set('job_type', 'restore');
4703 $updraftplus->jobdata_set('job_time_ms', $updraftplus->job_time_ms);
4704 $updraftplus->logfile_open($updraftplus->nonce);
4705
4706 # Provide download link for the log file
4707
4708 # TODO: Automatic purging of old log files
4709 # TODO: Provide option to auto-email the log file
4710
4711 echo '<h1>'.__('UpdraftPlus Restoration: Progress', 'updraftplus').'</h1><div id="updraft-restore-progress">';
4712
4713 $this->show_admin_warning('<a target="_blank" href="?action=downloadlog&page=updraftplus&updraftplus_backup_nonce='.htmlspecialchars($updraftplus->nonce).'">'.__('Follow this link to download the log file for this restoration (needed for any support requests).', 'updraftplus').'</a>');
4714
4715 $updraft_dir = trailingslashit($updraftplus->backups_dir_location());
4716 $foreign_known = apply_filters('updraftplus_accept_archivename', array());
4717
4718 $service = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
4719 if (!is_array($service)) $service = array($service);
4720
4721 // Now, need to turn any updraft_restore_<entity> fields (that came from a potential WP_Filesystem form) back into parts of the _POST array (which we want to use)
4722 if (empty($_POST['updraft_restore']) || (!is_array($_POST['updraft_restore']))) $_POST['updraft_restore'] = array();
4723
4724 $backup_set = $backup_history[$timestamp];
4725 $entities_to_restore = array();
4726 foreach ($_POST['updraft_restore'] as $entity) {
4727 if (empty($backup_set['meta_foreign'])) {
4728 $entities_to_restore[$entity] = $entity;
4729 } else {
4730 if ('db' == $entity && !empty($foreign_known[$backup_set['meta_foreign']]) && !empty($foreign_known[$backup_set['meta_foreign']]['separatedb'])) {
4731 $entities_to_restore[$entity] = 'db';
4732 } else {
4733 $entities_to_restore[$entity] = 'wpcore';
4734 }
4735 }
4736 }
4737
4738 foreach ($_POST as $key => $value) {
4739 if (0 === strpos($key, 'updraft_restore_')) {
4740 $nkey = substr($key, 16);
4741 if (!isset($entities_to_restore[$nkey])) {
4742 $_POST['updraft_restore'][] = $nkey;
4743 if (empty($backup_set['meta_foreign'])) {
4744 $entities_to_restore[$nkey] = $nkey;
4745 } else {
4746 if ('db' == $entity && !empty($foreign_known[$backup_set['meta_foreign']]['separatedb'])) {
4747 $entities_to_restore[$nkey] = 'db';
4748 } else {
4749 $entities_to_restore[$nkey] = 'wpcore';
4750 }
4751 }
4752 }
4753 }
4754 }
4755
4756 if (0 == count($_POST['updraft_restore'])) {
4757 echo '<p>'.__('ABORT: Could not find the information on which entities to restore.', 'updraftplus').'</p>';
4758 echo '<p>'.__('If making a request for support, please include this information:','updraftplus').' '.count($_POST).' : '.htmlspecialchars(serialize($_POST)).'</p>';
4759 return new WP_Error('missing_info', 'Backup information not found');
4760 }
4761
4762 $this->entities_to_restore = $entities_to_restore;
4763
4764 set_error_handler(array($updraftplus, 'php_error'), E_ALL & ~E_STRICT);
4765
4766 /*
4767 $_POST['updraft_restore'] is typically something like: array( 0=>'db', 1=>'plugins', 2=>'themes'), etc.
4768 i.e. array ( 'db', 'plugins', themes')
4769 */
4770
4771 if (empty($restore_options)) {
4772 // Gather the restore optons into one place - code after here should read the options, and not the HTTP layer
4773 $restore_options = array();
4774 if (!empty($_POST['updraft_restorer_restore_options'])) {
4775 parse_str(stripslashes($_POST['updraft_restorer_restore_options']), $restore_options);
4776 }
4777 $restore_options['updraft_restorer_replacesiteurl'] = empty($_POST['updraft_restorer_replacesiteurl']) ? false : true;
4778 $restore_options['updraft_encryptionphrase'] = empty($_POST['updraft_encryptionphrase']) ? '' : (string)stripslashes($_POST['updraft_encryptionphrase']);
4779 $restore_options['updraft_restorer_wpcore_includewpconfig'] = empty($_POST['updraft_restorer_wpcore_includewpconfig']) ? false : true;
4780 $updraftplus->jobdata_set('restore_options', $restore_options);
4781 }
4782
4783 // Restore in the most helpful order
4784 uksort($backup_set, array($this, 'sort_restoration_entities'));
4785
4786 // Now log
4787 $copy_restore_options = $restore_options;
4788 if (!empty($copy_restore_options['updraft_encryptionphrase'])) $copy_restore_options['updraft_encryptionphrase'] = '***';
4789 $updraftplus->log("Restore job started. Entities to restore: ".implode(', ', array_flip($entities_to_restore)).'. Restore options: '.json_encode($copy_restore_options));
4790
4791 $backup_set['timestamp'] = $timestamp;
4792
4793 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
4794
4795 // Allow add-ons to adjust the restore directory (but only in the case of restore - otherwise, they could just use the filter built into UpdraftPlus::get_backupable_file_entities)
4796 $backupable_entities = apply_filters('updraft_backupable_file_entities_on_restore', $backupable_entities, $restore_options, $backup_set);
4797
4798 // We use a single object for each entity, because we want to store information about the backup set
4799 require_once(UPDRAFTPLUS_DIR.'/restorer.php');
4800
4801 global $updraftplus_restorer;
4802
4803 $updraftplus_restorer = new Updraft_Restorer(new Updraft_Restorer_Skin, $backup_set, false, $restore_options);
4804
4805 $second_loop = array();
4806
4807 echo "<h2>".__('Final checks', 'updraftplus').'</h2>';
4808
4809 if (empty($backup_set['meta_foreign'])) {
4810 $entities_to_download = $entities_to_restore;
4811 } else {
4812 if (!empty($foreign_known[$backup_set['meta_foreign']]['separatedb'])) {
4813 $entities_to_download = array();
4814 if (in_array('db', $entities_to_restore)) {
4815 $entities_to_download['db'] = 1;
4816 }
4817 if (count($entities_to_restore) > 1 || !in_array('db', $entities_to_restore)) {
4818 $entities_to_download['wpcore'] = 1;
4819 }
4820 } else {
4821 $entities_to_download = array('wpcore' => 1);
4822 }
4823 }
4824
4825 // First loop: make sure that files are present + readable; and populate array for second loop
4826 foreach ($backup_set as $type => $files) {
4827 // All restorable entities must be given explicitly, as we can store other arbitrary data in the history array
4828 if (!isset($backupable_entities[$type]) && 'db' != $type) continue;
4829 if (isset($backupable_entities[$type]['restorable']) && $backupable_entities[$type]['restorable'] == false) continue;
4830
4831 if (!isset($entities_to_download[$type])) continue;
4832 if ('wpcore' == $type && is_multisite() && 0 === $updraftplus_restorer->ud_backup_is_multisite) {
4833 echo "<p>$type: <strong>";
4834 echo __('Skipping restoration of WordPress core when importing a single site into a multisite installation. If you had anything necessary in your WordPress directory then you will need to re-add it manually from the zip file.', 'updraftplus');
4835 #TODO
4836 #$updraftplus->log_e('Skipping restoration of WordPress core when importing a single site into a multisite installation. If you had anything necessary in your WordPress directory then you will need to re-add it manually from the zip file.');
4837 echo "</strong></p>";
4838 continue;
4839 }
4840
4841 if (is_string($files)) $files=array($files);
4842
4843 foreach ($files as $ind => $file) {
4844
4845 $fullpath = $updraft_dir.$file;
4846 echo sprintf(__("Looking for %s archive: file name: %s", 'updraftplus'), $type, htmlspecialchars($file))."<br>";
4847
4848 if (is_array($continuation_data) && isset($continuation_data['second_loop_entities'][$type]) && !in_array($file, $continuation_data['second_loop_entities'][$type])) {
4849 echo __('Skipping: this archive was already restored.', 'updraftplus')."<br>";
4850 // Set the marker so that the existing directory isn't moved out of the way
4851 $updraftplus_restorer->been_restored[$type] = true;
4852 continue;
4853 }
4854
4855 add_action('http_request_args', array($updraftplus, 'modify_http_options'));
4856 foreach ($service as $serv) {
4857 if (!is_readable($fullpath)) {
4858 $sd = (empty($updraftplus->backup_methods[$serv])) ? $serv : $updraftplus->backup_methods[$serv];
4859 echo __("File is not locally present - needs retrieving from remote storage",'updraftplus')." ($sd)";
4860 $this->download_file($file, $serv);
4861 echo ": ";
4862 if (!is_readable($fullpath)) {
4863 echo __("Error", 'updraftplus');
4864 } else {
4865 echo __("OK", 'updraftplus');
4866 }
4867 echo '<br>';
4868 }
4869 }
4870 remove_action('http_request_args', array($updraftplus, 'modify_http_options'));
4871
4872 $index = ($ind == 0) ? '' : $ind;
4873 // If a file size is stored in the backup data, then verify correctness of the local file
4874 if (isset($backup_history[$timestamp][$type.$index.'-size'])) {
4875 $fs = $backup_history[$timestamp][$type.$index.'-size'];
4876 echo __("Archive is expected to be size:",'updraftplus')." ".round($fs/1024, 1)." KB: ";
4877 $as = @filesize($fullpath);
4878 if ($as == $fs) {
4879 echo __('OK','updraftplus').'<br>';
4880 } else {
4881 echo "<strong>".__('Error:','updraftplus')."</strong> ".__('file is size:', 'updraftplus')." ".round($as/1024)." ($fs, $as)<br>";
4882 }
4883 } else {
4884 echo __("The backup records do not contain information about the proper size of this file.",'updraftplus')."<br>";
4885 }
4886 if (!is_readable($fullpath)) {
4887 echo __('Could not find one of the files for restoration', 'updraftplus')." ($file)<br>";
4888 $updraftplus->log("$file: ".__('Could not find one of the files for restoration', 'updraftplus'), 'error');
4889 echo '</div>';
4890 restore_error_handler();
4891 return false;
4892 }
4893 }
4894
4895 if (empty($updraftplus_restorer->ud_foreign)) {
4896 $types = array($type);
4897 } else {
4898 if ('db' != $type || empty($foreign_known[$updraftplus_restorer->ud_foreign]['separatedb'])) {
4899 $types = array('wpcore');
4900 } else {
4901 $types = array('db');
4902 }
4903 }
4904
4905 foreach ($types as $check_type) {
4906 $info = (isset($backupable_entities[$check_type])) ? $backupable_entities[$check_type] : array();
4907 $val = $updraftplus_restorer->pre_restore_backup($files, $check_type, $info, $continuation_data);
4908 if (is_wp_error($val)) {
4909 $updraftplus->log_wp_error($val);
4910 foreach ($val->get_error_messages() as $msg) {
4911 echo '<strong>'.__('Error:', 'updraftplus').'</strong> '.htmlspecialchars($msg).'<br>';
4912 }
4913 foreach ($val->get_error_codes() as $code) {
4914 if ('already_exists' == $code) $this->print_delete_old_dirs_form(false);
4915 }
4916 echo '</div>'; //close the updraft_restore_progress div even if we error
4917 restore_error_handler();
4918 return $val;
4919 } elseif (false === $val) {
4920 echo '</div>'; //close the updraft_restore_progress div even if we error
4921 restore_error_handler();
4922 return false;
4923 }
4924 }
4925
4926 foreach ($entities_to_restore as $entity => $via) {
4927 if ($via == $type) {
4928 if ('wpcore' == $via && 'db' == $entity && count($files) > 1) {
4929 $second_loop[$entity] = apply_filters('updraftplus_select_wpcore_file_with_db', $files, $updraftplus_restorer->ud_foreign);
4930 } else {
4931 $second_loop[$entity] = $files;
4932 }
4933 }
4934 }
4935
4936 }
4937
4938 $updraftplus_restorer->delete = (UpdraftPlus_Options::get_updraft_option('updraft_delete_local')) ? true : false;
4939 if ('none' === $service || 'email' === $service || empty($service) || (is_array($service) && 1 == count($service) && (in_array('none', $service) || in_array('', $service) || in_array('email', $service))) || !empty($updraftplus_restorer->ud_foreign)) {
4940 if ($updraftplus_restorer->delete) $updraftplus->log_e('Will not delete any archives after unpacking them, because there was no cloud storage for this backup');
4941 $updraftplus_restorer->delete = false;
4942 }
4943
4944 if (!empty($updraftplus_restorer->ud_foreign)) $updraftplus->log("Foreign backup; created by: ".$updraftplus_restorer->ud_foreign);
4945
4946 // Second loop: now actually do the restoration
4947 uksort($second_loop, array($this, 'sort_restoration_entities'));
4948
4949 // If continuing, then prune those already done
4950 if (is_array($continuation_data)) {
4951 foreach ($second_loop as $type => $files) {
4952 if (isset($continuation_data['second_loop_entities'][$type])) $second_loop[$type] = $continuation_data['second_loop_entities'][$type];
4953 }
4954 }
4955
4956 $updraftplus->jobdata_set('second_loop_entities', $second_loop);
4957 $updraftplus->jobdata_set('backup_timestamp', $timestamp);
4958 // use a site option, as otherwise on multisite when all the array of options is updated via UpdraftPlus_Options::update_site_option(), it will over-write any restored UD options from the backup
4959 update_site_option('updraft_restore_in_progress', $updraftplus->nonce);
4960
4961 foreach ($second_loop as $type => $files) {
4962 # Types: uploads, themes, plugins, others, db
4963 $info = (isset($backupable_entities[$type])) ? $backupable_entities[$type] : array();
4964
4965 echo ('db' == $type) ? "<h2>".__('Database','updraftplus')."</h2>" : "<h2>".$info['description']."</h2>";
4966 $updraftplus->log("Entity: ".$type);
4967
4968 if (is_string($files)) $files = array($files);
4969 foreach ($files as $fkey => $file) {
4970 $last_one = (1 == count($second_loop) && 1 == count($files));
4971
4972 $val = $updraftplus_restorer->restore_backup($file, $type, $info, $last_one);
4973
4974 if (is_wp_error($val)) {
4975 $codes = $val->get_error_codes();
4976 if (is_array($codes) && in_array('not_found', $codes) && !empty($updraftplus_restorer->ud_foreign) && apply_filters('updraftplus_foreign_allow_missing_entity', false, $type, $updraftplus_restorer->ud_foreign)) {
4977 $updraftplus->log("Entity to move not found in this zip - but this is possible with this foreign backup type");
4978 } else {
4979
4980 $updraftplus->log_e($val);
4981 foreach ($val->get_error_messages() as $msg) {
4982 echo '<strong>'.__('Error message', 'updraftplus').':</strong> '.htmlspecialchars($msg).'<br>';
4983 }
4984 $codes = $val->get_error_codes();
4985 if (is_array($codes)) {
4986 foreach ($codes as $code) {
4987 $data = $val->get_error_data($code);
4988 if (!empty($data)) {
4989 $pdata = (is_string($data)) ? $data : serialize($data);
4990 echo '<strong>'.__('Error data:', 'updraftplus').'</strong> '.htmlspecialchars($pdata).'<br>';
4991 if (false !== strpos($pdata, 'PCLZIP_ERR_BAD_FORMAT (-10)')) {
4992 echo '<a href="https://updraftplus.com/faqs/error-message-pclzip_err_bad_format-10-invalid-archive-structure-mean/"><strong>'.__('Please consult this FAQ for help on what to do about it.', 'updraftplus').'</strong></a><br>';
4993 }
4994 }
4995 }
4996 }
4997 echo '</div>'; //close the updraft_restore_progress div even if we error
4998 restore_error_handler();
4999 return $val;
5000 }
5001 } elseif (false === $val) {
5002 echo '</div>'; //close the updraft_restore_progress div even if we error
5003 restore_error_handler();
5004 return false;
5005 }
5006 unset($files[$fkey]);
5007 $second_loop[$type] = $files;
5008 $updraftplus->jobdata_set('second_loop_entities', $second_loop);
5009 $updraftplus->jobdata_set('backup_timestamp', $timestamp);
5010
5011 do_action('updraft_restored_archive', $file, $type, $val, $fkey, $timestamp);
5012
5013 }
5014 unset($second_loop[$type]);
5015 update_site_option('updraft_restore_in_progress', $updraftplus->nonce);
5016 $updraftplus->jobdata_set('second_loop_entities', $second_loop);
5017 $updraftplus->jobdata_set('backup_timestamp', $timestamp);
5018 }
5019
5020 // All done - remove
5021 delete_site_option('updraft_restore_in_progress');
5022
5023 foreach (array('template', 'stylesheet', 'template_root', 'stylesheet_root') as $opt) {
5024 add_filter('pre_option_'.$opt, array($this, 'option_filter_'.$opt));
5025 }
5026
5027 # Clear any cached pages after the restore
5028 $updraftplus_restorer->clear_cache();
5029
5030 if (!function_exists('validate_current_theme')) require_once(ABSPATH.WPINC.'/themes');
5031
5032 # Have seen a case where the current theme in the DB began with a capital, but not on disk - and this breaks migrating from Windows to a case-sensitive system
5033 $template = get_option('template');
5034 if (!empty($template) && $template != WP_DEFAULT_THEME && $template != strtolower($template)) {
5035
5036 $theme_root = get_theme_root($template);
5037 $theme_root2 = get_theme_root(strtolower($template));
5038
5039 if (!file_exists("$theme_root/$template/style.css") && file_exists("$theme_root/".strtolower($template)."/style.css")) {
5040 $updraftplus->log_e("Theme directory (%s) not found, but lower-case version exists; updating database option accordingly", $template);
5041 update_option('template', strtolower($template));
5042 }
5043
5044 }
5045
5046 if (!validate_current_theme()) {
5047 echo '<strong>';
5048 $updraftplus->log_e("The current theme was not found; to prevent this stopping the site from loading, your theme has been reverted to the default theme");
5049 echo '</strong>';
5050 }
5051
5052 echo '</div>'; //close the updraft_restore_progress div
5053
5054 restore_error_handler();
5055 return true;
5056 }
5057
5058 public function option_filter_template($val) { global $updraftplus; return $updraftplus->option_filter_get('template'); }
5059
5060 public function option_filter_stylesheet($val) { global $updraftplus; return $updraftplus->option_filter_get('stylesheet'); }
5061
5062 public function option_filter_template_root($val) { global $updraftplus; return $updraftplus->option_filter_get('template_root'); }
5063
5064 public function option_filter_stylesheet_root($val) { global $updraftplus; return $updraftplus->option_filter_get('stylesheet_root'); }
5065
5066 public function sort_restoration_entities($a, $b) {
5067 if ($a == $b) return 0;
5068 // Put the database first
5069 // Put wpcore after plugins/uploads/themes (needed for restores of foreign all-in-one formats)
5070 if ('db' == $a || 'wpcore' == $b) return -1;
5071 if ('db' == $b || 'wpcore' == $a) return 1;
5072 // After wpcore, next last is others
5073 if ('others' == $b) return -1;
5074 if ('others' == $a) return 1;
5075 // And then uploads - this is only because we want to make sure uploads is after plugins, so that we know before we get to the uploads whether the version of UD which might have to unpack them can do this new-style or not.
5076 if ('uploads' == $b) return -1;
5077 if ('uploads' == $a) return 1;
5078 return strcmp($a, $b);
5079 }
5080
5081 public function return_array($input) {
5082 if (!is_array($input)) $input = array();
5083 return $input;
5084 }
5085
5086 public function updraft_ajax_savesettings() {
5087 global $updraftplus;
5088
5089 if (empty($_POST) || empty($_POST['subaction']) || 'savesettings' != $_POST['subaction'] || !isset($_POST['nonce']) || !is_user_logged_in() || !UpdraftPlus_Options::user_can_manage() || !wp_verify_nonce($_POST['nonce'], 'updraftplus-settings-nonce')) die('Security check');
5090
5091 if (empty($_POST['settings']) || !is_string($_POST['settings'])) die('Invalid data');
5092
5093 parse_str(stripslashes($_POST['settings']), $posted_settings);
5094 // We now have $posted_settings as an array
5095
5096 echo json_encode($this->save_settings($posted_settings));
5097
5098 die;
5099 }
5100
5101 private function backup_now_remote_message() {
5102 global $updraftplus;
5103
5104 $service = $updraftplus->just_one(UpdraftPlus_Options::get_updraft_option('updraft_service'));
5105 if (is_string($service)) $service = array($service);
5106 if (!is_array($service)) $service = array();
5107
5108 $no_remote_configured = (empty($service) || array('none') === $service || array('') === $service) ? true : false;
5109
5110 if ($no_remote_configured) {
5111 return '<input type="checkbox" disabled="disabled" id="backupnow_includecloud"> <em>'.sprintf(__("Backup won't be sent to any remote storage - none has been saved in the %s", 'updraftplus'), '<a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&amp;tab=settings" id="updraft_backupnow_gotosettings">'.__('settings', 'updraftplus')).'</a>. '.__('Not got any remote storage?', 'updraftplus').' <a href="https://updraftplus.com/support/updraftplus-vault-faqs/">'.__("Check out UpdraftPlus Vault.", 'updraftplus').'</a></em>';
5112 } else {
5113 return '<input type="checkbox" id="backupnow_includecloud" checked="checked"> <label for="backupnow_includecloud">'.__("Send this backup to remote storage", 'updraftplus').'</label>';
5114 }
5115 }
5116
5117 public function save_settings($settings) {
5118
5119 global $updraftplus;
5120
5121 // Make sure that settings filters are registered
5122 UpdraftPlus_Options::admin_init();
5123
5124 $return_array = array('saved' => true);
5125
5126 $add_to_post_keys = array('updraft_interval', 'updraft_interval_database', 'updraft_starttime_files', 'updraft_starttime_db', 'updraft_startday_files', 'updraft_startday_db');
5127
5128 //If database and files are on same schedule, override the db day/time settings
5129 if (isset($settings['updraft_interval_database']) && isset($settings['updraft_interval_database']) && $settings['updraft_interval_database'] == $settings['updraft_interval'] && isset($settings['updraft_starttime_files'])) {
5130 $settings['updraft_starttime_db'] = $settings['updraft_starttime_files'];
5131 $settings['updraft_startday_db'] = $settings['updraft_startday_files'];
5132 }
5133 foreach ($add_to_post_keys as $key) {
5134 // For add-ons that look at $_POST to find saved settings, add the relevant keys to $_POST so that they find them there
5135 if (isset($settings[$key])) {
5136 $_POST[$key] = $settings[$key];
5137 }
5138 }
5139
5140 // Wipe the extra retention rules, as they are not saved correctly if the last one is deleted
5141 UpdraftPlus_Options::update_updraft_option('updraft_retain_extrarules', array());
5142 UpdraftPlus_Options::update_updraft_option('updraft_email', array());
5143 UpdraftPlus_Options::update_updraft_option('updraft_report_warningsonly', array());
5144 UpdraftPlus_Options::update_updraft_option('updraft_report_wholebackup', array());
5145 UpdraftPlus_Options::update_updraft_option('updraft_extradbs', array());
5146 UpdraftPlus_Options::update_updraft_option('updraft_include_more_path', array());
5147
5148 $relevant_keys = $updraftplus->get_settings_keys();
5149
5150 if (method_exists('UpdraftPlus_Options', 'mass_options_update')) {
5151 $original_settings = $settings;
5152 $settings = UpdraftPlus_Options::mass_options_update($settings);
5153 $mass_updated = true;
5154 }
5155
5156 foreach ($settings as $key => $value) {
5157 // $exclude_keys = array('option_page', 'action', '_wpnonce', '_wp_http_referer');
5158
5159 // if (!in_array($key, $exclude_keys)) {
5160 if (in_array($key, $relevant_keys)) {
5161 if ($key == "updraft_service" && is_array($value)){
5162 foreach ($value as $subkey => $subvalue){
5163 if ($subvalue == '0') unset($value[$subkey]);
5164 }
5165 }
5166
5167 // This flag indicates that either the stored database option was changed, or that the supplied option was changed before being stored. It isn't comprehensive - it's only used to update some UI elements with invalid input.
5168 $updated = empty($mass_updated) ? (is_string($value) && $value != UpdraftPlus_Options::get_updraft_option($key)) : (is_string($value) && (!isset($original_settings[$key]) || $original_settings[$key] != $value));
5169
5170 $db_updated = empty($mass_updated) ? UpdraftPlus_Options::update_updraft_option($key, $value) : true;
5171
5172 // Add information on what has changed to array to loop through to update links etc.
5173 // Restricting to strings for now, to prevent any unintended leakage (since this is just used for UI updating)
5174 if ($updated) {
5175 $value = UpdraftPlus_Options::get_updraft_option($key);
5176 if (is_string($value)) $return_array['changed'][$key] = $value;
5177 }
5178 } else {
5179 // When last active, it was catching: option_page, action, _wpnonce, _wp_http_referer, updraft_s3_endpoint, updraft_dreamobjects_endpoint. The latter two are empty; probably don't need to be in the page at all.
5180 //error_log("Non-UD key when saving from POSTed data: ".$key);
5181 }
5182 }
5183
5184 // Checking for various possible messages
5185 $updraft_dir = $updraftplus->backups_dir_location(false);
5186 $really_is_writable = $updraftplus->really_is_writable($updraft_dir);
5187 $dir_info = $this->really_writable_message($really_is_writable, $updraft_dir);
5188 $button_title = esc_attr(__('This button is disabled because your backup directory is not writable (see the settings).', 'updraftplus'));
5189
5190 $return_array['backup_now_message'] = $this->backup_now_remote_message();
5191
5192 $return_array['backup_dir'] = array('writable' => $really_is_writable, 'message' => $dir_info, 'button_title' => $button_title);
5193
5194 //Because of the single AJAX call, we need to remove the existing UD messages from the 'all_admin_notices' action
5195 remove_all_actions('all_admin_notices');
5196
5197 //Moving from 2 to 1 ajax call
5198 ob_start();
5199
5200 $service = UpdraftPlus_Options::get_updraft_option('updraft_service');
5201
5202 $this->setup_all_admin_notices_global($service);
5203 $this->setup_all_admin_notices_udonly($service);
5204
5205 do_action('all_admin_notices');
5206
5207 if (!$really_is_writable){ //Check if writable
5208 $this->show_admin_warning_unwritable();
5209 }
5210
5211 if ($return_array['saved'] == true){ //
5212 $this->show_admin_warning(__('Your settings have been saved.', 'updraftplus'), 'updated fade');
5213 }
5214
5215 $messages_output = ob_get_contents();
5216
5217 ob_clean();
5218
5219 // Backup schedule output
5220 $this->next_scheduled_backups_output();
5221
5222 $scheduled_output = ob_get_clean();
5223
5224 $return_array['messages'] = $messages_output;
5225 $return_array['scheduled'] = $scheduled_output;
5226
5227 //*** Add the updated options to the return message, so we can update on screen ***\\
5228
5229
5230 return $return_array;
5231
5232 }
5233
5234 }
5235