PluginProbe
UpdraftPlus: WP Backup & Migration Plugin / 1.8.13
UpdraftPlus: WP Backup & Migration Plugin v1.8.13
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.8.13, at admin.php

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