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

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

2,832 lines 140.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined ('ABSPATH')) die('No direct access allowed');
4
5 // For the purposes of improving site performance (don't load in 10s of Kilobytes of un-needed code on every page load), admin-area code is being progressively moved here.
6
7 // This gets called in admin_init, earlier than default (so our object can get used by those hooking admin_init). Or possibly in admin_menu.
8
9 global $updraftplus_admin;
10 if (!is_a($updraftplus_admin, 'UpdraftPlus_Admin')) $updraftplus_admin = new UpdraftPlus_Admin();
11
12 class UpdraftPlus_Admin {
13
14 function __construct() {
15 $this->admin_init();
16 }
17
18 function admin_init() {
19
20 add_action('core_upgrade_preamble', array($this, 'core_upgrade_preamble'));
21 add_action('admin_action_upgrade-plugin', array($this, 'admin_action_upgrade_pluginortheme'));
22 add_action('admin_action_upgrade-theme', array($this, 'admin_action_upgrade_pluginortheme'));
23
24 add_action('admin_head', array($this,'admin_head'));
25 add_filter('plugin_action_links', array($this, 'plugin_action_links'), 10, 2);
26 add_action('wp_ajax_updraft_download_backup', array($this, 'updraft_download_backup'));
27 add_action('wp_ajax_updraft_ajax', array($this, 'updraft_ajax_handler'));
28 add_action('wp_ajax_plupload_action', array($this,'plupload_action'));
29 add_action('wp_ajax_plupload_action2', array($this,'plupload_action2'));
30
31 global $updraftplus, $wp_version, $pagenow;
32 add_filter('updraftplus_dirlist_others', array($updraftplus, 'backup_others_dirlist'));
33
34 // First, the checks that are on all (admin) pages:
35
36 $service = UpdraftPlus_Options::get_updraft_option('updraft_service');
37
38 if (UpdraftPlus_Options::user_can_manage() && ('googledrive' === $service || is_array($service) && in_array('googledrive', $service)) && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_clientid','') != '' && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_token','') == '') {
39 add_action('admin_notices', array($this,'show_admin_warning_googledrive') );
40 }
41
42 if (UpdraftPlus_Options::user_can_manage() && ('dropbox' === $service || is_array($service) && in_array('dropbox', $service)) && UpdraftPlus_Options::get_updraft_option('updraft_dropboxtk_request_token','') == '') {
43 add_action('admin_notices', array($this,'show_admin_warning_dropbox') );
44 }
45
46 if (UpdraftPlus_Options::user_can_manage() && $this->disk_space_check(1024*1024*35) === false) add_action('admin_notices', array($this, 'show_admin_warning_diskspace'));
47
48 // Next, the actions that only come on settings pages
49 // if ($pagenow != 'options-general.php') return;
50
51 // Next, the actions that only come on the UpdraftPlus page
52 if ($pagenow != 'options-general.php' || !isset($_REQUEST['page']) || 'updraftplus' != $_REQUEST['page']) return;
53
54 if (UpdraftPlus_Options::user_can_manage() && defined('DISABLE_WP_CRON') && DISABLE_WP_CRON == true) {
55 add_action('admin_notices', array($this, 'show_admin_warning_disabledcron'));
56 }
57
58 if(UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
59 @ini_set('display_errors',1);
60 @error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
61 add_action('admin_notices', array($this, 'show_admin_debug_warning'));
62 }
63
64 // W3 Total Cache's object cache eats transients during cron jobs. Reported to them many times by multiple people.
65 // TODO: Remove: we no longer deploy transients
66 // if (defined('W3TC') && W3TC == true) {
67 // if (function_exists('w3_instance')) {
68 // $modules = w3_instance('W3_ModuleStatus');
69 // if ($modules->is_enabled('objectcache')) {
70 // add_action('admin_notices', array($this, 'show_admin_warning_w3_total_cache'));
71 // }
72 // }
73 // }
74
75 // LiteSpeed has a generic problem with terminating cron jobs
76 if (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false) {
77 if (!is_file(ABSPATH.'.htaccess') || !preg_match('/noabort/i', file_get_contents(ABSPATH.'.htaccess'))) {
78 add_action('admin_notices', array($this, 'show_admin_warning_litespeed'));
79 }
80 }
81
82 if (version_compare($wp_version, '3.2', '<')) add_action('admin_notices', array($this, 'show_admin_warning_wordpressversion'));
83
84 wp_enqueue_script('updraftplus-admin-ui', UPDRAFTPLUS_URL.'/includes/updraft-admin-ui.js', array('jquery', 'jquery-ui-dialog', 'plupload-all'));
85
86 wp_localize_script( 'updraftplus-admin-ui', 'updraftlion', array(
87 'rescanning' => __('Rescanning (looking for backups that you have uploaded manually into the internal backup store)...','updraftplus'),
88 'unexpectedresponse' => __('Unexpected response:','updraftplus'),
89 'calculating' => __('calculating...','updraftplus'),
90 'begunlooking' => __('Begun looking for this entity','updraftplus'),
91 'stilldownloading' => __('Some files are still downloading or being processed - please wait.', 'updraftplus'),
92 'processing' => __('Processing files - please wait...', 'updraftplus'),
93 'emptyresponse' => __('Error: the server sent an empty response.', 'updraftplus'),
94 'warnings' => __('Warnings:','updraftplus'),
95 'errors' => __('Errors:','updraftplus'),
96 'jsonnotunderstood' => __('Error: the server sent us a response (JSON) which we did not understand.', 'updraftplus'),
97 'error' => __('Error:','updraftplus'),
98 'fileready' => __('File ready.','updraftplus'),
99 'youshould' => __('You should:','updraftplus'),
100 'deletefromserver' => __('Delete from your web server','updraftplus'),
101 'downloadtocomputer' => __('Download to your computer','updraftplus'),
102 'andthen' => __('and then, if you wish,', 'updraftplus'),
103 'notunderstood' => __('Download error: the server sent us a response which we did not understand.', 'updraftplus'),
104 'requeststart' => __('Requesting start of backup...', 'updraftplus'),
105 'phpinfo' => __('PHP information', 'updraftplus'),
106 'raw' => __('Raw backup history', 'updraftplus'),
107 '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)). 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'),
108 'makesure' => __('(make sure that you were trying to upload a zip file previously created by UpdraftPlus)','updraftplus'),
109 'uploaderror' => __('Upload error:','updraftplus'),
110 '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'),
111 'uploaderr' => __('Upload error', 'updraftplus'),
112 'followlink' => __('Follow this link to attempt decryption and download the database file to your computer.','updraftplus'),
113 'thiskey' => __('This decryption key will be attempted:','updraftplus'),
114 'unknownresp' => __('Unknown server response:','updraftplus'),
115 'ukrespstatus' => __('Unknown server response status:','updraftplus'),
116 'uploaded' => __('The file was uploaded.','updraftplus'),
117 'backupnow' => __('Backup Now', 'updraftplus'),
118 'cancel' => __('Cancel', 'updraftplus'),
119 'delete' => __('Delete', 'updraftplus'),
120 'close' => __('Close', 'updraftplus'),
121 'restore' => __('Restore', 'updraftplus'),
122 ) );
123
124 }
125
126 function core_upgrade_preamble() {
127 if (!class_exists('UpdraftPlus_Addon_Autobackup')) {
128 if (defined('UPDRAFTPLUS_NOADS3')) return;
129 # TODO: Remove legacy/wrong use of transient any time from 1 Jun 2014
130 if (true == get_transient('updraftplus_dismissedautobackup')) return;
131 $dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismissedautobackup', 0);
132 if ($dismissed_until > time()) return;
133 }
134 ?>
135 <div id="updraft-autobackup" class="updated" style="padding: 6px; margin:8px 0px;">
136 <?php if (!class_exists('UpdraftPlus_Addon_Autobackup')) { ?>
137 <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 } ?>
138 <h3 style="margin-top: 0px;"><?php _e('Be safe with an automatic backup','updraftplus');?></h3>
139 <?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="http://updraftplus.com/shop/autobackup/">'.__('Be safe every time, without needing to remember - follow this link to learn more.' ,'updraftplus').'</a>'); ?>
140 </div>
141 <script>
142 jQuery(document).ready(function() {
143 jQuery('#updraft-autobackup').appendTo('.wrap p:first');
144 });
145 </script>
146 <?php
147 }
148
149 function admin_head() {
150
151 global $pagenow;
152 if ($pagenow != 'options-general.php' || !isset($_REQUEST['page']) || 'updraftplus' != $_REQUEST['page']) return;
153
154 $chunk_size = min(wp_max_upload_size()-1024, 1024*1024*2);
155
156 $plupload_init = array(
157 'runtimes' => 'html5,silverlight,flash,html4',
158 'browse_button' => 'plupload-browse-button',
159 'container' => 'plupload-upload-ui',
160 'drop_element' => 'drag-drop-area',
161 'file_data_name' => 'async-upload',
162 'multiple_queues' => true,
163 'max_file_size' => '100Gb',
164 'chunk_size' => $chunk_size.'b',
165 'url' => admin_url('admin-ajax.php'),
166 'flash_swf_url' => includes_url('js/plupload/plupload.flash.swf'),
167 'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'),
168 'filters' => array(array('title' => __('Allowed Files'), 'extensions' => 'zip,gz,crypt,txt')),
169 'multipart' => true,
170 'multi_selection' => true,
171 'urlstream_upload' => true,
172 // additional post data to send to our ajax hook
173 'multipart_params' => array(
174 '_ajax_nonce' => wp_create_nonce('updraft-uploader'),
175 'action' => 'plupload_action'
176 )
177 );
178
179 ?><script type="text/javascript">
180 var updraft_plupload_config=<?php echo json_encode($plupload_init); ?>;
181 var updraft_credentialtest_nonce='<?php echo wp_create_nonce('updraftplus-credentialtest-nonce');?>';
182 var updraft_download_nonce='<?php echo wp_create_nonce('updraftplus_download');?>';
183 var updraft_siteurl = '<?php echo esc_js(site_url());?>';
184 </script>
185 <?php
186 $plupload_init['browse_button'] = 'plupload-browse-button2';
187 $plupload_init['container'] = 'plupload-upload-ui2';
188 $plupload_init['drop_element'] = 'drag-drop-area2';
189 $plupload_init['multipart_params']['action'] = 'plupload_action2';
190 $plupload_init['filters'] = array(array('title' => __('Allowed Files'), 'extensions' => 'crypt'));
191 ?><script type="text/javascript">var updraft_plupload_config2=<?php echo json_encode($plupload_init); ?>;
192 var updraft_downloader_nonce = '<?php wp_create_nonce("updraftplus_download"); ?>'
193 </script>
194 <style type="text/css">
195 .updraftplus-remove a {
196 color: red;
197 }
198 .updraftplus-remove:hover {
199 background-color: red;
200 }
201 .updraftplus-remove a:hover {
202 color: #fff;
203 }
204 .drag-drop #drag-drop-area2 {
205 border: 4px dashed #ddd;
206 height: 200px;
207 }
208 #drag-drop-area2 .drag-drop-inside {
209 margin: 36px auto 0;
210 width: 350px;
211 }
212 #filelist, #filelist2 {
213 width: 100%;
214 }
215 #filelist .file, #filelist2 .file, #ud_downloadstatus .file, #ud_downloadstatus2 .file {
216 padding: 5px;
217 background: #ececec;
218 border: solid 1px #ccc;
219 margin: 4px 0;
220 }
221 #filelist .fileprogress, #filelist2 .fileprogress, #ud_downloadstatus .dlfileprogress, #ud_downloadstatus2 .dlfileprogress {
222 width: 0%;
223 background: #f6a828;
224 height: 5px;
225 }
226 #ud_downloadstatus .raw, #ud_downloadstatus2 .raw {
227 margin-top: 8px;
228 clear:left;
229 }
230 #ud_downloadstatus .file, #ud_downloadstatus2 .file {
231 margin-top: 8px;
232 }
233 </style>
234 <?php
235
236 }
237
238 function googledrive_remove_folderurlprefix($input) {
239 return preg_replace('/https:\/\/drive.google.com\/(.*)#folders\//', '', $input);
240 }
241
242 function disk_space_check($space) {
243 global $updraftplus;
244 $updraft_dir = $updraftplus->backups_dir_location();
245 $disk_free_space = @disk_free_space($updraft_dir);
246 if ($disk_free_space == false) return -1;
247 return ($disk_free_space > $space) ? true : false;
248 }
249
250 # Adds the settings link under the plugin on the plugin screen.
251 function plugin_action_links($links, $file) {
252 if ($file == 'updraftplus/updraftplus.php'){
253 $settings_link = '<a href="'.site_url().'/wp-admin/options-general.php?page=updraftplus">'.__("Settings", "updraftplus").'</a>';
254 array_unshift($links, $settings_link);
255 // $settings_link = '<a href="http://david.dw-perspective.org.uk/donate">'.__("Donate","UpdraftPlus").'</a>';
256 // array_unshift($links, $settings_link);
257 $settings_link = '<a href="http://updraftplus.com">'.__("Add-Ons / Pro Support","updraftplus").'</a>';
258 array_unshift($links, $settings_link);
259 }
260 return $links;
261 }
262
263 function admin_action_upgrade_pluginortheme() {
264
265 if (isset($_GET['action']) && ($_GET['action'] == 'upgrade-plugin' || $_GET['action'] == 'upgrade-theme') && !class_exists('UpdraftPlus_Addon_Autobackup') && !defined('UPDRAFTPLUS_NOADS3')) {
266
267 # TODO: Remove legacy/erroneous use of transient any time after 1 Jun 2014
268 $dismissed = get_transient('updraftplus_dismissedautobackup');
269 if (true == $dismissed) return;
270 $dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismissedautobackup', 0);
271 if ($dismissed_until > time()) return;
272
273 if ( 'upgrade-plugin' == $_GET['action'] ) {
274 $title = __('Update Plugin');
275 $parent_file = 'plugins.php';
276 $submenu_file = 'plugins.php';
277 } else {
278 $title = __('Update Theme');
279 $parent_file = 'themes.php';
280 $submenu_file = 'themes.php';
281 }
282
283 require_once(ABSPATH . 'wp-admin/admin-header.php');
284
285 ?>
286 <div id="updraft-autobackup" class="updated" style="float:left; padding: 6px; margin:8px 0px;">
287 <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>
288 <h3 style="margin-top: 0px;"><?php _e('Be safe with an automatic backup','updraftplus');?></h3>
289 <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="http://updraftplus.com/shop/autobackup/">'.__('Be safe every time, without needing to remember - follow this link to learn more.' ,'updraftplus').'</a>'; ?></p>
290 </div>
291 <?php
292 }
293 }
294
295 function show_admin_warning($message, $class = "updated") {
296 echo '<div class="updraftmessage '.$class.' fade">'."<p>$message</p></div>";
297 }
298
299 function show_admin_warning_disabledcron() {
300 $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="http://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>');
301 }
302
303 function show_admin_warning_diskspace() {
304 $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'));
305 }
306
307 function show_admin_warning_wordpressversion() {
308 $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.'),'3.2'),'updraftplus');
309 }
310
311 function show_admin_warning_litespeed() {
312 $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('Your website is hosted using the %s web server.','updraftplus'),'LiteSpeed').' <a href="http://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>');
313 }
314
315 function show_admin_debug_warning() {
316 $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>');
317 }
318
319 function show_admin_warning_w3_total_cache() {
320 $url = (is_multisite()) ? network_admin_url('admin.php?page=w3tc_general') : admin_url('admin.php?page=w3tc_general');
321 $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.__('W3 Total Cache\'s object cache is active. This is known to have a bug that messes with all scheduled tasks (including backup jobs).','updraftplus').' <a href="'.$url.'#object_cache">'.__('Go here to turn it off.','updraftplus').'</a> '.sprintf(__('<a href="%s">Go here</a> for more information.', 'updraftplus'),'http://updraftplus.com/faqs/whats-the-deal-with-w3-total-caches-object-cache/'));
322 }
323
324 function show_admin_warning_dropbox() {
325 $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a href="options-general.php?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>');
326 }
327
328 function show_admin_warning_googledrive() {
329 $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a href="options-general.php?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>');
330 }
331
332 // This options filter removes ABSPATH off the front of updraft_dir, if it is given absolutely and contained within it
333 function prune_updraft_dir_prefix($updraft_dir) {
334 if ('/' == substr($updraft_dir, 0, 1) || "\\" == substr($updraft_dir, 0, 1) || preg_match('/^[a-zA-Z]:/', $updraft_dir)) {
335 $wcd = trailingslashit(WP_CONTENT_DIR);
336 if (strpos($updraft_dir, $wcd) === 0) {
337 $updraft_dir = substr($updraft_dir, strlen($wcd));
338 }
339 # Legacy
340 // if (strpos($updraft_dir, ABSPATH) === 0) {
341 // $updraft_dir = substr($updraft_dir, strlen(ABSPATH));
342 // }
343 }
344 return $updraft_dir;
345 }
346
347 function updraft_download_backup() {
348
349 @set_time_limit(900);
350
351 global $updraftplus;
352
353 if (!isset($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'], 'updraftplus_download')) die;
354 if (!isset($_REQUEST['timestamp']) || !is_numeric($_REQUEST['timestamp']) || !isset($_REQUEST['type'])) exit;
355
356 $findex = (isset($_REQUEST['findex'])) ? $_REQUEST['findex'] : 0;
357 if (empty($findex)) $findex=0;
358
359 $backupable_entities = $updraftplus->get_backupable_file_entities(true);
360 $type_match = false;
361 foreach ($backupable_entities as $type => $info) {
362 if ($_REQUEST['type'] == $type) $type_match = true;
363 }
364
365 if (!$type_match && $_REQUEST['type'] != 'db') exit;
366
367 // Get the information on what is wanted
368 $type = $_REQUEST['type'];
369 $timestamp = $_REQUEST['timestamp'];
370
371 // You need a nonce before you can set job data. And we certainly don't yet have one.
372 $updraftplus->backup_time_nonce();
373
374 $debug_mode = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
375
376 // Set the job type before logging, as there can be different logging destinations
377 $updraftplus->jobdata_set('job_type', 'download');
378
379 // Retrieve the information from our backup history
380 $backup_history = $updraftplus->get_backup_history();
381 // Base name
382 $file = $backup_history[$timestamp][$type];
383
384 // Deal with multi-archive sets
385 if (is_array($file)) $file=$file[$findex];
386
387 // Where it should end up being downloaded to
388 $fullpath = $updraftplus->backups_dir_location().'/'.$file;
389
390 if (isset($_GET['stage']) && '2' == $_GET['stage']) {
391 $updraftplus->spool_file($type, $fullpath);
392 die;
393 }
394
395 if (isset($_POST['stage']) && 'delete' == $_POST['stage']) {
396 @unlink($fullpath);
397 echo 'deleted';
398 $updraftplus->log('The file has been deleted');
399 die;
400 }
401
402 // TODO: FIXME: Failed downloads may leave log files forever (though they are small)
403 // Note that log() assumes that the data is in _POST, not _GET
404 if ($debug_mode) $updraftplus->logfile_open($updraftplus->nonce);
405
406 $updraftplus->log("Requested to obtain file: timestamp=$timestamp, type=$type, index=$findex");
407
408 $itext = (empty($findex)) ? '' : $findex;
409 $known_size = isset($backup_history[$timestamp][$type.$itext.'-size']) ? $backup_history[$timestamp][$type.$itext.'-size'] : 0;
410
411 $services = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
412 if (is_string($services)) $services = array($services);
413
414 $updraftplus->jobdata_set('service', $service);
415
416 // Fetch it from the cloud, if we have not already got it
417
418 $needs_downloading = false;
419
420 if(!file_exists($fullpath)) {
421 //if the file doesn't exist and they're using one of the cloud options, fetch it down from the cloud.
422 $needs_downloading = true;
423 $updraftplus->log('File does not yet exist locally - needs downloading');
424 } elseif ($known_size>0 && filesize($fullpath) < $known_size) {
425 $updraftplus->log("The file was found locally (".filesize($fullpath).") but did not match the size in the backup history ($known_size) - will resume downloading");
426 $needs_downloading = true;
427 } elseif ($known_size>0) {
428 $updraftplus->log('The file was found locally and matched the recorded size from the backup history ('.round($known_size/1024,1).' Kb)');
429 } else {
430 $updraftplus->log('No file size was found recorded in the backup history. We will assume the local one is complete.');
431 $known_size = filesize($fullpath);
432 }
433
434 // The AJAX responder that updates on progress wants to see this
435 set_transient('ud_dlfile_'.$timestamp.'_'.$type.'_'.$findex, "downloading:$known_size:$fullpath", 3600);
436
437 if ($needs_downloading) {
438 // Close browser connection so that it can resume AJAX polling
439 header('Content-Length: 0');
440 header('Connection: close');
441 header('Content-Encoding: none');
442 if (session_id()) session_write_close();
443 echo "\r\n\r\n";
444 $is_downloaded = false;
445 foreach ($services as $service) {
446 if ($is_downloaded) continue;
447 $this->download_file($file, $service);
448 if (is_readable($fullpath)) {
449 clearstatcache();
450 $updraftplus->log('Remote fetch was successful (file size: '.round(filesize($fullpath)/1024,1).' Kb)');
451 $is_downloaded = true;
452 } else {
453 $updraftplus->log('Remote fetch failed');
454 }
455 }
456 }
457
458 // Now, spool the thing to the browser
459 if(is_file($fullpath) && is_readable($fullpath)) {
460
461 // That message is then picked up by the AJAX listener
462 set_transient('ud_dlfile_'.$timestamp.'_'.$type.'_'.$findex, 'downloaded:'.filesize($fullpath).":$fullpath", 3600);
463
464 } else {
465 set_transient('ud_dlfile_'.$timestamp.'_'.$type.'_'.$findex, 'failed', 3600);
466 set_transient('ud_dlerrors_'.$timestamp.'_'.$type.'_'.$findex, $updraftplus->errors, 3600);
467
468 $updraftplus->log('Remote fetch failed. File '.$fullpath.' did not exist or was unreadable. If you delete local backups then remote retrieval may have failed.');
469
470 }
471
472 @fclose($updraftplus->logfile_handle);
473 if (!$debug_mode) @unlink($updraftplus->logfile_name);
474
475 exit;
476
477 }
478
479 # Pass only a single service, as a string, into this function
480 function download_file($file, $service) {
481
482 global $updraftplus;
483
484 @set_time_limit(900);
485
486 $updraftplus->log("Requested file from remote service: $service: $file");
487
488 $method_include = UPDRAFTPLUS_DIR.'/methods/'.$service.'.php';
489 if (file_exists($method_include)) require_once($method_include);
490
491 $objname = "UpdraftPlus_BackupModule_${service}";
492 if (method_exists($objname, "download")) {
493 $remote_obj = new $objname;
494 $remote_obj->download($file);
495 } else {
496 $updraftplus->log("Automatic backup restoration is not available with the method: $service.");
497 $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');
498 }
499
500 }
501
502 // Called via AJAX
503 function updraft_ajax_handler() {
504
505 global $updraftplus;
506
507 // Test the nonce
508 $nonce = (empty($_REQUEST['nonce'])) ? "" : $_REQUEST['nonce'];
509 if (! wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce') || empty($_REQUEST['subaction'])) die('Security check');
510 if (isset($_REQUEST['subaction']) && 'lastlog' == $_REQUEST['subaction']) {
511 echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', '('.__('Nothing yet logged', 'updraftplus').')'));
512 } elseif (isset($_GET['subaction']) && 'activejobs_list' == $_GET['subaction']) {
513 if (!empty($_GET['oneshot'])) {
514 $job_id = get_site_option('updraft_oneshotnonce', false);
515 $active_jobs = (false === $job_id) ? '' : $this->print_active_job($job_id, true);
516 } else {
517 $active_jobs = $this->print_active_jobs();
518 }
519 echo json_encode(array(
520 'l' => htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', '('.__('Nothing yet logged', 'updraftplus').')')),
521 'j' => $active_jobs
522 ));
523 } elseif (isset($_REQUEST['subaction']) && 'dismissautobackup' == $_REQUEST['subaction']) {
524 UpdraftPlus_Options::update_updraft_option('updraftplus_dismissedautobackup', time() + 84*86400);
525 } elseif (isset($_GET['subaction']) && 'restore_alldownloaded' == $_GET['subaction'] && isset($_GET['restoreopts']) && isset($_GET['timestamp'])) {
526
527 $backups = $updraftplus->get_backup_history();
528 $updraft_dir = $updraftplus->backups_dir_location();
529
530 $timestamp = (int)$_GET['timestamp'];
531 if (!isset($backups[$timestamp])) {
532 echo json_encode(array('m' => '', 'w' => '', 'e' => __('No such backup set exists', 'updraftplus')));
533 die;
534 }
535
536 $mess = array();
537 parse_str($_GET['restoreopts'], $res);
538
539 if (isset($res['updraft_restore'])) {
540
541 $elements = array_flip($res['updraft_restore']);
542
543 $warn = array();
544 $err = array();
545
546 if (isset($elements['db'])) {
547 // Analyse the header of the database file + display results
548 list ($mess2, $warn2, $err2) = $this->analyse_db_file($_GET['timestamp'], $res);
549 $mess = array_merge($mess, $mess2);
550 $warn = array_merge($warn, $warn2);
551 $err = array_merge($err, $err2);
552 }
553
554 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
555 $backupable_plus_db = $backupable_entities; $backupable_plus_db['db'] = array('path' => 'path-unused', 'description' => __('Database', 'updraftplus'));
556 foreach ($backupable_plus_db as $type => $info) {
557 if (!isset($elements[$type])) continue;
558 $whatwegot = $backups[$timestamp][$type];
559 if (is_string($whatwegot)) $whatwegot = array($whatwegot);
560 $expected_index = 0;
561 $missing = '';
562 ksort($whatwegot);
563 $outof = false;
564 foreach ($whatwegot as $index => $file) {
565 if (preg_match('/\d+of(\d+)\.zip/', $file, $omatch)) { $outof = max($matches[1], 1); }
566 if ($index != $expected_index) {
567 $missing .= ($missing == '') ? (1+$expected_index) : ",".(1+$expected_index);
568 }
569 if (!file_exists($updraft_dir.'/'.$file)) {
570 $err[] = sprintf(__('File not found (you need to upload it): %s', 'updraftplus'), $updraft_dir.'/'.$file);
571 } elseif (filesize($updraft_dir.'/'.$file) == 0) {
572 $err[] = sprintf(__('File was found, but is zero-sized (you need to re-upload it): %s', 'updraftplus'), $file);
573 } else {
574 $itext = (0 == $index) ? '' : $index;
575 if (!empty($backups[$timestamp][$type.$itext.'-size']) && $backups[$timestamp][$type.$itext.'-size'] != filesize($updraft_dir.'/'.$file)) {
576 $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']);
577 }
578 do_action_ref_array("updraftplus_checkzip_$type", array($updraft_dir.'/'.$file, &$mess, &$warn, &$err));
579 }
580 $expected_index++;
581 }
582 do_action_ref_array("updraftplus_checkzip_end_$type", array(&$mess, &$warn, &$err));
583 # Detect missing archives where they are missing from the end of the set
584 if ($outof>0 && $expected_index < $outof) {
585 for ($j = $expected_index; $j<$outof; $j++) {
586 $missing .= ($missing == '') ? (1+$j) : ",".(1+$j);
587 }
588 }
589 if ('' != $missing) {
590 $warn[] = sprintf(__("This multi-archive backup set appears to have the following archives missing: %s", 'updraftplus'), $missing.' ('.$info['description'].')');
591 }
592 }
593
594 if (0 == count($err) && 0 == count($warn)) {
595 $mess_first = __('The backup archive files have been successfully processed. Now press Restore again to proceed.', 'updraftplus');
596 } elseif (0 == count($err)) {
597 $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');
598 } else {
599 $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');
600 }
601
602 echo json_encode(array('m' => '<p>'.$mess_first.'</p>'.implode('<br>', $mess), 'w' => implode('<br>', $warn), 'e' => implode('<br>', $err)));
603 }
604
605 } elseif (isset($_POST['backup_timestamp']) && 'deleteset' == $_REQUEST['subaction']) {
606 $backups = $updraftplus->get_backup_history();
607 $timestamp = $_POST['backup_timestamp'];
608 if (!isset($backups[$timestamp])) {
609 echo json_encode(array('result' => 'error', 'message' => __('Backup set not found', 'updraftplus')));
610 die;
611 }
612
613 // You need a nonce before you can set job data. And we certainly don't yet have one.
614 $updraftplus->backup_time_nonce();
615 // Set the job type before logging, as there can be different logging destinations
616 $updraftplus->jobdata_set('job_type', 'delete');
617
618 if (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) $updraftplus->logfile_open($updraftplus->nonce);
619
620 $updraft_dir = $updraftplus->backups_dir_location();
621 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
622
623 $nonce = isset($backups[$timestamp]['nonce']) ? $backups[$timestamp]['nonce'] : '';
624
625 $delete_from_service = array();
626
627 if (isset($_POST['delete_remote']) && 1==$_POST['delete_remote']) {
628 // Locate backup set
629 if (isset($backups[$timestamp]['service'])) {
630 $services = is_string($backups[$timestamp]['service']) ? array($backups[$timestamp]['service']) : $backups[$timestamp]['service'];
631 if (is_array($services)) {
632 foreach ($services as $service) {
633 if ($service != 'none') $delete_from_service[] = $service;
634 }
635 }
636 }
637 }
638
639 $files_to_delete = array();
640 foreach ($backupable_entities as $key => $ent) {
641 if (isset($backups[$timestamp][$key])) {
642 $files_to_delete[$key] = $backups[$timestamp][$key];
643 }
644 }
645 // Delete DB
646 if (isset($backups[$timestamp]['db'])) $files_to_delete['db'] = $backups[$timestamp]['db'];
647
648 // Also delete the log
649 if ($nonce && !UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
650 $files_to_delete['log'] = "log.$nonce.txt";
651 }
652
653 unset($backups[$timestamp]);
654 UpdraftPlus_Options::update_updraft_option('updraft_backup_history', $backups);
655
656 $message = '';
657
658 $local_deleted = 0;
659 $remote_deleted = 0;
660 foreach ($files_to_delete as $key => $files) {
661 # Local deletion
662 if (is_string($files)) $files=array($files);
663 foreach ($files as $file) {
664 if (is_file($updraft_dir.'/'.$file)) {
665 if (@unlink($updraft_dir.'/'.$file)) $local_deleted++;
666 }
667 }
668 if ('log' != $key && count($delete_from_service) > 0) {
669 foreach ($delete_from_service as $service) {
670 if ('email' == $service) continue;
671 if (file_exists(UPDRAFTPLUS_DIR."/methods/$service.php")) require_once(UPDRAFTPLUS_DIR."/methods/$service.php");
672 $objname = "UpdraftPlus_BackupModule_".$service;
673 $deleted = -1;
674 if (class_exists($objname)) {
675 # TODO: Re-use the object (i.e. prevent repeated connection setup/teardown)
676 $remote_obj = new $objname;
677 $deleted = $remote_obj->delete($files);
678 }
679 if ($deleted === -1) {
680 //echo __('Did not know how to delete from this cloud service.', 'updraftplus');
681 } elseif ($deleted !== false) {
682 $remote_deleted = $remote_deleted + count($files);
683 } else {
684 // Do nothing
685 }
686 }
687 }
688 }
689 $message .= __('The backup set has been removed.', 'updraftplus')."\n";
690 $message .= sprintf(__('Local archives deleted: %d', 'updraftplus'),$local_deleted)."\n";
691 $message .= sprintf(__('Remote archives deleted: %d', 'updraftplus'),$remote_deleted)."\n";
692
693 $updraftplus->log("Local archives deleted: ".$local_deleted);
694 $updraftplus->log("Remote archives deleted: ".$remote_deleted);
695
696 print json_encode(array('result' => 'success', 'message' => $message));
697
698 } elseif ('rawbackuphistory' == $_REQUEST['subaction']) {
699 echo '<h3>'.__('Known backups (raw)', 'updraftplus').'</h3><pre>';
700 var_dump($updraftplus->get_backup_history());
701 echo '</pre>';
702 echo '<h3>Files</h3><pre>';
703 $updraft_dir = $updraftplus->backups_dir_location();
704 $d = dir($updraft_dir);
705 while (false !== ($entry = $d->read())) {
706 $fp = $updraft_dir.'/'.$entry;
707 if (is_dir($fp)) {
708 $size = ' d';
709 } elseif (is_link($fp)) {
710 $size = ' l';
711 } elseif (is_file($fp)) {
712 $size = sprintf("%8.1f", round(filesize($fp)/1024, 1));
713 } else {
714 $size = ' ?';
715 }
716 printf("%s %s \n", $size, $entry);
717 }
718 echo '</pre>';
719 @$d->close();
720 } elseif ('countbackups' == $_REQUEST['subaction']) {
721 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
722 $backup_history = (is_array($backup_history))?$backup_history:array();
723 echo sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history));
724 } elseif ('ping' == $_REQUEST['subaction']) {
725 // 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
726 echo 'pong';
727 } elseif ('phpinfo' == $_REQUEST['subaction']) {
728 phpinfo(INFO_ALL ^ (INFO_CREDITS | INFO_LICENSE));
729 } elseif ('backupnow' == $_REQUEST['subaction']) {
730 echo '<strong>',__('Schedule backup','updraftplus').':</strong> ';
731 if (wp_schedule_single_event(time()+5, 'updraft_backup_all') === false) {
732 $updraftplus->log("A backup run failed to schedule");
733 echo __("Failed.",'updraftplus')."</div>";
734 } else {
735 echo htmlspecialchars(__('OK. You should soon see activity in the "Last log message" field below.','updraftplus'))." <a href=\"http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/\">".__('Nothing happening? Follow this link for help.','updraftplus')."</a></div>";
736 $updraftplus->log("A backup run has been scheduled");
737 }
738
739 } elseif (isset($_GET['subaction']) && 'lastbackup' == $_GET['subaction']) {
740 echo $this->last_backup_html();
741 } elseif (isset($_GET['subaction']) && 'activejobs_delete' == $_GET['subaction'] && isset($_GET['jobid'])) {
742
743 $cron = get_option('cron');
744 $found_it = 0;
745 foreach ($cron as $time => $job) {
746 if (isset($job['updraft_backup_resume'])) {
747 foreach ($job['updraft_backup_resume'] as $hook => $info) {
748 if (isset($info['args'][1]) && $info['args'][1] == $_GET['jobid']) {
749 $args = $cron[$time]['updraft_backup_resume'][$hook]['args'];
750 wp_unschedule_event($time, 'updraft_backup_resume', $args);
751 if (!$found_it) echo json_encode(array('ok' => 'Y', 'm' => __('Job deleted', 'updraftplus')));
752 $found_it = 1;
753 }
754 }
755 }
756 }
757
758 if (!$found_it) echo json_encode(array('ok' => 'N', 'm' => __('Could not find that job - perhaps it has already finished?', 'updraftplus')));
759
760 } elseif (isset($_GET['subaction']) && 'diskspaceused' == $_GET['subaction'] && isset($_GET['entity'])) {
761 if ($_GET['entity'] == 'updraft') {
762 echo $this->recursive_directory_size($updraftplus->backups_dir_location());
763 } else {
764 $backupable_entities = $updraftplus->get_backupable_file_entities(true, false);
765 if (!empty($backupable_entities[$_GET['entity']])) {
766 $dirs = apply_filters('updraftplus_dirlist_'.$_GET['entity'], $backupable_entities[$_GET['entity']]);
767 echo $this->recursive_directory_size($dirs);
768 } else {
769 _e('Error','updraftplus');
770 }
771 }
772 } elseif (isset($_GET['subaction']) && 'historystatus' == $_GET['subaction']) {
773 $rescan = (isset($_GET['rescan']) && $_GET['rescan'] == 1);
774 if ($rescan) $this->rebuild_backup_history();
775 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
776 $backup_history = (is_array($backup_history))?$backup_history:array();
777 echo json_encode(array('n' => sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history)), 't' => $this->existing_backup_table($backup_history)));
778 } elseif (isset($_GET['subaction']) && 'downloadstatus' == $_GET['subaction'] && isset($_GET['timestamp']) && isset($_GET['type'])) {
779
780 $response = array();
781 $findex = (isset($_GET['findex'])) ? $_GET['findex'] : '0';
782 if (empty($findex)) $findex = '0';
783
784 $response['m'] = get_transient('ud_dlmess_'.$_GET['timestamp'].'_'.$_GET['type'].'_'.$findex).'<br>';
785
786 if ($file = get_transient('ud_dlfile_'.$_GET['timestamp'].'_'.$_GET['type'].'_'.$findex)) {
787 if ('failed' == $file) {
788 $response['e'] = __('Download failed','updraftplus').'<br>';
789 $errs = get_transient('ud_dlerrors_'.$_GET['timestamp'].'_'.$_GET['type'].'_'.$findex);
790 if (is_array($errs) && !empty($errs)) {
791 $response['e'] .= '<ul style="list-style: disc inside;">';
792 foreach ($errs as $err) {
793 if (is_array($err)) {
794 $response['e'] .= '<li>'.htmlspecialchars($err['message']).'</li>';
795 } else {
796 $response['e'] .= '<li>'.htmlspecialchars($err).'</li>';
797 }
798 }
799 $response['e'] .= '</ul>';
800 }
801 } elseif (preg_match('/^downloaded:(\d+):(.*)$/', $file, $matches) && file_exists($matches[2])) {
802 $response['p'] = 100;
803 $response['f'] = $matches[2];
804 $response['s'] = (int)$matches[1];
805 $response['t'] = (int)$matches[1];
806 $response['m'] = __('File ready.', 'updraftplus');
807 } elseif (preg_match('/^downloading:(\d+):(.*)$/', $file, $matches) && file_exists($matches[2])) {
808 // Convert to bytes
809 $response['f'] = $matches[2];
810 $total_size = (int)max($matches[1], 1);
811 $cur_size = filesize($matches[2]);
812 $response['s'] = $cur_size;
813 $response['t'] = $total_size;
814 $response['m'] .= __("Download in progress", 'updraftplus').' ('.round($cur_size/1024).' / '.round(($total_size/1024)).' Kb)';
815 $response['p'] = round(100*$cur_size/$total_size);
816 } else {
817 $response['m'] .= __('No local copy present.', 'updraftplus');
818 $response['p'] = 0;
819 $response['s'] = 0;
820 $response['t'] = 1;
821 }
822 }
823
824 echo json_encode($response);
825
826 } elseif (isset($_POST['subaction']) && $_POST['subaction'] == 'credentials_test') {
827 $method = (preg_match("/^[a-z0-9]+$/", $_POST['method'])) ? $_POST['method'] : "";
828
829 // Test the credentials, return a code
830 require_once(UPDRAFTPLUS_DIR."/methods/$method.php");
831
832 $objname = "UpdraftPlus_BackupModule_${method}";
833 if (method_exists($objname, "credentials_test")) call_user_func(array('UpdraftPlus_BackupModule_'.$method, 'credentials_test'));
834 }
835
836 die;
837
838 }
839
840 function analyse_db_file($timestamp, $res) {
841
842 $mess = array(); $warn = array(); $err = array();
843
844 global $updraftplus, $wp_version;
845 include(ABSPATH.'wp-includes/version.php');
846
847 $backup = $updraftplus->get_backup_history($timestamp);
848 if (!isset($backup['nonce']) || !isset($backup['db'])) return array($mess, $warn, $err);
849
850 $updraft_dir = $updraftplus->backups_dir_location();
851
852 $db_file = (is_string($backup['db'])) ? $updraft_dir.'/'.$backup['db'] : $updraft_dir.'/'.$backup['db'][0];
853
854 if (!is_readable($db_file)) return;
855
856 // Encrypted - decrypt it
857 if ($updraftplus->is_db_encrypted($db_file)) {
858
859 $encryption = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
860
861 if (!$encryption) {
862 $err[] = sprintf(__('Error: %s', 'updraftplus'), __('Decryption failed. The database file is encrypted, but you have no encryption key entered.', 'updraftplus'));
863 return array($mess, $warn, $err);
864 }
865
866 $updraftplus->ensure_phpseclib('Crypt_Rijndael', 'Crypt/Rijndael');
867 $rijndael = new Crypt_Rijndael();
868
869 // Get decryption key
870 $rijndael->setKey($encryption);
871 $ciphertext = $rijndael->decrypt(file_get_contents($db_file));
872 if ($ciphertext) {
873 $new_db_file = $updraft_dir.'/'.basename($db_file, '.crypt');
874 if (!file_put_contents($new_db_file, $ciphertext)) {
875 $err[] = __('Failed to write out the decrypted database to the filesystem.','updraftplus');
876 return array($mess, $warn, $err);
877 }
878 $db_file = $new_db_file;
879 } else {
880 $err[] = __('Decryption failed. The most likely cause is that you used the wrong key.','updraftplus');
881 return array($mess, $warn, $err);
882 }
883 }
884
885 # Even the empty schema when gzipped comes to 1565 bytes; a blank WP 3.6 install at 5158. But we go low, in case someone wants to share single tables.
886 if (filesize($db_file) < 1000) {
887 $err[] = sprintf(__('The database is too small to be a valid WordPress database (size: %s Kb).','updraftplus'), round(filesize($db_file)/1024, 1));
888 return array($mess, $warn, $err);
889 }
890
891 $dbhandle = gzopen($db_file, 'r');
892 if (!$dbhandle) {
893 $err[] = __('Failed to open database file.','updraftplus');
894 return array($mess, $warn, $err);
895 }
896
897 # Analyse the file, print the results.
898
899 $line = 0;
900 $old_siteurl = '';
901 $old_table_prefix = '';
902 $old_siteinfo = array();
903 $gathering_siteinfo = true;
904 $old_wp_version = '';
905
906 $tables_found = array();
907
908 // TODO: If the backup is the right size/checksum, then we could restore the $line <= 100 in the 'while' condition and not bother scanning the whole thing? Or better: sort the core tables to be first so that this usually terminates early
909
910 $wanted_tables = array('terms', 'term_taxonomy', 'term_relationships', 'commentmeta', 'comments', 'links', 'options', 'postmeta', 'posts', 'users', 'usermeta');
911
912 while (!gzeof($dbhandle) && ($line<100 || count($wanted_tables)>0)) {
913 $line++;
914 // Up to 1Mb
915 $buffer = rtrim(gzgets($dbhandle, 1048576));
916 // Comments are what we are interested in
917 if (substr($buffer, 0, 1) == '#') {
918
919 if ('' == $old_siteurl && preg_match('/^\# Backup of: (http(.*))$/', $buffer, $matches)) {
920 $old_siteurl = $matches[1];
921 $mess[] = __('Backup of:', 'updraftplus').' '.htmlspecialchars($old_siteurl);
922 // Check for should-be migration
923 if ($old_siteurl != site_url()) {
924 $powarn = apply_filters('updraftplus_dbscan_urlchange', sprintf(__('Warning: %s', 'updraftplus'), '<a href="http://updraftplus.com/shop/migrator/">'.__('This backup set is from a different site - this is not a restoration, but a migration. You need the Migrator add-on in order to make this work.', 'updraftplus').'</a>'), $old_siteurl, $res);
925 if (!empty($powarn)) $warn[] = $powarn;
926 }
927 } elseif ('' == $old_wp_version && preg_match('/^\# WordPress Version: ([0-9]+(\.[0-9]+)+)/', $buffer, $matches)) {
928 $old_wp_version = $matches[1];
929 if (version_compare($old_wp_version, $wp_version, '>')) {
930 $mess[] = sprintf(__('%s version: %s', 'updraftplus'), 'WordPress', $old_wp_version);
931 $warn[] = sprintf(__('You are importing from a newer version of WordPress (%s) into an older one (%s). There are no guarantees that WordPress can handle this.', 'updraftplus'), $old_wp_version, $wp_version);
932 }
933 } elseif ('' == $old_table_prefix && preg_match('/^\# Table prefix: (\S+)$/', $buffer, $matches)) {
934 $old_table_prefix = $matches[1];
935 // echo '<strong>'.__('Old table prefix:', 'updraftplus').'</strong> '.htmlspecialchars($old_table_prefix).'<br>';
936 } elseif ($gathering_siteinfo && preg_match('/^\# Site info: (\S+)$/', $buffer, $matches)) {
937 if ('end' == $matches[1]) {
938 $gathering_siteinfo = false;
939 // Sanity checks
940 if (isset($old_siteinfo['multisite']) && !$old_siteinfo['multisite'] && is_multisite()) {
941 // Just need to check that you're crazy
942 if (!defined('UPDRAFTPLUS_EXPERIMENTAL_IMPORTINTOMULTISITE') || UPDRAFTPLUS_EXPERIMENTAL_IMPORTINTOMULTISITE != true) {
943 $err[] = sprintf(__('Error: %s', 'updraftplus'), __('You are running on WordPress multisite - but your backup is not of a multisite site.', 'updraftplus'));
944 return array($mess, $warn, $err);
945 }
946 // Got the needed code?
947 if (!class_exists('UpdraftPlusAddOn_MultiSite') || !class_exists('UpdraftPlus_Addons_Migrator')) {
948 $err[] = sprintf(__('Error: %s', 'updraftplus'), __('To import an ordinary WordPress site into a multisite installation requires both the multisite and migrator add-ons.', 'updraftplus'));
949 return array($mess, $warn, $err);
950 }
951 }
952 } elseif (preg_match('/^([^=]+)=(.*)$/', $matches[1], $kvmatches)) {
953 $key = $kvmatches[1];
954 $val = $kvmatches[2];
955 if ('multisite' == $key && $val) {
956 $mess[] = '<strong>'.__('Site information:','updraftplus').'</strong>'.' is a WordPress Network';
957 }
958 $old_siteinfo[$key]=$val;
959 }
960 }
961
962 } elseif (preg_match('/^\s*create table \`?([^\`\(]*)\`?\s*\(/i', $buffer, $matches)) {
963 $table = $matches[1];
964 $tables_found[] = $table;
965 if ($old_table_prefix) {
966 // Remove prefix
967 $table = $updraftplus->str_replace_once($old_table_prefix, '', $table);
968 if (in_array($table, $wanted_tables)) {
969 $wanted_tables = array_diff($wanted_tables, array($table));
970 }
971 }
972 }
973 }
974
975 @gzclose($dbhandle);
976
977 /* $blog_tables = "CREATE TABLE $wpdb->terms (
978 CREATE TABLE $wpdb->term_taxonomy (
979 CREATE TABLE $wpdb->term_relationships (
980 CREATE TABLE $wpdb->commentmeta (
981 CREATE TABLE $wpdb->comments (
982 CREATE TABLE $wpdb->links (
983 CREATE TABLE $wpdb->options (
984 CREATE TABLE $wpdb->postmeta (
985 CREATE TABLE $wpdb->posts (
986 $users_single_table = "CREATE TABLE $wpdb->users (
987 $users_multi_table = "CREATE TABLE $wpdb->users (
988 $usermeta_table = "CREATE TABLE $wpdb->usermeta (
989 $ms_global_tables = "CREATE TABLE $wpdb->blogs (
990 CREATE TABLE $wpdb->blog_versions (
991 CREATE TABLE $wpdb->registration_log (
992 CREATE TABLE $wpdb->site (
993 CREATE TABLE $wpdb->sitemeta (
994 CREATE TABLE $wpdb->signups (
995 */
996
997 $missing_tables = array();
998 if ($old_table_prefix) {
999 foreach ($wanted_tables as $table) {
1000 if (!in_array($old_table_prefix.$table, $tables_found)) {
1001 $missing_tables[] = $table;
1002 }
1003 }
1004 if (count($missing_tables)>0) {
1005 $warn[] = sprintf(__('This database backup is missing core WordPress tables: %s', 'updraftplus'), implode(', ', $missing_tables));
1006 }
1007 } else {
1008 $warn[] = __('UpdraftPlus was unable to find the table prefix when scanning the database backup.', 'updraftplus');
1009 }
1010
1011 return array($mess, $warn, $err);
1012
1013 }
1014
1015 function upload_dir($uploads) {
1016 global $updraftplus;
1017 $updraft_dir = $updraftplus->backups_dir_location();
1018 if (is_writable($updraft_dir)) $uploads['path'] = $updraft_dir;
1019 return $uploads;
1020 }
1021
1022 // We do actually want to over-write
1023 function unique_filename_callback($dir, $name, $ext) {
1024 return $name.$ext;
1025 }
1026
1027 function sanitize_file_name($filename) {
1028 // WordPress 3.4.2 on multisite (at least) adds in an unwanted underscore
1029 return preg_replace('/-db\.gz_\.crypt$/', '-db.gz.crypt', $filename);
1030 }
1031
1032 function plupload_action() {
1033 // check ajax nonce
1034
1035 global $updraftplus;
1036 @set_time_limit(900);
1037
1038 check_ajax_referer('updraft-uploader');
1039
1040 $updraft_dir = $updraftplus->backups_dir_location();
1041 if (!is_writable($updraft_dir)) exit;
1042
1043 add_filter('upload_dir', array($this, 'upload_dir'));
1044 add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
1045 // handle file upload
1046
1047 $farray = array( 'test_form' => true, 'action' => 'plupload_action' );
1048
1049 $farray['test_type'] = false;
1050 $farray['ext'] = 'x-gzip';
1051 $farray['type'] = 'application/octet-stream';
1052
1053 if (isset($_POST['chunks'])) {
1054
1055 } else {
1056 $farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
1057 }
1058
1059 $status = wp_handle_upload(
1060 $_FILES['async-upload'],
1061 $farray
1062 );
1063 remove_filter('upload_dir', array($this, 'upload_dir'));
1064 remove_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
1065
1066 if (isset($status['error'])) {
1067 echo 'ERROR:'.$status['error'];
1068 exit;
1069 }
1070
1071 // If this was the chunk, then we should instead be concatenating onto the final file
1072 if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
1073 $final_file = $_POST['name'];
1074 rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
1075 $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
1076
1077 // Final chunk? If so, then stich it all back together
1078 if ($_POST['chunk'] == $_POST['chunks']-1) {
1079 if ($wh = fopen($updraft_dir.'/'.$final_file, 'wb')) {
1080 for ($i=0 ; $i<$_POST['chunks']; $i++) {
1081 $rf = $updraft_dir.'/'.$final_file.'.'.$i.'.zip.tmp';
1082 if ($rh = fopen($rf, 'rb')) {
1083 while ($line = fread($rh, 32768)) fwrite($wh, $line);
1084 fclose($rh);
1085 @unlink($rf);
1086 }
1087 }
1088 fclose($wh);
1089 $status['file'] = $updraft_dir.'/'.$final_file;
1090 }
1091 }
1092
1093 }
1094
1095 if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
1096 $file = basename($status['file']);
1097 if (!preg_match('/^log\.[a-f0-9]{12}\.txt/', $file) && !preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)([0-9]+(of[0-9]+)?)?\.(zip|gz|gz\.crypt)$/i', $file, $matches)) {
1098 @unlink($status['file']);
1099 echo sprintf(__('Error: %s', 'updraftplus'),__('Bad filename format - this does not look like a file created by UpdraftPlus','updraftplus'));
1100 exit;
1101 } else {
1102 $backupable_entities = $updraftplus->get_backupable_file_entities(true);
1103 $type = $matches[3];
1104 if ('db' != $type && !isset($backupable_entities[$type]) && !preg_match('/^log\.[a-f0-9]{12}\.txt/', $file)) {
1105 @unlink($status['file']);
1106 echo 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)));
1107 exit;
1108 }
1109 }
1110 }
1111
1112 // send the uploaded file url in response
1113 echo 'OK:'.$status['url'];
1114 exit;
1115 }
1116
1117 function plupload_action2() {
1118
1119 @set_time_limit(900);
1120 global $updraftplus;
1121
1122 // check ajax nonce
1123 check_ajax_referer('updraft-uploader');
1124
1125 $updraft_dir = $updraftplus->backups_dir_location();
1126 if (!is_writable($updraft_dir)) exit;
1127
1128 add_filter('upload_dir', array($this, 'upload_dir'));
1129 add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
1130 // handle file upload
1131
1132 $farray = array( 'test_form' => true, 'action' => 'plupload_action2' );
1133
1134 $farray['test_type'] = false;
1135 $farray['ext'] = 'crypt';
1136 $farray['type'] = 'application/octet-stream';
1137
1138 if (isset($_POST['chunks'])) {
1139 // $farray['ext'] = 'zip';
1140 // $farray['type'] = 'application/zip';
1141 } else {
1142 $farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
1143 }
1144
1145 $status = wp_handle_upload(
1146 $_FILES['async-upload'],
1147 $farray
1148 );
1149 remove_filter('upload_dir', array($this, 'upload_dir'));
1150 remove_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
1151
1152 if (isset($status['error'])) {
1153 echo 'ERROR:'.$status['error'];
1154 exit;
1155 }
1156
1157 // If this was the chunk, then we should instead be concatenating onto the final file
1158 if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
1159 $final_file = $_POST['name'];
1160 rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
1161 $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
1162
1163 // Final chunk? If so, then stich it all back together
1164 if ($_POST['chunk'] == $_POST['chunks']-1) {
1165 if ($wh = fopen($updraft_dir.'/'.$final_file, 'wb')) {
1166 for ($i=0 ; $i<$_POST['chunks']; $i++) {
1167 $rf = $updraft_dir.'/'.$final_file.'.'.$i.'.zip.tmp';
1168 if ($rh = fopen($rf, 'rb')) {
1169 while ($line = fread($rh, 32768)) fwrite($wh, $line);
1170 fclose($rh);
1171 @unlink($rf);
1172 }
1173 }
1174 fclose($wh);
1175 $status['file'] = $updraft_dir.'/'.$final_file;
1176 }
1177 }
1178
1179 }
1180
1181 if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
1182 $file = basename($status['file']);
1183 if (!preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(gz\.crypt)$/i', $file)) {
1184
1185 @unlink($status['file']);
1186 echo 'ERROR:'.__('Bad filename format - this does not look like an encrypted database file created by UpdraftPlus','updraftplus');
1187
1188 exit;
1189 }
1190 }
1191
1192 // send the uploaded file url in response
1193 // echo 'OK:'.$status['url'];
1194 echo 'OK:'.$file;
1195 exit;
1196 }
1197
1198
1199 function settings_output() {
1200
1201 global $updraftplus;
1202
1203 wp_enqueue_style('jquery-ui', UPDRAFTPLUS_URL.'/includes/jquery-ui-1.8.22.custom.css');
1204
1205 /*
1206 we use request here because the initial restore is triggered by a POSTed form. we then may need to obtain credentials
1207 for the WP_Filesystem. to do this WP outputs a form, but we don't pass our parameters via that. So the values are
1208 passed back in as GET parameters. REQUEST covers both GET and POST so this logic works.
1209 */
1210 if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_restore' && isset($_REQUEST['backup_timestamp'])) {
1211 $backup_success = $this->restore_backup($_REQUEST['backup_timestamp']);
1212 if(empty($updraftplus->errors) && $backup_success === true) {
1213 // If we restored the database, then that will have out-of-date information which may confuse the user - so automatically re-scan for them.
1214 $this->rebuild_backup_history();
1215 echo '<p><strong>'.__('Restore successful!','updraftplus').'</strong></p>';
1216 echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus&updraft_restore_success=true">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1217 return;
1218 } elseif (is_wp_error($backup_success)) {
1219 echo '<p>Restore failed...</p>';
1220 $updraftplus->list_errors();
1221 echo '<b>Actions:</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1222 return;
1223 } elseif (false === $backup_success) {
1224 # 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"
1225 return;
1226 }
1227 //uncomment the below once i figure out how i want the flow of a restoration to work.
1228 //echo '<b>'__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">Return to UpdraftPlus Configuration</a>';
1229 }
1230 $deleted_old_dirs = false;
1231 if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_delete_old_dirs') {
1232
1233 echo '<h1>UpdraftPlus - '.__('Remove old directories','updraftplus').'</h1>';
1234
1235 $nonce = (empty($_REQUEST['_wpnonce'])) ? "" : $_REQUEST['_wpnonce'];
1236 if (!wp_verify_nonce($nonce, 'updraft_delete_old_dirs')) die('Security check');
1237
1238 if($this->delete_old_dirs()) {
1239 echo '<p>'.__('Old directories successfully removed.','updraftplus').'</p><br/>';
1240 $deleted_old_dirs = true;
1241 } else {
1242 echo '<p>',__('Old directory removal failed for some reason. You may want to do this manually.','updraftplus').'</p><br/>';
1243 }
1244 echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1245 return;
1246 }
1247
1248 if(isset($_GET['error'])) $this->show_admin_warning(htmlspecialchars($_GET['error']), 'error');
1249 if(isset($_GET['message'])) $this->show_admin_warning(htmlspecialchars($_GET['message']));
1250
1251 if(isset($_GET['action']) && $_GET['action'] == 'updraft_create_backup_dir' && isset($_GET['nonce']) && wp_verify_nonce($_GET['nonce'], 'create_backup_dir')) {
1252 $created = $this->create_backup_dir();
1253 if(is_wp_error($created)) {
1254 echo '<p>'.__('Backup directory could not be created','updraftplus').'...<br/>';
1255 echo '<ul style="list-style: disc inside;">';
1256 foreach ($created->get_error_messages() as $key => $msg) {
1257 echo '<li>'.htmlspecialchars($msg).'</li>';
1258 }
1259 echo '</ul></p>';
1260 } elseif ($created !== false) {
1261 echo '<p>'.__('Backup directory successfully created.','updraftplus').'</p><br/>';
1262 }
1263 echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1264 return;
1265 }
1266
1267 echo '<div id="updraft_backup_started" class="updated fade" style="display:none; max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;"></div>';
1268
1269 // updraft_file_ids is not deleted
1270 if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_all') { $updraftplus->boot_backup(true,true); }
1271 elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_db') {
1272 $updraftplus->boot_backup(false, true, false, true);
1273 // global $updraftplus_backup;
1274 // if (!is_a($updraftplus_backup, 'UpdraftPlus_Backup')) require_once(UPDRAFTPLUS_DIR.'/backup.php');
1275 // $updraftplus_backup->backup_db();
1276 } elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_wipesettings') {
1277 $settings = array('updraft_autobackup_default', 'updraftplus_tmp_googledrive_access_token', 'updraftplus_dismissedautobackup', 'updraft_interval', 'updraft_interval_database', 'updraft_retain', 'updraft_retain_db', 'updraft_encryptionphrase', 'updraft_service', 'updraft_dropbox_appkey', 'updraft_dropbox_secret', 'updraft_googledrive_clientid', 'updraft_googledrive_secret', 'updraft_googledrive_remotepath', 'updraft_ftp_login', 'updraft_ftp_pass', 'updraft_ftp_remote_path', 'updraft_server_address', 'updraft_dir', 'updraft_email', 'updraft_delete_local', 'updraft_debug_mode', 'updraft_include_plugins', 'updraft_include_themes', 'updraft_include_uploads', 'updraft_include_others', 'updraft_include_wpcore', 'updraft_include_wpcore_exclude', 'updraft_include_more',
1278 'updraft_include_blogs', 'updraft_include_mu-plugins', 'updraft_include_others_exclude', 'updraft_lastmessage', 'updraft_googledrive_clientid', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder', 'updraft_last_backup', 'updraft_starttime_files', 'updraft_starttime_db', 'updraft_startday_db', 'updraft_startday_files', 'updraft_sftp_settings', 'updraft_s3generic_login', 'updraft_s3generic_pass', 'updraft_s3generic_remote_path', 'updraft_s3generic_endpoint', 'updraft_webdav_settings', 'updraft_disable_ping', 'updraft_cloudfiles_user', 'updraft_cloudfiles_apikey', 'updraft_cloudfiles_path', 'updraft_cloudfiles_authurl', 'updraft_ssl_useservercerts', 'updraft_ssl_disableverify', 'updraft_s3_login', 'updraft_s3_pass', 'updraft_s3_remote_path', 'updraft_dreamobjects_login', 'updraft_dreamobjects_pass', 'updraft_dreamobjects_remote_path');
1279
1280 foreach ($settings as $s) UpdraftPlus_Options::delete_updraft_option($s);
1281
1282 $site_options = array('updraft_oneshotnonce');
1283 foreach ($site_options as $s) delete_site_option($s);
1284
1285 $this->show_admin_warning(__("Your settings have been wiped.",'updraftplus'));
1286 }
1287
1288 ?>
1289 <div class="wrap">
1290 <h1><?php echo $updraftplus->plugin_title; ?></h1>
1291
1292 <?php _e('By UpdraftPlus.Com','updraftplus')?> ( <a href="http://updraftplus.com">UpdraftPlus.Com</a> | <a href="http://updraftplus.com/news/"><?php _e('News','updraftplus');?></a> | <?php if (!defined('UPDRAFTPLUS_NOADS3')) { ?><a href="http://updraftplus.com/shop/"><?php _e("Premium",'updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/"><?php _e("Support",'updraftplus');?></a> | <a href="http://david.dw-perspective.org.uk"><?php _e("Lead developer's homepage",'updraftplus');?></a> | <?php if (1==0 && !defined('UPDRAFTPLUS_NOADS3')) { ?><a href="http://wordshell.net">WordShell - WordPress command line</a> | <a href="http://david.dw-perspective.org.uk/donate"><?php _e('Donate','updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/frequently-asked-questions/">FAQs</a> | <a href="http://profiles.wordpress.org/davidanderson/"><?php _e('More plugins','updraftplus');?></a> ) <?php _e('Version','updraftplus');?>: <?php echo $updraftplus->version; ?>
1293 <br>
1294
1295 <div id="updraft-hidethis">
1296 <p><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'); ?> <a href="http://updraftplus.com/do-you-have-a-javascript-or-jquery-error/"><?php _e('Go here for more information.', 'updraftplus'); ?></a></strong></p>
1297 </p>
1298 </div>
1299
1300 <?php
1301 if(isset($_GET['updraft_restore_success'])) {
1302 echo "<div class=\"updated fade\" style=\"padding:8px;\"><strong>".__('Your backup has been restored.','updraftplus').'</strong> '.__('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.')."</div>";
1303 }
1304
1305 $ws_advert = $updraftplus->wordshell_random_advert(1);
1306 if ($ws_advert) { echo '<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;">'.$ws_advert.'</div>'; }
1307
1308 if($deleted_old_dirs) echo '<div style="color:blue" class=\"updated fade\">'.__('Old directories successfully deleted.','updraftplus').'</div>';
1309
1310 if(!$updraftplus->memory_check(64)) {?>
1311 <div class="updated fade" style="padding:8px;"><?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>
1312 <?php
1313 }
1314 if($this->scan_old_dirs()) {?>
1315 <div class="updated fade" style="padding:8px;"><?php _e('Your WordPress install has old directories from its state before you restored/migrated (technical information: these are suffixed with -old). Use this button to delete them (if you have verified that the restoration worked).','updraftplus');?>
1316 <form method="post" action="<?php echo remove_query_arg(array('updraft_restore_success','action')) ?>">
1317 <?php wp_nonce_field('updraft_delete_old_dirs'); ?>
1318 <input type="hidden" name="action" value="updraft_delete_old_dirs" />
1319 <input type="submit" class="button-primary" value="<?php _e('Delete Old Directories','updraftplus');?>" />
1320 </form>
1321 </div>
1322 <?php
1323 }
1324 if(!empty($updraftplus->errors)) {
1325 echo '<div class="error fade" style="padding:8px;">';
1326 $updraftplus->list_errors();
1327 echo '</div>';
1328 }
1329 ?>
1330
1331 <h2 style="clear:left;"><?php _e('Existing Schedule And Backups','updraftplus');?></h2>
1332 <table class="form-table" style="float:left; clear: both; width:545px;">
1333 <noscript>
1334 <tr>
1335 <th><?php _e('JavaScript warning','updraftplus');?>:</th>
1336 <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>
1337 </tr>
1338 </noscript>
1339 <?php
1340 $updraft_dir = $updraftplus->backups_dir_location();
1341 // UNIX timestamp
1342 $next_scheduled_backup = wp_next_scheduled('updraft_backup');
1343 if ($next_scheduled_backup) {
1344 // Convert to GMT
1345 $next_scheduled_backup_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup);
1346 // Convert to blog time zone
1347 $next_scheduled_backup = get_date_from_gmt($next_scheduled_backup_gmt, 'D, F j, Y H:i');
1348 } else {
1349 $next_scheduled_backup = __('Nothing currently scheduled','updraftplus');
1350 }
1351
1352 $next_scheduled_backup_database = wp_next_scheduled('updraft_backup_database');
1353 if (UpdraftPlus_Options::get_updraft_option('updraft_interval_database',UpdraftPlus_Options::get_updraft_option('updraft_interval')) == UpdraftPlus_Options::get_updraft_option('updraft_interval')) {
1354 $next_scheduled_backup_database = ('Nothing currently scheduled' == $next_scheduled_backup) ? $next_scheduled_backup : __("At the same time as the files backup", 'updraftplus');
1355 } else {
1356 if ($next_scheduled_backup_database) {
1357 // Convert to GMT
1358 $next_scheduled_backup_database_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup_database);
1359 // Convert to blog time zone
1360 $next_scheduled_backup_database = get_date_from_gmt($next_scheduled_backup_database_gmt, 'D, F j, Y H:i');
1361 } else {
1362 $next_scheduled_backup_database = __('Nothing currently scheduled','updraftplus');
1363 }
1364 }
1365 $current_time = get_date_from_gmt(gmdate('Y-m-d H:i:s'), 'D, F j, Y H:i');
1366
1367 $backup_disabled = ($updraftplus->really_is_writable($updraft_dir)) ? '' : 'disabled="disabled"';
1368
1369 $last_backup_html = $this->last_backup_html();
1370
1371 ?>
1372
1373 <script>
1374 var lastbackup_laststatus = '<?php echo esc_js($last_backup_html);?>';
1375 </script>
1376
1377 <tr>
1378 <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>
1379 <td>
1380 <div style="width: 76px; float:left;"><?php _e('Files','updraftplus'); ?>:</div><div style="color:blue; float:left;"><?php echo $next_scheduled_backup?></div>
1381 <div style="width: 76px; clear: left; float:left;"><?php _e('Database','updraftplus');?>: </div><div style="color:blue; float:left;"><?php echo $next_scheduled_backup_database?></div>
1382 <div style="width: 76px; clear: left; float:left;"><?php _e('Time now','updraftplus');?>: </div><div style="color:blue; float:left;"><?php echo $current_time?></div>
1383 </td>
1384 </tr>
1385 <tr>
1386 <th><?php _e('Last backup job run:','updraftplus');?></th>
1387 <td id="updraft_last_backup"><?php echo $last_backup_html ?></td>
1388 </tr>
1389 </table>
1390 <div style="float:left; width:200px; margin-top: <?php echo (class_exists('UpdraftPlus_Addons_Migrator')) ? "20" : "0" ?>px;">
1391 <div style="margin-bottom: 10px;">
1392 <button type="button" <?php echo $backup_disabled ?> class="button-primary" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px; min-width: 170px;" onclick="jQuery('#updraft-backupnow-modal').dialog('open');"><?php _e('Backup Now','updraftplus');?></button>
1393 </div>
1394 <div style="margin-bottom: 10px;">
1395 <?php
1396 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1397 $backup_history = (is_array($backup_history))?$backup_history:array();
1398 ?>
1399 <input type="button" class="button-primary" value="<?php _e('Restore','updraftplus');?>" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px; min-width: 170px;" onclick="jQuery('.download-backups').slideDown(); updraft_historytimertoggle(1); jQuery('html,body').animate({scrollTop: jQuery('#updraft_lastlogcontainer').offset().top},'slow');">
1400 </div>
1401 <div>
1402 <button type="button" class="button-primary" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px; min-width: 170px;" onclick="jQuery('#updraft-migrate-modal').dialog('open');"><?php _e('Clone/Migrate','updraftplus');?></button>
1403 </div>
1404 </div>
1405 <br style="clear:both" />
1406 <table class="form-table">
1407
1408
1409 <tr id="updraft_lastlogmessagerow">
1410 <th><?php _e('Last log message','updraftplus');?>:</th>
1411 <td>
1412 <span id="updraft_lastlogcontainer"><?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', __('(Nothing yet logged)','updraftplus'))); ?></span><br>
1413 <a href="?page=updraftplus&action=downloadlatestmodlog&wpnonce=<?php echo wp_create_nonce('updraftplus_download') ?>"><?php _e('Download most recently modified log file','updraftplus');?></a>
1414 </td>
1415 </tr>
1416
1417 <?php $active_jobs = $this->print_active_jobs();?>
1418 <tr id="updraft_activejobsrow" style="<?php if (!$active_jobs) echo 'display:none;'; ?>">
1419 <th><?php _e('Backups in progress:', 'updraftplus');?></th>
1420 <td id="updraft_activejobs"><?php echo $active_jobs;?></td>
1421 </tr>
1422
1423 <tr>
1424 <th><?php echo htmlspecialchars(__('Backups, logs & restoring','updraftplus')); ?>:</th>
1425 <td><a id="updraft_showbackups" href="#" title="<?php _e('Press to see available backups','updraftplus');?>" onclick="jQuery('.download-backups').fadeToggle(); updraft_historytimertoggle(0);"><?php echo sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history)); ?></a></td>
1426 </tr>
1427 <?php
1428 if (defined('UPDRAFTPLUS_EXPERIMENTAL_MISC') && UPDRAFTPLUS_EXPERIMENTAL_MISC == true) {
1429 ?>
1430 <tr>
1431 <th><?php echo __('Latest UpdraftPlus.com news:', 'updraftplus'); ?></th>
1432 <td>Blah blah blah. Move to right-hand col?</td>
1433 </tr>
1434 <?php } ?>
1435
1436 </table>
1437
1438 <table class="form-table">
1439 <tr>
1440 <td style="">&nbsp;</td><td class="download-backups" style="display:none; border: 2px dashed #aaa;">
1441 <h2><?php echo __('Downloading and restoring', 'updraftplus'); ?></h2>
1442 <p style="display:none; background-color:pink; padding:8px; margin:4px;border: 1px dotted;" id="ud-whitespace-warning">
1443 <?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="http://updraftplus.com/problems-with-extra-white-space/">'.__('Please consult this FAQ for help on what to do about it.', 'updraftplus').'</a>';?>
1444 </p>
1445 <p style="max-width: 740px;"><ul style="list-style: disc inside;">
1446 <li><strong><?php _e('Downloading','updraftplus');?>:</strong> <?php _e("Pressing a button for Database/Plugins/Themes/Uploads/Others will make UpdraftPlus try to bring the backup file back from the remote storage (if any - e.g. Amazon S3, Dropbox, Google Drive, FTP) to your webserver. Then you will be allowed to download it to your computer. If the fetch from the remote storage stops progressing (wait 30 seconds to make sure), then press again to resume. Remember that you can also visit the cloud storage vendor's website directly.",'updraftplus');?></li>
1447 <li><strong><?php _e('Restoring','updraftplus');?>:</strong> <?php _e("Press the button for the backup you wish to restore. If your site is large and you are using remote storage, then you should first click on each entity in order to retrieve it back to the webserver. This will prevent time-outs from occuring during the restore process itself.",'updraftplus');?> <?php _e('More tasks:','updraftplus');?> <a href="#" onclick="jQuery('#updraft-plupload-modal').slideToggle(); return false;"><?php _e('upload backup files','updraftplus');?></a> | <a href="#" onclick="updraft_updatehistory(1); return false;" title="<?php _e('Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below.','updraftplus'); ?>"><?php _e('rescan folder for new backup sets','updraftplus');?></a></li>
1448 <li><strong><?php _e('Opera web browser','updraftplus');?>:</strong> <?php _e('If you are using this, then turn Turbo/Road mode off.','updraftplus');?></li>
1449
1450 <?php
1451 $service = UpdraftPlus_Options::get_updraft_option('updraft_service');
1452 if ($service === 'googledrive' || (is_array($service) && in_array('googledrive', $service))) {
1453 ?><li><strong><?php _e('Google Drive','updraftplus');?>:</strong> <?php _e('Google changed their permissions setup recently (April 2013). To download or restore from Google Drive, you <strong>must</strong> first re-authenticate (using the link in the Google Drive configuration section).','updraftplus');?></li>
1454 <?php } ?>
1455
1456 <li title="<?php _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 id="updraft_diskspaceused"><em>(calculating...)</em></span> <a href="#" onclick="updraftplus_diskspace(); return false;"><?php _e('refresh','updraftplus');?></a></li></ul>
1457
1458 <div id="updraft-plupload-modal" title="<?php _e('UpdraftPlus - Upload backup files','updraftplus'); ?>" style="width: 75%; margin: 16px; display:none; margin-left: 100px;">
1459 <p style="max-width: 610px;"><em><?php _e("Upload files into UpdraftPlus. Use this to import backups made on a different WordPress installation." ,'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>
1460 <div id="plupload-upload-ui" style="width: 70%;">
1461 <div id="drag-drop-area">
1462 <div class="drag-drop-inside">
1463 <p class="drag-drop-info"><?php _e('Drop backup zips here', 'updraftplus'); ?></p>
1464 <p><?php _ex('or', 'Uploader: Drop zip files here - or - Select Files'); ?></p>
1465 <p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
1466 </div>
1467 </div>
1468 <div id="filelist">
1469 </div>
1470 </div>
1471
1472 </div>
1473
1474 <div id="ud_downloadstatus"></div>
1475 <div id="updraft_existing_backups" style="margin-bottom:12px;">
1476 <?php
1477 print $this->existing_backup_table($backup_history);
1478 ?>
1479 </div>
1480 </td>
1481 </tr>
1482 </table>
1483
1484 <div id="updraft-delete-modal" title="<?php _e('Delete backup set', 'updraftplus');?>">
1485 <form id="updraft_delete_form" method="post">
1486 <p style="margin-top:3px; padding-top:0">
1487 <?php _e('Are you sure that you wish to delete this backup set?', 'updraftplus'); ?>
1488 </p>
1489 <fieldset>
1490 <input type="hidden" name="nonce" value="<?php echo wp_create_nonce('updraftplus-credentialtest-nonce');?>">
1491 <input type="hidden" name="action" value="updraft_ajax">
1492 <input type="hidden" name="subaction" value="deleteset">
1493 <input type="hidden" name="backup_timestamp" value="0" id="updraft_delete_timestamp">
1494 <input type="hidden" name="backup_nonce" value="0" id="updraft_delete_nonce">
1495 <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>
1496 <p id="updraft-delete-waitwarning" style="display:none;"><em><?php _e('Deleting... please allow time for the communications with the remote storage to complete.', 'updraftplus');?></em></p>
1497 </div>
1498 </fieldset>
1499 </form>
1500 </div>
1501
1502 <div id="updraft-restore-modal" title="UpdraftPlus - <?php _e('Restore backup','updraftplus');?>">
1503 <p><strong><?php _e('Restore backup from','updraftplus');?>:</strong> <span class="updraft_restore_date"></span></p>
1504
1505 <div id="updraft-restore-modal-stage2">
1506
1507 <p><strong><?php _e('Downloading / preparing backup files...', 'updraftplus');?></strong></p>
1508 <div id="ud_downloadstatus2"></div>
1509
1510 <div id="updraft-restore-modal-stage2a"></div>
1511
1512 </div>
1513
1514 <div id="updraft-restore-modal-stage1">
1515 <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>
1516 <form id="updraft_restore_form" method="post">
1517 <fieldset>
1518 <input type="hidden" name="action" value="updraft_restore">
1519 <input type="hidden" name="backup_timestamp" value="0" id="updraft_restore_timestamp">
1520 <?php
1521
1522 # 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
1523 if($updraftplus->detect_safe_mode()) {
1524 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="http://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/>";
1525 }
1526
1527 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
1528 foreach ($backupable_entities as $type => $info) {
1529 if (!isset($info['restorable']) || $info['restorable'] == true) {
1530 echo '<div><input id="updraft_restore_'.$type.'" type="checkbox" name="updraft_restore[]" value="'.$type.'"> <label for="updraft_restore_'.$type.'">'.$info['description'].'</label><br>';
1531
1532 do_action("updraftplus_restore_form_$type");
1533
1534 echo '</div>';
1535 } else {
1536 $sdescrip = isset($info['shortdescription']) ? $info['shortdescription'] : $info['description'];
1537 echo "<div style=\"margin: 8px 0;\"><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.'"></div>';
1538 }
1539 }
1540 ?>
1541 <div><input id="updraft_restore_db" type="checkbox" name="updraft_restore[]" value="db"> <label for="updraft_restore_db"><?php _e('Database','updraftplus'); ?></label><br>
1542
1543
1544 <div id="updraft_restorer_dboptions" style="display:none; padding:12px; margin: 8px 0 4px; border: dashed 1px;"><h4 style="margin: 0px 0px 6px; padding:0px;"><?php echo sprintf(__('%s restoration options:','updraftplus'),__('Database','updraftplus')); ?></h4>
1545
1546 <?php
1547
1548 do_action("updraftplus_restore_form_db");
1549
1550 if (!class_exists('UpdraftPlus_Addons_Migrator')) {
1551
1552 echo '<a href="http://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>';
1553
1554 }
1555
1556 ?>
1557
1558 </div>
1559
1560 </div>
1561 </fieldset>
1562 </form>
1563 <p><em><a href="http://updraftplus.com/faqs/what-should-i-understand-before-undertaking-a-restoration/" target="_new"><?php _e('Do read this helpful article of useful things to know before restoring.','updraftplus');?></a></em></p>
1564 </div>
1565
1566 </div>
1567
1568 <div id="updraft-migrate-modal" title="<?php _e('Migrate Site', 'updraftplus'); ?>">
1569
1570 <?php
1571 if (class_exists('UpdraftPlus_Addons_Migrator')) {
1572 echo '<p>'.str_replace('"', "&quot;", __('Migration of data from another site happens through the "Restore" button. A "migration" is ultimately the same as a restoration - but using backup archives that you import from another site. UpdraftPlus modifies the restoration operation appropriately, to fit the backup data to the new site.', 'updraftplus')).' '.sprintf(__('<a href="%s">Read this article to see step-by-step how it\'s done.</a>', 'updraftplus'),'http://updraftplus.com/faqs/how-do-i-migrate-to-a-new-site-location/');
1573 } else {
1574 echo '<p>'.__('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="http://updraftplus.com/shop/migrator/">'.__('Get it here.', 'updraftplus').'</a>';
1575 }
1576 ?>
1577 </p>
1578 </div>
1579
1580 <div id="updraft-iframe-modal">
1581 <div id="updraft-iframe-modal-innards">
1582 </div>
1583 </div>
1584
1585 <div id="updraft-backupnow-modal" title="UpdraftPlus - <?php _e('Perform a one-time backup','updraftplus'); ?>">
1586 <p><?php _e("To proceed, press 'Backup Now'. Then, watch the 'Last Log Message' field for activity after about 10 seconds. WordPress should start the backup running in the background.",'updraftplus');?></p>
1587
1588 <p><?php _e('Does nothing happen when you schedule backups?','updraftplus');?> <a href="http://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 help.','updraft');?></a></p>
1589 </div>
1590
1591 <?php
1592 if (is_multisite() && !file_exists(UPDRAFTPLUS_DIR.'/addons/multisite.php')) {
1593 ?>
1594 <h2>UpdraftPlus <?php _e('Multisite','updraftplus');?></h2>
1595 <table>
1596 <tr>
1597 <td>
1598 <p style="max-width:800px;"><?php echo __('Do you need WordPress Multisite support?','updraftplus').' <a href="http://updraftplus.com/">'. __('Please check out UpdraftPlus Premium, or the stand-alone Multisite add-on.','updraftplus');?></a>.</p>
1599 </td>
1600 </tr>
1601 </table>
1602 <?php } ?>
1603 <h2 style="margin-top: 6px;"><?php _e('Configure Backup Contents And Schedule','updraftplus');?></h2>
1604 <?php UpdraftPlus_Options::options_form_begin(); ?>
1605 <?php $this->settings_formcontents($last_backup_html); ?>
1606 </form>
1607 <div style="padding-top: 40px; display:none;" class="expertmode">
1608 <hr>
1609 <h2><?php _e('Debug Information And Expert Options','updraftplus');?></h2>
1610 <p>
1611 <?php
1612 echo sprintf(__('Web server:','updraftplus'), 'PHP').' '.htmlspecialchars($_SERVER["SERVER_SOFTWARE"]).' ('.htmlspecialchars(php_uname()).')<br />';
1613 $peak_memory_usage = memory_get_peak_usage(true)/1024/1024;
1614 $memory_usage = memory_get_usage(true)/1024/1024;
1615 echo __('Peak memory usage','updraftplus').': '.$peak_memory_usage.' MB<br/>';
1616 echo __('Current memory usage','updraftplus').': '.$memory_usage.' MB<br/>';
1617 echo __('PHP memory limit','updraftplus').': '.ini_get('memory_limit').' <br/>';
1618 echo sprintf(__('%s version:','updraftplus'), 'PHP').' '.phpversion().' - ';
1619 echo '<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><br/>';
1620 echo sprintf(__('%s version:','updraftplus'), 'MySQL').' '.((function_exists('mysql_get_server_info')) ? mysql_get_server_info() : '?').'<br>';
1621
1622 if (version_compare(phpversion(), '5.2.0', '>=') && extension_loaded('zip')) {
1623 $ziparchive_exists .= __('Yes', 'updraftplus');
1624 } else {
1625 $ziparchive_exists .= (method_exists('ZipArchive', 'addFile')) ? __('Yes', 'updraftplus') : __('No', 'updraftplus');
1626 }
1627
1628 echo __('PHP has support for ZipArchive::addFile:', 'updraftplus').' '.$ziparchive_exists.'<br>';
1629
1630 $binzip = $updraftplus->find_working_bin_zip(false);
1631
1632 echo __('zip executable found:', 'updraftplus').' '.((is_string($binzip)) ? __('Yes').': '.$binzip : __('No')).'<br>';
1633
1634 echo '<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><br/>';
1635
1636
1637 echo '<h3>'.__('Total (uncompressed) on-disk data:','updraftplus').'</h3>';
1638 echo '<p style="clear: left; max-width: 600px;"><em>'.__('N.B. This count is based upon what was, or was not, excluded the last time you saved the options.', 'updraftplus').'</em></p>';
1639
1640 foreach ($backupable_entities as $key => $info) {
1641
1642 $sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']);
1643 if (strlen($sdescrip) > 20 && isset($info['shortdescription'])) $sdescrip = $info['shortdescription'];
1644
1645 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>';
1646 }
1647
1648 ?>
1649
1650 </p>
1651 <p style="clear: left; padding-top: 20px; max-width: 600px; margin:0;"><?php _e('The buttons below will immediately execute a backup run, independently of WordPress\'s scheduler. If these work whilst your scheduled backups and the "Backup Now" button do absolutely nothing (i.e. not even produce a log file), then it means that your scheduler is broken. You should then disable all your other plugins, and try the "Backup Now" button. If that fails, then contact your web hosting company and ask them if they have disabled wp-cron. If it succeeds, then re-activate your other plugins one-by-one, and find the one that is the problem and report a bug to them.','updraftplus');?></p>
1652
1653 <table border="0" style="border: none;">
1654 <tbody>
1655 <tr>
1656 <td>
1657 <form method="post">
1658 <input type="hidden" name="action" value="updraft_backup_debug_all" />
1659 <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>
1660 </form>
1661 </td><td>
1662 <form method="post">
1663 <input type="hidden" name="action" value="updraft_backup_debug_db" />
1664 <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>
1665 </form>
1666 </td>
1667 </tr>
1668 </tbody>
1669 </table>
1670 <h3><?php _e('Wipe Settings','updraftplus');?></h3>
1671 <p style="max-width: 600px;"><?php _e('This button will delete all UpdraftPlus settings (but not any of your existing backups from your cloud storage). You will then need to enter all your settings again. You can also do this before deactivating/deinstalling UpdraftPlus if you wish.','updraftplus');?></p>
1672 <form method="post">
1673 <input type="hidden" name="action" value="updraft_wipesettings" />
1674 <p><input type="submit" class="button-primary" value="<?php _e('Wipe All Settings','updraftplus'); ?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will delete all your UpdraftPlus settings - are you sure you want to do this?'));?>'))" /></p>
1675 </form>
1676 </div>
1677
1678 <?php
1679 }
1680
1681 function print_active_jobs() {
1682 $cron = get_option('cron');
1683 if (!is_array($cron)) $cron = array();
1684 // $found_jobs = 0;
1685
1686 $ret = '';
1687
1688 foreach ($cron as $time => $job) {
1689 if (isset($job['updraft_backup_resume'])) {
1690 foreach ($job['updraft_backup_resume'] as $hook => $info) {
1691 if (isset($info['args'][1])) {
1692 // $found_jobs++;
1693 $job_id = $info['args'][1];
1694 $ret .= $this->print_active_job($job_id, false, $time, $info['args'][0]);
1695 }
1696 }
1697 }
1698 }
1699
1700 // if (0 == $found_jobs) {
1701 // $ret .= '<p><em>'.__('(None)', 'updraftplus').'</em></p>';
1702 // }
1703 return $ret;
1704 }
1705
1706 function print_active_job($job_id, $is_oneshot = false, $time = false, $next_resumption = false) {
1707
1708 global $updraftplus;
1709 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
1710
1711 $jobdata = $updraftplus->jobdata_getarray($job_id);
1712
1713 #if (!is_array($jobdata)) $jobdata = array();
1714 if (!isset($jobdata['backup_time'])) return '';
1715
1716 $began_at = (isset($jobdata['backup_time'])) ? get_date_from_gmt(gmdate('Y-m-d H:i:s', $jobdata['backup_time']), 'D, F j, Y H:i') : '?';
1717
1718 $jobstatus = empty($jobdata['jobstatus']) ? 'unknown' : $jobdata['jobstatus'];
1719 $stage = 0;
1720 switch ($jobstatus) {
1721 # Stage 0
1722 case 'begun':
1723 $curstage = __('Backup begun', 'updraftplus');
1724 break;
1725 # Stage 1
1726 case 'filescreating':
1727 $stage = 1;
1728 $curstage = __('Creating file backup zips', 'updraftplus');
1729 if (!empty($jobdata['filecreating_substatus']) && isset($backupable_entities[$jobdata['filecreating_substatus']['e']]['description'])) {
1730
1731 $sdescrip = preg_replace('/ \(.*\)$/', '', $backupable_entities[$jobdata['filecreating_substatus']['e']]['description']);
1732 if (strlen($sdescrip) > 20 && isset($backupable_entities[$jobdata['filecreating_substatus']]['shortdescription'])) $sdescrip = $backupable_entities[$jobdata['filecreating_substatus']]['shortdescription'];
1733 $curstage .= ' ('.$sdescrip.')';
1734 if (isset($jobdata['filecreating_substatus']['i']) && isset($jobdata['filecreating_substatus']['t'])) {
1735 $stage = min(2, 1 + ($jobdata['filecreating_substatus']['i']/max($jobdata['filecreating_substatus']['t'],1)));
1736 }
1737 }
1738 break;
1739 case 'filescreated':
1740 $stage = 2;
1741 $curstage = __('Created file backup zips', 'updraftplus');
1742 break;
1743 # Stage 2
1744 case 'dbcreating':
1745 $stage = 2;
1746 $curstage = __('Creating database backup', 'updraftplus');
1747 if (!empty($jobdata['dbcreating_substatus']['t'])) {
1748 $curstage .= ' ('.sprintf(__('table: %s', 'updraftplus'), $jobdata['dbcreating_substatus']['t']).')';
1749 if (!empty($jobdata['dbcreating_substatus']['i']) && !empty($jobdata['dbcreating_substatus']['a'])) {
1750 $stage = min(3, 2 + ($jobdata['dbcreating_substatus']['i'] / max($jobdata['dbcreating_substatus']['a'],1)));
1751 }
1752 }
1753 break;
1754 case 'dbcreated':
1755 $stage = 3;
1756 $curstage = __('Created database backup', 'updraftplus');
1757 break;
1758 # Stage 3
1759 case 'dbencrypting':
1760 $stage = 3;
1761 $curstage = __('Encrypting database', 'updraftplus');
1762 break;
1763 case 'dbencrypted':
1764 $stage = 3;
1765 $curstage = __('Encrypted database', 'updraftplus');
1766 break;
1767 # Stage 4
1768 case 'clouduploading':
1769 $stage = 4;
1770 $curstage = __('Uploading files to remote storage', 'updraftplus');
1771 if (isset($jobdata['uploading_substatus']['t']) && isset($jobdata['uploading_substatus']['i'])) {
1772 $t = max((int)$jobdata['uploading_substatus']['t'], 1);
1773 $i = min($jobdata['uploading_substatus']['i']/$t, 1);
1774 $p = min($jobdata['uploading_substatus']['p'], 1);
1775 $pd = $i + $p/$t;
1776 $stage = 4 + $pd;
1777 $curstage .= ' '.sprintf(__('(%s%%, file %s of %s)', 'updraftplus'), floor(100*$pd), $jobdata['uploading_substatus']['i']+1, $t);
1778 }
1779 break;
1780 case 'pruning':
1781 $stage = 5;
1782 $curstage = __('Pruning old backup sets', 'updraftplus');
1783 break;
1784 case 'resumingforerrors':
1785 $stage = -1;
1786 $curstage = __('Waiting until scheduled time to retry because of errors', 'updraftplus');
1787 break;
1788 # Stage 6
1789 case 'finished':
1790 $stage = 6;
1791 $curstage = __('Backup finished', 'updraftplus');
1792 break;
1793 default:
1794 $curstage = __('Unknown', 'updraftplus');
1795 }
1796
1797 $runs_started = $jobdata['runs_started'];
1798 $time_passed = $jobdata['run_times'];
1799 $last_checkin_ago = -1;
1800 if (is_array($time_passed)) {
1801 foreach ($time_passed as $run => $passed) {
1802 if (isset($runs_started[$run])) {
1803 $time_ago = microtime(true) - ($runs_started[$run] + $time_passed[$run]);
1804 if ($time_ago < $last_checkin_ago || $last_checkin_ago == -1) $last_checkin_ago = $time_ago;
1805 }
1806 }
1807 }
1808
1809 $next_res_txt = ($is_oneshot) ? '' : ' - '.sprintf(__("next resumption: %d (after %ss)", 'updraftplus'), $next_resumption, $time-time()). ' ';
1810 $last_activity_txt = ($last_checkin_ago >= 0) ? ' - '.sprintf(__('last activity: %ss ago', 'updraftplus'), floor($last_checkin_ago)).' ' : '';
1811
1812 if ($last_checkin_ago < 50 || $is_oneshot) {
1813 $show_inline_info = $last_activity_txt;
1814 $title_info = $next_res_txt;
1815 } else {
1816 $show_inline_info = $next_res_txt;
1817 $title_info = $last_activity_txt;
1818 }
1819
1820 $ret .= '<div style="min-width: 480px; margin-top: 4px; clear:left; float:left; padding: 8px; border: 1px solid;" id="updraft-jobid-'.$job_id.'"><span style="font-weight:bold;" title="'.esc_attr(sprintf(__('Job ID: %s', 'updraftplus'), $job_id)).$title_info.'">'.$began_at.'</span> ';
1821
1822 $ret .= $show_inline_info;
1823
1824 $ret .= '- <a href="?page=updraftplus&action=downloadlog&updraftplus_backup_nonce='.$job_id.'">'.__('show log', 'updraftplus').'</a>';
1825
1826 if (!$is_oneshot) $ret .=' - <a 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')).'" href="javascript:updraft_activejobs_delete(\''.$job_id.'\')">'.__('delete schedule', 'updraftplus').'</a>';
1827
1828 if (!empty($jobdata['warnings']) && is_array($jobdata['warnings'])) {
1829 $ret .= '<ul style="list-style: disc inside;">';
1830 foreach ($jobdata['warnings'] as $warning) {
1831 $ret .= '<li>'.sprintf(__('Warning: %s', 'updraftplus'), make_clickable(htmlspecialchars($warning))).'</li>';
1832 }
1833 $ret .= '</ul>';
1834 }
1835
1836 $ret .= '<div style="border-radius: 4px; margin-top: 8px; padding-top: 4px;border: 1px solid #aaa; width: 100%; height: 22px; position: relative; text-align: center; font-style: italic;">';
1837 $ret .= htmlspecialchars($curstage);
1838 $ret .= '<div style="z-index:-1; position: absolute; left: 0px; top: 0px; text-align: center; background-color: #f6a828; height: 100%; width:'.(($stage>0) ? (ceil((100/6)*$stage)) : '0').'%"></div>';
1839 $ret .= '</div></div>';
1840
1841 $ret .= '</div>';
1842
1843 return $ret;
1844
1845 }
1846
1847 //deletes the -old directories that are created when a backup is restored.
1848 function delete_old_dirs() {
1849 global $wp_filesystem;
1850 $credentials = request_filesystem_credentials(wp_nonce_url("options-general.php?page=updraftplus&action=updraft_delete_old_dirs", 'updraft_delete_old_dirs'));
1851 WP_Filesystem($credentials);
1852 if ( $wp_filesystem->errors->get_error_code() ) {
1853 foreach ( $wp_filesystem->errors->get_error_messages() as $message )
1854 show_message($message);
1855 exit;
1856 }
1857 // From WP_CONTENT_DIR - which contains 'themes'
1858 $ret = $this->delete_old_dirs_dir($wp_filesystem->wp_content_dir());
1859 // $ret2 = $this->delete_old_dirs_dir($wp_filesystem->abspath());
1860 $plugs = untrailingslashit($wp_filesystem->wp_plugins_dir());
1861 if ($wp_filesystem->is_dir($plugs.'-old')) {
1862 print "<strong>".__('Delete','updraftplus').": </strong>plugins-old: ";
1863 if(!$wp_filesystem->delete($plugs.'-old', true)) {
1864 $ret3 = false;
1865 print "<strong>".__('Failed', 'updraftplus')."</strong><br>";
1866 } else {
1867 $ret3 = true;
1868 print "<strong>".__('OK', 'updraftplus')."</strong><br>";
1869 }
1870 } else {
1871 $ret3 = true;
1872 }
1873
1874 return ($ret && $ret3) ? true : false;
1875 }
1876
1877 function delete_old_dirs_dir($dir) {
1878
1879 global $wp_filesystem;
1880 $list = $wp_filesystem->dirlist($dir);
1881 if (!is_array($list)) return false;
1882
1883 $ret = true;
1884 foreach ($list as $item) {
1885 if (substr($item['name'], -4, 4) == "-old") {
1886 //recursively delete
1887 print "<strong>".__('Delete','updraftplus').": </strong>".htmlspecialchars($item['name']).": ";
1888 if(!$wp_filesystem->delete($dir.$item['name'], true)) {
1889 $ret = false;
1890 print "<strong>".__('Failed', 'updraftplus')."</strong><br>";
1891 } else {
1892 print "<strong>".__('OK', 'updraftplus')."</strong><br>";
1893 }
1894 }
1895 }
1896 return $ret;
1897 }
1898
1899 // The aim is to get a directory that is writable by the webserver, because that's the only way we can create zip files
1900 function create_backup_dir() {
1901
1902 global $wp_filesystem, $updraftplus;
1903
1904 if (false === ($credentials = request_filesystem_credentials('options-general.php?page=updraftplus&action=updraft_create_backup_dir&nonce='.wp_create_nonce('create_backup_dir')))) {
1905 return false;
1906 }
1907
1908 if ( ! WP_Filesystem($credentials) ) {
1909 // our credentials were no good, ask the user for them again
1910 request_filesystem_credentials('options-general.php?page=updraftplus&action=updraft_create_backup_dir&nonce='.wp_create_nonce('create_backup_dir'), '', true);
1911 return false;
1912 }
1913
1914 $updraft_dir = $updraftplus->backups_dir_location();
1915
1916 $default_backup_dir = $wp_filesystem->find_folder(dirname($updraft_dir)).basename($updraft_dir);
1917
1918 $updraft_dir = ($updraft_dir) ? $wp_filesystem->find_folder(dirname($updraft_dir)).basename($updraft_dir) : $default_backup_dir;
1919
1920 if (!$wp_filesystem->is_dir($default_backup_dir) && !$wp_filesystem->mkdir($default_backup_dir, 0775)) {
1921 $wperr = new WP_Error;
1922 if ( $wp_filesystem->errors->get_error_code() ) {
1923 foreach ( $wp_filesystem->errors->get_error_messages() as $message ) {
1924 $wperr->add('mkdir_error', $message);
1925 }
1926 return $wperr;
1927 } else {
1928 return new WP_Error('mkdir_error', __('The request to the filesystem to create the directory failed.', 'updraftplus'));
1929 }
1930 }
1931
1932 if ($wp_filesystem->is_dir($default_backup_dir)) {
1933
1934 if ($updraftplus->really_is_writable($updraft_dir)) return true;
1935
1936 @$wp_filesystem->chmod($default_backup_dir, 0775);
1937 if ($updraftplus->really_is_writable($updraft_dir)) return true;
1938
1939 @$wp_filesystem->chmod($default_backup_dir, 0777);
1940
1941 if ($updraftplus->really_is_writable($updraft_dir)) {
1942 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>';
1943 return true;
1944 } else {
1945 @$wp_filesystem->chmod($default_backup_dir, 0775);
1946 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 to set permissions for a WordPress plugin to write to the directory.', 'updraftplus'));
1947 }
1948 }
1949
1950 return true;
1951 }
1952
1953 function execution_time_check($time) {
1954 $setting = ini_get('max_execution_time');
1955 return ( $setting==0 || $setting >= $time) ? true : false;
1956 }
1957
1958 //scans the content dir to see if any -old dirs are present
1959 function scan_old_dirs() {
1960 $dirArr = scandir(untrailingslashit(WP_CONTENT_DIR));
1961 foreach($dirArr as $dir) {
1962 if (preg_match('/-old$/', $dir)) return true;
1963 }
1964 # No need to scan ABSPATH - we don't backup there
1965 $plugdir = untrailingslashit(WP_PLUGIN_DIR);
1966 if (is_dir($plugdir.'-old')) return true;
1967 return false;
1968 }
1969
1970 function last_backup_html() {
1971
1972 global $updraftplus;
1973
1974 $updraft_last_backup = UpdraftPlus_Options::get_updraft_option('updraft_last_backup');
1975
1976 if($updraft_last_backup) {
1977
1978 // Convert to GMT, then to blog time
1979 $last_backup_text = "<span style=\"color:".(($updraft_last_backup['success']) ? 'green' : 'black').";\">".get_date_from_gmt(gmdate('Y-m-d H:i:s', $updraft_last_backup['backup_time']), 'D, F j, Y H:i').'</span><br>';
1980
1981 if (is_array($updraft_last_backup['errors'])) {
1982 foreach ($updraft_last_backup['errors'] as $err) {
1983 $level = (is_array($err)) ? $err['level'] : 'error';
1984 $message = (is_array($err)) ? $err['message'] : $err;
1985
1986 $last_backup_text .= ('warning' == $level) ? "<span style=\"color:orange;\">" : "<span style=\"color:red;\">";
1987
1988 if ('warning' == $level) {
1989 $message = sprintf(__("Warning: %s", 'updraftplus'), make_clickable(htmlspecialchars($message)));
1990 } else {
1991 $message = htmlspecialchars($message);
1992 }
1993
1994 $last_backup_text .= $message;
1995
1996 $last_backup_text .= '</span><br>';
1997 }
1998 }
1999
2000 if (!empty($updraft_last_backup['backup_nonce'])) {
2001 $updraft_dir = $updraftplus->backups_dir_location();
2002
2003 $potential_log_file = $updraft_dir."/log.".$updraft_last_backup['backup_nonce'].".txt";
2004
2005 if (is_readable($potential_log_file)) $last_backup_text .= "<a href=\"?page=updraftplus&action=downloadlog&updraftplus_backup_nonce=".$updraft_last_backup['backup_nonce']."\">".__('Download log file','updraftplus')."</a>";
2006 }
2007
2008 } else {
2009 $last_backup_text = "<span style=\"color:blue;\">".__('No backup has been completed.','updraftplus')."</span>";
2010 }
2011
2012 return $last_backup_text;
2013
2014 }
2015
2016 function settings_formcontents($last_backup_html) {
2017
2018 global $updraftplus;
2019
2020 $updraft_dir = $updraftplus->backups_dir_location();
2021
2022 ?>
2023 <table class="form-table" style="width:900px;">
2024 <tr>
2025 <th><?php _e('File backup intervals','updraftplus'); ?>:</th>
2026 <td><select id="updraft_interval" name="updraft_interval" onchange="updraft_check_same_times();">
2027 <?php
2028 $intervals = array ("manual" => _x("Manual",'i.e. Non-automatic','updraftplus'), 'every4hours' => __("Every 4 hours",'updraftplus'), 'every8hours' => __("Every 8 hours",'updraftplus'), 'twicedaily' => __("Every 12 hours",'updraftplus'), 'daily' => __("Daily",'updraftplus'), 'weekly' => __("Weekly",'updraftplus'), 'fortnightly' => __("Fortnightly",'updraftplus'), 'monthly' => __("Monthly",'updraftplus'));
2029 foreach ($intervals as $cronsched => $descrip) {
2030 echo "<option value=\"$cronsched\" ";
2031 if ($cronsched == UpdraftPlus_Options::get_updraft_option('updraft_interval','manual')) echo 'selected="selected"';
2032 echo ">$descrip</option>\n";
2033 }
2034 ?>
2035 </select> <span id="updraft_files_timings"><?php echo apply_filters('updraftplus_schedule_showfileopts', '<input type="hidden" name="updraftplus_starttime_files" value="">'); ?></span>
2036 <?php
2037 echo __('and retain this many backups', 'updraftplus').': ';
2038 $updraft_retain = UpdraftPlus_Options::get_updraft_option('updraft_retain', 1);
2039 $updraft_retain = ((int)$updraft_retain > 0) ? (int)$updraft_retain : 1;
2040 ?> <input type="text" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:40px;" />
2041 </td>
2042 </tr>
2043 <tr>
2044 <th><?php _e('Database backup intervals','updraftplus'); ?>:</th>
2045 <td><select id="updraft_interval_database" name="updraft_interval_database" onchange="updraft_check_same_times();">
2046 <?php
2047 foreach ($intervals as $cronsched => $descrip) {
2048 echo "<option value=\"$cronsched\" ";
2049 if ($cronsched == UpdraftPlus_Options::get_updraft_option('updraft_interval_database', UpdraftPlus_Options::get_updraft_option('updraft_interval'))) echo 'selected="selected"';
2050 echo ">$descrip</option>\n";
2051 }
2052 ?>
2053 </select> <span id="updraft_db_timings"><?php echo apply_filters('updraftplus_schedule_showdbopts', '<input type="hidden" name="updraftplus_starttime_db" value="">'); ?></span>
2054 <?php
2055 echo __('and retain this many backups', 'updraftplus').': ';
2056 $updraft_retain_db = UpdraftPlus_Options::get_updraft_option('updraft_retain_db', $updraft_retain);
2057 $updraft_retain_db = ((int)$updraft_retain_db > 0) ? (int)$updraft_retain_db : 1;
2058 ?> <input type="text" name="updraft_retain_db" value="<?php echo $updraft_retain_db ?>" style="width:40px" />
2059 </td>
2060 </tr>
2061 <tr class="backup-interval-description">
2062 <td></td><td><p><?php echo htmlspecialchars(__('If you would like to automatically schedule backups, choose schedules from the dropdowns above. Backups will occur at the intervals specified. If the two schedules are the same, then the two backups will take place together. If you choose "manual" then you must click the "Backup Now" button whenever you wish a backup to occur.', 'updraftplus')); ?></p>
2063 <?php echo apply_filters('updraftplus_fixtime_ftinfo', '<p><strong>'.__('To fix the time at which a backup should take place,','updraftplus').' </strong> ('.__('e.g. if your server is busy at day and you want to run overnight','updraftplus').'), <a href="http://updraftplus.com/shop/fix-time/">'.htmlspecialchars(__('use the "Fix Time" add-on','updraftplus')).'</a></p>'); ?>
2064 </td>
2065 </tr>
2066 <tr>
2067 <th><?php _e('Include in files backup','updraftplus');?>:</th>
2068 <td>
2069
2070 <?php
2071 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2072 $include_others_exclude = UpdraftPlus_Options::get_updraft_option('updraft_include_others_exclude',UPDRAFT_DEFAULT_OTHERS_EXCLUDE);
2073 # The true (default value if non-existent) here has the effect of forcing a default of on.
2074 foreach ($backupable_entities as $key => $info) {
2075 $included = (UpdraftPlus_Options::get_updraft_option("updraft_include_$key", apply_filters("updraftplus_defaultoption_include_".$key, true))) ? 'checked="checked"' : "";
2076 if ('others' == $key) {
2077 ?><input id="updraft_include_others" type="checkbox" name="updraft_include_others" value="1" <?php echo $included; ?> /> <label title="<?php echo sprintf(__('Your wp-content directory server path: %s', 'updraftplus'), WP_CONTENT_DIR); ?>" for="updraft_include_<?php echo $key ?>"><?php echo __('Any other directories found inside wp-content', 'updraftplus');?></label><br><?php
2078
2079 $display = ($included) ? '' : 'style="display:none;"';
2080
2081 echo "<div id=\"updraft_include_others_exclude\" $display>";
2082
2083 echo '<label for="updraft_include_others_exclude">'.__('Exclude these:', 'updraftplus').'</label>';
2084
2085 echo '<input title="'.__('If entering multiple files/directories, then separate them with commas. You can use a * at the end of any entry as a wildcard.', 'updraftplus').'" type="text" id="updraft_include_others_exclude" name="updraft_include_others_exclude" size="54" value="'.htmlspecialchars($include_others_exclude).'" />';
2086
2087 echo '<br>';
2088
2089 echo '</div>';
2090
2091 } else {
2092 echo "<input id=\"updraft_include_$key\" type=\"checkbox\" name=\"updraft_include_$key\" value=\"1\" $included /><label for=\"updraft_include_$key\"".((isset($info['htmltitle'])) ? ' title="'.htmlspecialchars($info['htmltitle']).'"' : '')."> ".$info['description']."</label><br>";
2093 do_action("updraftplus_config_option_include_$key");
2094 }
2095 }
2096 ?>
2097 <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="http://updraftplus.com/shop/">'.htmlspecialchars(__('Or, get the "More Files" add-on from our shop.', 'updraftplus'))); ?></a> <a href="http://wordshell.net"></p><p>(<?php echo __('Use WordShell for automatic backup, version control and patching', 'updraftplus');?></a>).</p></td>
2098 </td>
2099 </tr>
2100 <tr>
2101 <th><?php _e('Email','updraftplus'); ?>:</th>
2102 <td><input type="text" title="<?php _e('To send to more than one address, separate each address with a comma.', 'updraftplus'); ?>" style="width:260px" name="updraft_email" value="<?php echo UpdraftPlus_Options::get_updraft_option('updraft_email'); ?>" /> <br><?php _e('Enter an address here to have a report sent (and the whole backup, if you choose) to it.','updraftplus'); ?></td>
2103 </tr>
2104
2105 <tr>
2106 <th><?php _e('Database encryption phrase','updraftplus');?>:</th>
2107 <?php
2108 $updraft_encryptionphrase = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
2109 ?>
2110 <td><input type="<?php echo apply_filters('updraftplus_admin_secret_field_type', 'text'); ?>" name="updraft_encryptionphrase" id="updraft_encryptionphrase" value="<?php echo $updraft_encryptionphrase ?>" style="width:132px" /></td>
2111 </tr>
2112 <tr class="backup-crypt-description">
2113 <td></td><td><p><?php _e('If you enter text here, it is used to encrypt backups (Rijndael). <strong>Do make a separate record of it and do not lose it, or all your backups <em>will</em> be useless.</strong> Presently, only the database file is encrypted. This is also the key used to decrypt backups from this admin interface (so if you change it, then automatic decryption will not work until you change it back).','updraftplus');?> <a href="#" onclick="jQuery('#updraftplus_db_decrypt').val(jQuery('#updraft_encryptionphrase').val()); jQuery('#updraft-manualdecrypt-modal').slideToggle(); return false;"><?php _e('You can also decrypt a database manually here.','updraftplus');?></a></p>
2114
2115 <div id="updraft-manualdecrypt-modal" style="width: 85%; margin: 16px; display:none; margin-left: 100px;">
2116 <p><h3><?php _e("Manually decrypt a database backup file" ,'updraftplus');?></h3></p>
2117 <div id="plupload-upload-ui2" style="width: 80%;">
2118 <div id="drag-drop-area2">
2119 <div class="drag-drop-inside">
2120 <p class="drag-drop-info"><?php _e('Drop encrypted database files (db.gz.crypt files) here to upload them for decryption'); ?></p>
2121 <p><?php _ex('or', 'Uploader: Drop db.gz.crypt files here to upload them for decryption - or - Select Files'); ?></p>
2122 <p class="drag-drop-buttons"><input id="plupload-browse-button2" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
2123 <p style="margin-top: 18px;"><?php _e('Use decryption key','updraftplus')?>: <input id="updraftplus_db_decrypt" type="text" size="12"></input></p>
2124 </div>
2125 </div>
2126 <div id="filelist2">
2127 </div>
2128 </div>
2129
2130 </div>
2131
2132
2133 </td>
2134 </tr>
2135 </table>
2136
2137 <h2><?php _e('Copying Your Backup To Remote Storage','updraftplus');?></h2>
2138
2139 <?php
2140 $debug_mode = (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) ? 'checked="checked"' : "";
2141 // Should be one of s3, dropbox, ftp, googledrive, email, or whatever else is added
2142 $active_service = UpdraftPlus_Options::get_updraft_option('updraft_service');
2143 ?>
2144
2145 <table class="form-table" style="width:900px;">
2146 <tr>
2147 <th><?php _e('Choose your remote storage','updraftplus');?>:</th>
2148 <td><?php
2149
2150 if (false === apply_filters('updraftplus_storage_printoptions', false, $active_service)) {
2151 if (is_array($active_service)) $active_service = $updraftplus->just_one($active_service);
2152 ?>
2153
2154 <select name="updraft_service" id="updraft-service">
2155 <option value="none" <?php
2156 if ('none' === $active_service) echo ' selected="selected"'; ?>><?php _e('None','updraftplus'); ?></option>
2157 <?php
2158 foreach ($updraftplus->backup_methods as $method => $description) {
2159 echo "<option value=\"$method\"";
2160 if ($active_service === $method || (is_array($active_service) && in_array($method, $active_service))) echo ' selected="selected"';
2161 echo '>'.$description;
2162 echo "</option>\n";
2163 }
2164 ?>
2165 </select>
2166
2167 <?php echo '<p><a href="http://updraftplus.com/shop/morestorage/">'.htmlspecialchars(__('You can send a backup to more than one destination with an add-on.','updraftplus')).'</a></p>'; ?>
2168
2169 </td>
2170 </tr>
2171
2172 <?php } ?>
2173
2174 <?php
2175 foreach ($updraftplus->backup_methods as $method => $description) {
2176 do_action('updraftplus_config_print_before_storage', $method);
2177 require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
2178 $call_method = "UpdraftPlus_BackupModule_$method";
2179 call_user_func(array($call_method, 'config_print'));
2180 do_action('updraftplus_config_print_after_storage', $method);
2181 }
2182 ?>
2183
2184 </table>
2185 <script type="text/javascript">
2186 /* <![CDATA[ */
2187
2188 jQuery(document).ready(function() {
2189 <?php
2190 $really_is_writable = $updraftplus->really_is_writable($updraft_dir);
2191 if (!$really_is_writable) echo "jQuery('.backupdirrow').show();\n";
2192 ?>
2193 <?php
2194 if (!empty($active_service)) {
2195 if (is_array($active_service)) {
2196 foreach ($active_service as $serv) {
2197 echo "jQuery('.${serv}').show();\n";
2198 }
2199 } else {
2200 echo "jQuery('.${active_service}').show();\n";
2201 }
2202 }
2203 foreach ($updraftplus->backup_methods as $method => $description) {
2204 // already done: require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
2205 $call_method = "UpdraftPlus_BackupModule_$method";
2206 if (method_exists($call_method, 'config_print_javascript_onready')) call_user_func(array($call_method, 'config_print_javascript_onready'));
2207 }
2208 ?>
2209 });
2210 /* ]]> */
2211 </script>
2212 <table class="form-table" style="width:900px;">
2213 <tr>
2214 <td colspan="2"><h2><?php _e('Advanced / Debugging Settings','updraftplus'); ?></h2></td>
2215 </tr>
2216 <tr>
2217 <th><?php _e('Debug mode','updraftplus');?>:</th>
2218 <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. You <strong>must</strong> send us this log if you are filing a bug report.','updraftplus');?></label></td>
2219 </tr>
2220 <tr>
2221 <th><?php _e('Expert settings','updraftplus');?>:</th>
2222 <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>
2223 </tr>
2224 <?php
2225 $delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
2226 $split_every_mb = UpdraftPlus_Options::get_updraft_option('updraft_split_every', 1*800);
2227 if (!is_numeric($split_every_mb)) $split_every_mb = 1*800;
2228 if ($split_every_mb < UPDRAFTPLUS_SPLIT_MIN) $split_every_mb = UPDRAFTPLUS_SPLIT_MIN;
2229 ?>
2230
2231 <tr class="expertmode" style="display:none;">
2232 <th><?php _e('Split archives every:','updraftplus');?></th>
2233 <td><input type="text" name="updraft_split_every" id="updraft_split_every" value="<?php echo $split_every_mb ?>" size="5" /> Mb<br><?php _e('UpdraftPlus will split up backup archives when they exceed this file size. The default value is 800 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'); ?></td>
2234 </tr>
2235
2236 <tr class="deletelocal expertmode" style="display:none;">
2237 <th><?php _e('Delete local backup','updraftplus');?>:</th>
2238 <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>
2239 </tr>
2240
2241 <tr class="expertmode backupdirrow" style="display:none;">
2242 <th><?php _e('Backup directory','updraftplus');?>:</th>
2243 <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>
2244 </tr>
2245 <tr class="expertmode backupdirrow" style="display:none;">
2246 <td></td><td><?php
2247
2248 if($really_is_writable) {
2249 $dir_info = '<span style="color:green">'.__('Backup directory specified is writable, which is good.','updraftplus').'</span>';
2250 } else {
2251 $dir_info = '<span style="color:red">';
2252 if (!is_dir($updraft_dir)) {
2253 $dir_info .= __('Backup directory specified does <b>not</b> exist.','updraftplus');
2254 } else {
2255 $dir_info .= __('Backup directory specified exists, but is <b>not</b> writable.','updraftplus');
2256 }
2257 $dir_info .= ' <span style="font-size:110%;font-weight:bold"><a href="options-general.php?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>';
2258 }
2259
2260 echo $dir_info.' '.__("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>
2261 </tr>
2262
2263 <tr class="expertmode" style="display:none;">
2264 <th><?php _e('Use the server\'s SSL certificates','updraftplus');?>:</th>
2265 <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>
2266 </tr>
2267
2268 <tr class="expertmode" style="display:none;">
2269 <th><?php _e('Do not verify SSL certificates','updraftplus');?>:</th>
2270 <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>
2271 </tr>
2272
2273 <tr class="expertmode" style="display:none;">
2274 <th><?php _e('Disable SSL entirely where possible', 'updraftplus');?>:</th>
2275 <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="http://updraftplus.com/faqs/i-get-ssl-certificate-errors-when-backing-up-andor-restoring/">See this FAQ also.</a></label></td>
2276 </tr>
2277
2278 <?php do_action('updraftplus_configprint_expertoptions'); ?>
2279
2280 <tr>
2281 <td></td>
2282 <td>
2283 <?php
2284 $ws_ad = $updraftplus->wordshell_random_advert(1);
2285 if ($ws_ad) {
2286 ?>
2287 <p style="margin: 10px 0; padding: 10px; font-size: 140%; background-color: lightYellow; border-color: #E6DB55; border: 1px solid; border-radius: 4px;">
2288 <?php echo $ws_ad; ?>
2289 </p>
2290 <?php
2291 }
2292 ?>
2293 </td>
2294 </tr>
2295 <tr>
2296 <td></td>
2297 <td>
2298 <input type="hidden" name="action" value="update" />
2299 <input type="submit" class="button-primary" value="<?php _e('Save Changes','updraftplus');?>" />
2300 </td>
2301 </tr>
2302 </table>
2303 <?php
2304 }
2305
2306 function show_double_warning($text, $extraclass = '') {
2307
2308 ?><div class="error updraftplusmethod <?php echo $extraclass; ?>"><p><?php echo $text; ?></p></div>
2309
2310 <p><?php echo $text; ?></p>
2311
2312 <?php
2313
2314 }
2315
2316 function optionfilter_split_every($value) {
2317 $value=absint($value);
2318 if (!$value >= UPDRAFTPLUS_SPLIT_MIN) $value = UPDRAFTPLUS_SPLIT_MIN;
2319 return $value;
2320 }
2321
2322 function curl_check($service, $has_fallback = false, $extraclass = '') {
2323 // Check requirements
2324 if (!function_exists("curl_init")) {
2325
2326 $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').' '.sprintf(__("Your options are 1) Install/enable %s or 2) Change web hosting companies - %s is a standard PHP component, and required by all cloud backup plugins that we know of.",'updraftplus'), 'Curl', 'Curl'), $extraclass);
2327
2328 } else {
2329 $curl_version = curl_version();
2330 $curl_ssl_supported= ($curl_version['features'] & CURL_VERSION_SSL);
2331 if (!$curl_ssl_supported) {
2332 if ($has_fallback) {
2333 ?><p><strong><?php _e('Warning','updraftplus'); ?>:</strong> <?php echo 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><?php
2334 } else {
2335 $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);
2336 }
2337 } else {
2338 ?><p><em><?php echo 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><?php
2339 }
2340 }
2341 }
2342
2343 function recursive_directory_size($directories) {
2344
2345 if (is_string($directories)) $directories = array($directories);
2346
2347 $size = 0;
2348
2349 foreach ($directories as $dir) {
2350 if (is_file($dir)) {
2351 $size += @filesize($dir);
2352 } else {
2353 $size += $this->recursive_directory_size_raw($dir);
2354 }
2355 }
2356
2357 if ($size > 1073741824) {
2358 return round($size / 1073741824, 1).' Gb';
2359 } elseif ($size > 1048576) {
2360 return round($size / 1048576, 1).' Mb';
2361 } elseif ($size > 1024) {
2362 return round($size / 1024, 1).' Kb';
2363 } else {
2364 return round($size, 1).' b';
2365 }
2366
2367 }
2368
2369 function recursive_directory_size_raw($directory) {
2370
2371 $size = 0;
2372 if(substr($directory,-1) == '/') $directory = substr($directory,0,-1);
2373
2374 if(!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) return -1;
2375
2376 if($handle = opendir($directory)) {
2377 while(($file = readdir($handle)) !== false) {
2378 $path = $directory.'/'.$file;
2379 if($file != '.' && $file != '..') {
2380 if(is_file($path)) {
2381 $size += filesize($path);
2382 } elseif(is_dir($path)) {
2383 $handlesize = $this->recursive_directory_size_raw($path);
2384 if($handlesize >= 0) { $size += $handlesize; }# else { return -1; }
2385 }
2386 }
2387 }
2388 closedir($handle);
2389 }
2390
2391 return $size;
2392
2393 }
2394
2395 function existing_backup_table($backup_history = false) {
2396
2397 global $updraftplus;
2398 $ret = '';
2399
2400 // Fetch it if it was not passed
2401 if ($backup_history === false) $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
2402 if (!is_array($backup_history)) $backup_history=array();
2403
2404 $updraft_dir = $updraftplus->backups_dir_location();
2405
2406 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2407
2408 $ret .= '<table>';
2409
2410 krsort($backup_history);
2411
2412 foreach($backup_history as $key=>$backup) {
2413 # https://core.trac.wordpress.org/ticket/25331
2414 # $pretty_date = date_i18n('Y-m-d G:i',$key);
2415 // Convert to blog time zone
2416 $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', $key), 'Y-m-d G:i');
2417
2418 $esc_pretty_date=esc_attr($pretty_date);
2419 $entities = '';
2420 $sval = ((isset($backup['service']) && $backup['service'] != 'email' && $backup['service'] != 'none')) ? '1' : '0';
2421 $title = __('Delete this backup set', 'updraftplus');
2422 $non=$backup['nonce'];
2423 $ret .= <<<ENDHERE
2424 <tr id="updraft_existing_backups_row_$key">
2425 <td><div class="updraftplus-remove" style="width: 19px; height: 19px; padding-top:0px; font-size: 18px; text-align:center;font-weight:bold; border-radius: 7px;"><a style="text-decoration:none;" href="javascript:updraft_delete('$key', '$non', $sval);" title="$title">×</a></div></td><td><b>$pretty_date</b>
2426 ENDHERE;
2427
2428 $jobdata = $updraftplus->jobdata_getarray($non);
2429 if (is_array($jobdata) && !empty($jobdata['resume_interval']) && (empty($jobdata['jobstatus']) || 'finished' != $jobdata['jobstatus'])) {
2430 $ret .= "<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>';
2431 }
2432
2433 $ret .= "</td>\n<td>";
2434 if (isset($backup['db'])) {
2435 $entities .= '/db=0/';
2436 $sdescrip = preg_replace('/ \(.*\)$/', '', __('Database','updraftplus'));
2437 $nf = wp_nonce_field('updraftplus_download', '_wpnonce', true, false);
2438 $dbt = __('Database','updraftplus');
2439 $ret .= <<<ENDHERE
2440 <form id="uddownloadform_db_${key}_0" action="admin-ajax.php" onsubmit="return updraft_downloader('uddlstatus_', $key, 'db', '#ud_downloadstatus', '0', '$esc_pretty_date')" method="post">
2441 $nf
2442 <input type="hidden" name="action" value="updraft_download_backup" />
2443 <input type="hidden" name="type" value="db" />
2444 <input type="hidden" name="timestamp" value="$key" />
2445 <input type="submit" value="$dbt" />
2446 </form>
2447 ENDHERE;
2448 } else {
2449 $ret .= sprintf(_x('(No %s)','Message shown when no such object is available','updraftplus'), __('database', 'updraftplus'));
2450 }
2451 $ret .="</td>";
2452
2453 // Now go through each of the file entities
2454 foreach ($backupable_entities as $type => $info) {
2455 $ret .= '<td>';
2456 $sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']);
2457 if (strlen($sdescrip) > 20 && isset($info['shortdescription'])) $sdescrip = $info['shortdescription'];
2458 if (isset($backup[$type])) {
2459 if (!is_array($backup[$type])) $backup[$type]=array($backup[$type]);
2460 $nf = wp_nonce_field('updraftplus_download', '_wpnonce', true, false);
2461 $howmanyinset = count($backup[$type]);
2462 $expected_index = 0;
2463 $index_missing = false;
2464 $set_contents = '';
2465 $entities .= "/$type=";
2466 $whatfiles = $backup[$type];
2467 ksort($whatfiles);
2468 foreach ($whatfiles as $findex => $bfile) {
2469 $set_contents .= ($set_contents == '') ? $findex : ",$findex";
2470 if ($findex != $expected_index) $index_missing = true;
2471 $expected_index++;
2472 }
2473 $entities .= $set_contents.'/';
2474 $first_printed = true;
2475 foreach ($whatfiles as $findex => $bfile) {
2476 $ide = __('Press here to download','updraftplus').' '.strtolower($info['description']);
2477 $pdescrip = ($findex > 0) ? $sdescrip.' ('.($findex+1).')' : $sdescrip;
2478 if (!$first_printed) {
2479 $ret .= '<div style="display:none;">';
2480 }
2481 if (count($backup[$type]) >0) {
2482 $ide .= ' '.sprintf(__('(%d archive(s) in set).', 'updraftplus'), $howmanyinset);
2483 }
2484 if ($index_missing) {
2485 $ide .= ' '.__('You appear to be missing one or more archives from this multi-archive set.', 'updraftplus');
2486 }
2487 $ret .= <<<ENDHERE
2488 <form id="uddownloadform_${type}_${key}_${findex}" action="admin-ajax.php" onsubmit="return updraft_downloader('uddlstatus_', '$key', '$type', '#ud_downloadstatus', '$set_contents', '$esc_pretty_date')" method="post">
2489 $nf
2490 <input type="hidden" name="action" value="updraft_download_backup" />
2491 <input type="hidden" name="type" value="$type" />
2492 <input type="hidden" name="timestamp" value="$key" />
2493 <input type="hidden" name="findex" value="$findex" />
2494 <input type="submit" title="$ide" value="$pdescrip" />
2495 </form>
2496 ENDHERE;
2497 if (!$first_printed) {
2498 $ret .= '</div>';
2499 } else {
2500 $first_printed = false;
2501 }
2502 }
2503 } else {
2504 $ret .= sprintf(_x('(No %s)','Message shown when no such object is available','updraftplus'), preg_replace('/\s\(.{12,}\)/', '', strtolower($sdescrip)));
2505 }
2506 $ret .= '</td>';
2507 };
2508
2509 $ret .= '<td>';
2510 if (isset($backup['nonce']) && preg_match("/^[0-9a-f]{12}$/",$backup['nonce']) && is_readable($updraft_dir.'/log.'.$backup['nonce'].'.txt')) {
2511 $nval = $backup['nonce'];
2512 $lt = __('Backup Log','updraftplus');
2513 $ret .= <<<ENDHERE
2514 <form action="options-general.php" method="get">
2515 <input type="hidden" name="action" value="downloadlog" />
2516 <input type="hidden" name="page" value="updraftplus" />
2517 <input type="hidden" name="updraftplus_backup_nonce" value="$nval" />
2518 <input type="submit" value="$lt" />
2519 </form>
2520 ENDHERE;
2521 } else {
2522 $ret .= "(No&nbsp;backup&nbsp;log)";
2523 }
2524 $ret .= <<<ENDHERE
2525 </td>
2526 <td>
2527 <form method="post" action="">
2528 <input type="hidden" name="backup_timestamp" value="$key">
2529 <input type="hidden" name="action" value="updraft_restore" />
2530 ENDHERE;
2531 if ($entities) {
2532 $ret .= '<button title="'.__('After pressing this button, you will be given the option to choose which components you wish to restore','updraftplus').'" type="button" class="button-primary" style="padding-top:2px;padding-bottom:2px;font-size:16px !important; min-height:26px;" onclick="'."updraft_restore_setoptions('$entities'); jQuery('#updraft_restore_timestamp').val('$key'); jQuery('.updraft_restore_date').html('$pretty_date'); updraft_restore_stage = 1; jQuery('#updraft-restore-modal').dialog('open'); jQuery('#updraft-restore-modal-stage1').show();jQuery('#updraft-restore-modal-stage2').hide(); jQuery('#updraft-restore-modal-stage2a').html('');\">".__('Restore','updraftplus').'</button>';
2533 }
2534 $ret .= <<<ENDHERE
2535 </form>
2536 </td>
2537 </tr>
2538 ENDHERE;
2539 }
2540 $ret .= '</table>';
2541 return $ret;
2542 }
2543
2544 // This function examines inside the updraft directory to see if any new archives have been uploaded. If so, it adds them to the backup set. (Non-present items are also removed, only if the service is 'none').
2545 function rebuild_backup_history() {
2546
2547 global $updraftplus;
2548
2549 $known_files = array();
2550 $known_nonces = array();
2551 $changes = false;
2552
2553 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
2554 if (!is_array($backup_history)) $backup_history = array();
2555
2556 $updraft_dir = $updraftplus->backups_dir_location();
2557 if (!is_dir($updraft_dir)) return;
2558
2559 // Accumulate a list of known files
2560 foreach ($backup_history as $btime => $bdata) {
2561 $found_file = false;
2562 foreach ($bdata as $key => $values) {
2563 // Record which set this file is found in
2564 if (!is_array($values)) $values=array($values);
2565 foreach ($values as $val) {
2566 if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+([0-9]+(of[0-9]+)?)?+\.(zip|gz|gz\.crypt)$/i', $val, $matches)) {
2567 $nonce = $matches[2];
2568 if (isset($bdata['service']) && $bdata['service'] == 'none' && !is_file($updraft_dir.'/'.$val)) {
2569 # File no longer present
2570 } else {
2571 $found_file = true;
2572 $known_files[$val] = $nonce;
2573 $known_nonces[$nonce] = $btime;
2574 }
2575 }
2576 }
2577 }
2578 if (!$found_file) {
2579 unset($backup_history[$btime]);
2580 $changes = true;
2581 }
2582 }
2583
2584 if (!$handle = opendir($updraft_dir)) return;
2585
2586 while (false !== ($entry = readdir($handle))) {
2587 if ($entry != "." && $entry != "..") {
2588 if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)([0-9]+(of[0-9]+)?)?\.(zip|gz|gz\.crypt)$/i', $entry, $matches)) {
2589 $btime = strtotime($matches[1]);
2590 if ($btime > 100) {
2591 if (!isset($known_files[$entry])) {
2592 $changes = true;
2593 $nonce = $matches[2];
2594 $type = $matches[3];
2595 $index = (empty($matches[4])) ? '0' : (max((int)$matches[4]-1,0));
2596 $itext = ($index == 0) ? '' : $index;
2597 // The time from the filename does not include seconds. Need to identify the seconds to get the right time
2598 if (isset($known_nonces[$nonce])) $btime = $known_nonces[$nonce];
2599 // No cloud backup known of this file
2600 if (!isset($backup_history[$btime])) $backup_history[$btime] = array('service' => 'none' );
2601 $backup_history[$btime][$type][$index] = $entry;
2602 $fs = @filesize($updraft_dir.'/'.$entry);
2603 if (false !== $fs) $backup_history[$btime][$type.$itext.'-size'] = $fs;
2604 $backup_history[$btime]['nonce'] = $nonce;
2605 }
2606 }
2607 }
2608 }
2609 }
2610
2611 if ($changes) UpdraftPlus_Options::update_updraft_option('updraft_backup_history', $backup_history);
2612
2613 }
2614
2615 // Return values: false = 'not yet' (not necessarily terminal); WP_Error = terminal failure; true = success
2616 function restore_backup($timestamp) {
2617
2618 @set_time_limit(900);
2619
2620 global $wp_filesystem, $updraftplus;
2621 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
2622 if(!is_array($backup_history[$timestamp])) {
2623 echo '<p>'.__('This backup does not exist in the backup history - restoration aborted. Timestamp:','updraftplus')." $timestamp</p><br/>";
2624 return new WP_Error('does_not_exist', 'Backup does not exist in the backup history');
2625 }
2626
2627 // request_filesystem_credentials passes on fields just via hidden name/value pairs.
2628 // Build array of parameters to be passed via this
2629 $extra_fields = array();
2630 if (isset($_POST['updraft_restore']) && is_array($_POST['updraft_restore'])) {
2631 foreach ($_POST['updraft_restore'] as $entity) {
2632 $_POST['updraft_restore_'.$entity] = 1;
2633 $extra_fields[] = 'updraft_restore_'.$entity;
2634 }
2635 }
2636 // Now make sure that updraft_restorer_ option fields get passed along to request_filesystem_credentials
2637 foreach ($_POST as $key => $value) {
2638 if (0 === strpos($key, 'updraft_restorer_')) $extra_fields[] = $key;
2639 }
2640
2641 $credentials = request_filesystem_credentials("options-general.php?page=updraftplus&action=updraft_restore&backup_timestamp=$timestamp", '', false, false, $extra_fields);
2642 WP_Filesystem($credentials);
2643 if ( $wp_filesystem->errors->get_error_code() ) {
2644 foreach ( $wp_filesystem->errors->get_error_messages() as $message ) show_message($message);
2645 exit;
2646 }
2647
2648 # Set up logging
2649 $updraftplus->backup_time_nonce();
2650 $updraftplus->jobdata_set('job_type', 'restore');
2651 $updraftplus->logfile_open($updraftplus->nonce);
2652 # TODO: Provide download link for the log file
2653 # TODO: Automatic purging of old log files
2654 # TODO: Provide option to auto-email the log file
2655
2656 //if we make it this far then WP_Filesystem has been instantiated and is functional (tested with ftpext, what about suPHP and other situations where direct may work?)
2657 echo '<h1>'.__('UpdraftPlus Restoration: Progress', 'updraftplus').'</h1><div id="updraft-restore-progress">';
2658
2659 $updraft_dir = trailingslashit($updraftplus->backups_dir_location());
2660
2661 $service = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
2662 if (!is_array($service)) $service = array($service);
2663
2664 // 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)
2665 if (empty($_POST['updraft_restore']) || (!is_array($_POST['updraft_restore']))) $_POST['updraft_restore'] = array();
2666
2667 $entities_to_restore = array_flip($_POST['updraft_restore']);
2668
2669 $entities_log = '';
2670 foreach ($_POST as $key => $value) {
2671 if (strpos($key, 'updraft_restore_') === 0 ) {
2672 $nkey = substr($key, 16);
2673 if (!isset($entities_to_restore[$nkey])) {
2674 $_POST['updraft_restore'][] = $nkey;
2675 $entities_to_restore[$nkey] = 1;
2676 $entities_log .= ('' == $entities_log) ? $nkey : ",$nkey";
2677 }
2678 }
2679 }
2680
2681 $updraftplus->log("Restore job started. Entities to restore: $entities_log");
2682
2683 if (count($_POST['updraft_restore']) == 0) {
2684 echo '<p>'.__('ABORT: Could not find the information on which entities to restore.', 'updraftplus').'</p>';
2685 echo '<p>'.__('If making a request for support, please include this information:','updraftplus').' '.count($_POST).' : '.htmlspecialchars(serialize($_POST)).'</p>';
2686 return new WP_Error('missing_info', 'Backup information not found');
2687 }
2688
2689 /*
2690 $_POST['updraft_restore'] is typically something like: array( 0=>'db', 1=>'plugins', 2=>'themes'), etc.
2691 i.e. array ( 'db', 'plugins', themes')
2692 */
2693
2694 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2695
2696 $backup_set = $backup_history[$timestamp];
2697 uksort($backup_set, array($this, 'sort_restoration_entities'));
2698
2699 // We use a single object for each entity, because we want to store information about the backup set
2700 require_once(UPDRAFTPLUS_DIR.'/restorer.php');
2701
2702 global $updraftplus_restorer;
2703 $updraftplus_restorer = new Updraft_Restorer();
2704
2705 $second_loop = array();
2706
2707 echo "<h2>".__('Final checks', 'updraftplus').'</h2>';
2708
2709 // First loop: make sure that files are present + readable; and populate array for second loop
2710 foreach ($backup_set as $type => $files) {
2711 // All restorable entities must be given explicitly, as we can store other arbitrary data in the history array
2712 if (!isset($backupable_entities[$type]) && 'db' != $type) continue;
2713 if (isset($backupable_entities[$type]['restorable']) && $backupable_entities[$type]['restorable'] == false) continue;
2714
2715 if (!isset($entities_to_restore[$type])) continue;
2716
2717 if ($type == 'wpcore' && is_multisite() && 0 === $updraftplus_restorer->ud_backup_is_multisite) {
2718 echo "<p>$type: <strong>";
2719 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');
2720 #TODO
2721 #$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.');
2722 echo "</strong></p>";
2723 continue;
2724 }
2725
2726 if (is_string($files)) $files=array($files);
2727
2728 foreach ($files as $ind => $file) {
2729 $fullpath = $updraft_dir.$file;
2730 echo sprintf(__("Looking for %s archive: file name: %s", 'updraftplus'), $type, htmlspecialchars($file))."<br>";
2731
2732 foreach ($service as $serv) {
2733 if(!is_readable($fullpath)) {
2734 $sd = (empty($updraftplus->backup_methods[$serv])) ? $serv : $updraftplus->backup_methods[$serv];
2735 echo __("File is not locally present - needs retrieving from remote storage",'updraftplus')." ($sd)";
2736 $this->download_file($file, $serv);
2737 echo ": ";
2738 if (!is_readable($fullpath)) {
2739 echo __("Error", 'updraftplus');
2740 } else {
2741 echo __("OK", 'updraftplus');
2742 }
2743 echo '<br>';
2744 }
2745 }
2746
2747 $index = ($ind == 0) ? '' : $ind;
2748 // If a file size is stored in the backup data, then verify correctness of the local file
2749 if (isset($backup_history[$timestamp][$type.$index.'-size'])) {
2750 $fs = $backup_history[$timestamp][$type.$index.'-size'];
2751 echo __("Archive is expected to be size:",'updraftplus')." ".round($fs/1024, 1)." Kb: ";
2752 $as = @filesize($fullpath);
2753 if ($as == $fs) {
2754 echo __('OK','updraftplus').'<br>';
2755 } else {
2756 echo "<strong>".__('Error:','updraftplus')."</strong> ".__('file is size:', 'updraftplus')." ".round($as/1024)." ($fs, $as)<br>";
2757 }
2758 } else {
2759 echo __("The backup records do not contain information about the proper size of this file.",'updraftplus')."<br>";
2760 }
2761 if (!is_readable($fullpath)) {
2762 echo __('Could not find one of the files for restoration', 'updraftplus')." ($file)<br>";
2763 $updraftplus->log("$file: ".__('Could not find one of the files for restoration', 'updraftplus'), 'error');
2764 echo '</div>';
2765 return false;
2766 }
2767 }
2768
2769 $info = (isset($backupable_entities[$type])) ? $backupable_entities[$type] : array();
2770
2771 $val = $updraftplus_restorer->pre_restore_backup($files, $type, $info);
2772 if (is_wp_error($val)) {
2773 foreach ($val->get_error_messages() as $msg) {
2774 echo '<strong>'.__('Error:', 'updraftplus').'</strong> '.htmlspecialchars($msg).'<br>';
2775 }
2776 echo '</div>'; //close the updraft_restore_progress div even if we error
2777 return $val;
2778 } elseif (false === $val) {
2779 echo '</div>'; //close the updraft_restore_progress div even if we error
2780 return false;
2781 }
2782
2783 $second_loop[$type] = $files;
2784 }
2785 $updraftplus_restorer->delete = (UpdraftPlus_Options::get_updraft_option('updraft_delete_local')) ? true : false;
2786 if ('none' === $service || '' === $service) {
2787 if ($updraftplus_restorer->delete) _e('Will not delete any archives after unpacking them, because there was no cloud storage for this backup','updraftplus').'<br>';
2788 $updraftplus_restorer->delete = false;
2789 }
2790
2791 // Second loop: now actually do the restoration
2792 uksort($second_loop, array($this, 'sort_restoration_entities'));
2793 foreach ($second_loop as $type => $files) {
2794 # Types: uploads, themes, plugins, others, db
2795 $info = (isset($backupable_entities[$type])) ? $backupable_entities[$type] : array();
2796
2797 echo ('db' == $type) ? "<h2>".__('Database','updraftplus')."</h2>" : "<h2>".$info['description']."</h2>";
2798
2799
2800 if (is_string($files)) $files = array($files);
2801 foreach ($files as $file) {
2802 $val = $updraftplus_restorer->restore_backup($file, $type, $info);
2803
2804 if(is_wp_error($val)) {
2805 foreach ($val->get_error_messages() as $msg) {
2806 echo '<strong>'.__('Error message', 'updraftplus').':</strong> '.htmlspecialchars($msg).'<br>';
2807 }
2808 echo '</div>'; //close the updraft_restore_progress div even if we error
2809 return $val;
2810 } elseif (false === $val) {
2811 echo '</div>'; //close the updraft_restore_progress div even if we error
2812 return false;
2813 }
2814 }
2815 }
2816
2817 echo '</div>'; //close the updraft_restore_progress div
2818 return true;
2819 }
2820
2821 function sort_restoration_entities($a, $b) {
2822 if ($a == $b) return 0;
2823 # Put the database first
2824 if ($a == 'db') return -1;
2825 if ($b == 'db') return 1;
2826 return strcmp($a, $b);
2827 }
2828
2829 }
2830
2831 ?>
2832