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