PluginProbe ʕ •ᴥ•ʔ
UpdraftPlus: WP Backup & Migration Plugin / 1.9.15
UpdraftPlus: WP Backup & Migration Plugin v1.9.15
1.26.4 1.26.3 1.9.19 1.9.25 1.9.26 1.9.30 1.9.31 1.9.32 1.9.4 1.9.40 1.9.41 1.9.42 1.9.43 1.9.44 1.9.45 1.9.46 1.9.5 1.9.50 1.9.51 1.9.60 1.9.62 1.9.63 1.9.64 1.11.12 1.4.8 1.11.15 1.4.9 1.11.17 1.5.16 1.11.18 1.5.20 1.11.2 1.5.21 1.11.20 1.5.22 1.11.23 1.5.5 1.11.24 1.5.6 1.11.25 1.5.7 1.11.26 1.5.8 1.11.27 1.5.9 1.11.28 1.6.1 1.11.3 1.6.17 1.11.4 1.6.2 1.11.5 1.6.46 1.11.8 1.7.0 1.11.9 1.7.1 1.12.0 1.7.18 1.12.1 1.7.20 1.12.12 1.7.3 1.12.13 1.7.34 1.12.15 1.7.35 1.12.17 1.7.39 1.12.2 1.7.40 1.12.20 1.7.41 1.12.23 1.8.1 1.12.24 1.8.11 1.12.25 1.8.12 1.12.28 1.8.13 1.12.29 1.8.2 1.12.30 1.8.5 1.12.32 1.8.8 1.12.34 1.9.0 1.12.35 1.9.13 1.12.37 1.9.15 1.12.39 1.9.17 1.12.4 1.12.40 1.12.6 1.13.1 1.13.11 1.13.12 1.13.15 1.13.16 1.13.2 1.13.3 1.13.4 1.13.5 1.13.6 1.13.7 1.13.8 1.13.9 1.14.10 1.14.11 1.14.12 1.14.13 1.14.2 1.14.3 1.14.4 1.14.5 1.14.7 1.14.9 1.15.0 1.15.2 1.15.3 1.15.5 1.15.6 1.15.7 1.16.0 1.16.10 1.16.11 1.16.12 1.16.13 1.16.14 1.16.15 1.16.16 1.16.17 1.16.20 1.16.21 1.16.22 1.16.23 1.16.24 1.16.25 1.16.26 1.16.28 1.16.29 1.16.32 1.16.34 1.16.35 1.16.36 1.16.37 1.16.4 1.16.40 1.16.41 1.16.42 1.16.43 1.16.44 1.16.45 1.16.46 1.16.47 1.16.48 1.16.49 1.16.5 1.16.50 1.16.51 1.16.53 1.16.55 1.16.56 1.16.59 1.16.6 1.16.60 1.16.61 1.16.62 1.16.63 1.16.64 1.16.65 1.16.66 1.16.67 1.16.68 1.16.69 1.16.7 1.16.8 1.16.9 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.14 1.2.15 1.2.16 1.2.17 1.2.19 1.2.2 1.2.20 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.33 1.2.35 1.2.36 1.2.38 1.2.39 1.2.4 1.2.40 1.2.41 1.2.42 1.2.43 1.2.44 1.2.45 1.2.46 1.2.5 1.2.7 1.2.8 1.2.9 1.22.1 1.22.10 1.22.11 1.22.12 1.22.14 1.22.15 1.22.16 1.22.17 1.22.18 1.22.19 1.22.20 1.22.21 1.22.22 1.22.23 1.22.24 1.22.3 1.22.4 1.22.5 1.22.6 1.22.7 1.22.8 1.22.9 1.23.1 1.23.10 1.23.11 1.23.12 1.23.13 1.23.15 1.23.16 1.23.2 1.23.3 1.23.4 1.23.5 1.23.6 1.23.7 1.23.8 1.23.9 1.24.1 1.24.10 1.24.11 1.24.12 1.24.2 trunk 1.24.3 0.7.4 1.24.4 0.7.7 1.24.5 0.8.28 1.24.6 0.8.29 1.24.7 0.8.30 1.24.8 0.8.31 1.24.9 0.8.32 1.25.1 0.8.33 1.25.2 0.8.36 1.25.3 0.8.37 1.25.5 0.8.50 1.25.6 0.8.51 1.25.7 0.9.1 1.25.8 0.9.10 1.25.9 0.9.11 1.26.1 0.9.12 1.26.2 0.9.2 1.3.10 0.9.20 1.3.12 0.9.21 1.3.14 0.9.22 1.3.15 1.0.10 1.3.17 1.0.11 1.3.18 1.0.12 1.3.19 1.0.15 1.3.2 1.0.16 1.3.20 1.0.18 1.3.22 1.0.20 1.3.23 1.0.3 1.3.24 1.0.4 1.3.25 1.0.5 1.3.3 1.0.6 1.3.4 1.0.7 1.3.6 1.0.8 1.3.7 1.0.9 1.3.8 1.1.0 1.3.9 1.1.10 1.4.0 1.1.11 1.4.10 1.1.12 1.4.11 1.1.13 1.4.12 1.1.14 1.4.13 1.1.15 1.4.14 1.1.16 1.4.15 1.1.17 1.4.2 1.1.2 1.4.27 1.1.3 1.4.28 1.1.5 1.4.29 1.1.6 1.4.30 1.1.8 1.4.4 1.1.9 1.4.48 1.10.1 1.4.5 1.10.3 1.4.6 1.11.1 1.4.7
updraftplus / admin.php
updraftplus Last commit date
addons 13 years ago images 11 years ago includes 11 years ago languages 11 years ago methods 11 years ago oc 11 years ago admin.php 11 years ago backup.php 11 years ago class-zip.php 11 years ago example-decrypt.php 11 years ago index.html 12 years ago options.php 11 years ago readme.txt 11 years ago restorer.php 11 years ago updraftplus.php 11 years ago
admin.php
4032 lines
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 lives 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 public $logged = array();
15
16 public function __construct() {
17 $this->admin_init();
18 }
19
20 private function admin_init() {
21
22 add_action('core_upgrade_preamble', array($this, 'core_upgrade_preamble'));
23 add_action('admin_action_upgrade-plugin', array($this, 'admin_action_upgrade_pluginortheme'));
24 add_action('admin_action_upgrade-theme', array($this, 'admin_action_upgrade_pluginortheme'));
25
26 add_action('admin_head', array($this,'admin_head'));
27 add_filter((is_multisite() ? 'network_admin_' : '').'plugin_action_links', array($this, 'plugin_action_links'), 10, 2);
28 add_action('wp_ajax_updraft_download_backup', array($this, 'updraft_download_backup'));
29 add_action('wp_ajax_updraft_ajax', array($this, 'updraft_ajax_handler'));
30 add_action('wp_ajax_plupload_action', array($this,'plupload_action'));
31 add_action('wp_ajax_plupload_action2', array($this,'plupload_action2'));
32
33 global $updraftplus, $wp_version, $pagenow;
34 add_filter('updraftplus_dirlist_others', array($updraftplus, 'backup_others_dirlist'));
35 add_filter('updraftplus_dirlist_uploads', array($updraftplus, 'backup_uploads_dirlist'));
36
37 // First, the checks that are on all (admin) pages:
38
39 $service = UpdraftPlus_Options::get_updraft_option('updraft_service');
40
41 if (UpdraftPlus_Options::user_can_manage() && ('googledrive' === $service || is_array($service) && in_array('googledrive', $service))) {
42 $opts = UpdraftPlus_Options::get_updraft_option('updraft_googledrive');
43 if (empty($opts)) {
44 $clientid = UpdraftPlus_Options::get_updraft_option('updraft_googledrive_clientid', '');
45 $token = UpdraftPlus_Options::get_updraft_option('updraft_googledrive_token', '');
46 } else {
47 $clientid = $opts['clientid'];
48 $token = $opts['token'];
49 }
50 if (!empty($clientid) && empty($token)) add_action('all_admin_notices', array($this,'show_admin_warning_googledrive'));
51 }
52
53 if (UpdraftPlus_Options::user_can_manage() && ('dropbox' === $service || is_array($service) && in_array('dropbox', $service))) {
54 $opts = UpdraftPlus_Options::get_updraft_option('updraft_dropbox');
55 if (empty($opts['tk_request_token'])) {
56 add_action('all_admin_notices', array($this,'show_admin_warning_dropbox') );
57 }
58 }
59
60 if (UpdraftPlus_Options::user_can_manage() && ('bitcasa' === $service || is_array($service) && in_array('bitcasa', $service))) {
61 $opts = UpdraftPlus_Options::get_updraft_option('updraft_bitcasa');
62 if (!empty($opts['clientid']) && !empty($opts['secret']) && empty($opts['token'])) add_action('all_admin_notices', array($this,'show_admin_warning_bitcasa') );
63 }
64
65 if (UpdraftPlus_Options::user_can_manage() && $this->disk_space_check(1048576*35) === false) add_action('all_admin_notices', array($this, 'show_admin_warning_diskspace'));
66
67 // Next, the actions that only come on the UpdraftPlus page
68 if ($pagenow != UpdraftPlus_Options::admin_page() || empty($_REQUEST['page']) || 'updraftplus' != $_REQUEST['page']) return;
69
70 if (UpdraftPlus_Options::user_can_manage() && defined('DISABLE_WP_CRON') && DISABLE_WP_CRON == true) {
71 add_action('all_admin_notices', array($this, 'show_admin_warning_disabledcron'));
72 }
73
74 if (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
75 @ini_set('display_errors',1);
76 @error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
77 add_action('all_admin_notices', array($this, 'show_admin_debug_warning'));
78 }
79
80 if (null === UpdraftPlus_Options::get_updraft_option('updraft_interval')) {
81 add_action('all_admin_notices', array($this, 'show_admin_nosettings_warning'));
82 }
83
84 # Avoid false positives, by attempting to raise the limit (as happens when we actually do a backup)
85 @set_time_limit(900);
86 $max_execution_time = (int)@ini_get('max_execution_time');
87 if ($max_execution_time>0 && $max_execution_time<20) {
88 add_action('all_admin_notices', array($this, 'show_admin_warning_execution_time'));
89 }
90
91 // LiteSpeed has a generic problem with terminating cron jobs
92 if (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false) {
93 if (!is_file(ABSPATH.'.htaccess') || !preg_match('/noabort/i', file_get_contents(ABSPATH.'.htaccess'))) {
94 add_action('all_admin_notices', array($this, 'show_admin_warning_litespeed'));
95 }
96 }
97
98 if (version_compare($wp_version, '3.2', '<')) add_action('all_admin_notices', array($this, 'show_admin_warning_wordpressversion'));
99
100 add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));
101
102 }
103
104 public function admin_enqueue_scripts() {
105
106 wp_enqueue_style('jquery-ui', UPDRAFTPLUS_URL.'/includes/jquery-ui-1.8.22.custom.css');
107
108 global $wp_version;
109 if (version_compare($wp_version, '3.3', '<')) {
110 # Require a newer jQuery (3.2.1 has 1.6.1, so we go for something not too much newer). We use .on() in a way that is incompatible with < 1.7
111 wp_deregister_script('jquery');
112 wp_register_script('jquery', 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', false, '1.7.2', false);
113 wp_enqueue_script('jquery');
114 # No plupload until 3.3
115 # Put in footer, to make sure that jQuery loads first
116 wp_enqueue_script('updraftplus-admin-ui', UPDRAFTPLUS_URL.'/includes/updraft-admin-ui.js', array('jquery', 'jquery-ui-dialog'), '37', true);
117 } else {
118 wp_enqueue_script('updraftplus-admin-ui', UPDRAFTPLUS_URL.'/includes/updraft-admin-ui.js', array('jquery', 'jquery-ui-dialog', 'plupload-all'), '37');
119 }
120
121 wp_localize_script( 'updraftplus-admin-ui', 'updraftlion', array(
122 'sendonlyonwarnings' => __('Send a report only when there are warnings/errors', 'updraftplus'),
123 'wholebackup' => __('When the Email storage method is enabled, also send the entire backup', 'updraftplus'),
124 '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')),
125 'rescanning' => __('Rescanning (looking for backups that you have uploaded manually into the internal backup store)...','updraftplus'),
126 'rescanningremote' => __('Rescanning remote and local storage for backup sets...','updraftplus'),
127 'enteremailhere' => esc_attr(__('To send to more than one address, separate each address with a comma.', 'updraftplus')),
128 'excludedeverything' => __('If you exclude both the database and the files, then you have excluded everything!', 'updraftplus'),
129 'restoreproceeding' => __('The restore operation has begun. Do not press stop or close your browser until it reports itself as having finished.', 'updraftplus'),
130 'unexpectedresponse' => __('Unexpected response:','updraftplus'),
131 'servererrorcode' => __('The web server returned an error code (try again, or check your web server logs)', 'updraftplus'),
132 'newuserpass' => __("The new user's RackSpace console password is (this will not be shown again):", 'updraftplus'),
133 'trying' => __('Trying...', 'updraftplus'),
134 'calculating' => __('calculating...','updraftplus'),
135 'begunlooking' => __('Begun looking for this entity','updraftplus'),
136 'stilldownloading' => __('Some files are still downloading or being processed - please wait.', 'updraftplus'),
137 'processing' => __('Processing files - please wait...', 'updraftplus'),
138 'emptyresponse' => __('Error: the server sent an empty response.', 'updraftplus'),
139 'warnings' => __('Warnings:','updraftplus'),
140 'errors' => __('Errors:','updraftplus'),
141 'jsonnotunderstood' => __('Error: the server sent us a response (JSON) which we did not understand.', 'updraftplus'),
142 'error' => __('Error:','updraftplus'),
143 'fileready' => __('File ready.','updraftplus'),
144 'youshould' => __('You should:','updraftplus'),
145 'deletefromserver' => __('Delete from your web server','updraftplus'),
146 'downloadtocomputer' => __('Download to your computer','updraftplus'),
147 'andthen' => __('and then, if you wish,', 'updraftplus'),
148 'notunderstood' => __('Download error: the server sent us a response which we did not understand.', 'updraftplus'),
149 'requeststart' => __('Requesting start of backup...', 'updraftplus'),
150 'phpinfo' => __('PHP information', 'updraftplus'),
151 'delete_old_dirs' => __('Delete Old Directories', 'updraftplus'),
152 'raw' => __('Raw backup history', 'updraftplus'),
153 'notarchive' => __('This file does not appear to be an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)).', 'updraftplus').' '.__('However, UpdraftPlus archives are standard zip/SQL files - so if you are sure that your file has the right format, then you can rename it to match that pattern.','updraftplus'),
154 'notarchive2' => '<p>'.__('This file does not appear to be an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)).', 'updraftplus').'</p> <p><a href="http://updraftplus.com/shop/updraftplus-premium/">'.__('If this is a backup created by a different backup plugin, then UpdraftPlus Premium may be able to help you.', 'updraftplus').'</a></p>',
155 'makesure' => __('(make sure that you were trying to upload a zip file previously created by UpdraftPlus)','updraftplus'),
156 'uploaderror' => __('Upload error:','updraftplus'),
157 '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'),
158 'uploaderr' => __('Upload error', 'updraftplus'),
159 'followlink' => __('Follow this link to attempt decryption and download the database file to your computer.','updraftplus'),
160 'thiskey' => __('This decryption key will be attempted:','updraftplus'),
161 'unknownresp' => __('Unknown server response:','updraftplus'),
162 'ukrespstatus' => __('Unknown server response status:','updraftplus'),
163 'uploaded' => __('The file was uploaded.','updraftplus'),
164 'backupnow' => __('Backup Now', 'updraftplus'),
165 'cancel' => __('Cancel', 'updraftplus'),
166 'deletebutton' => __('Delete', 'updraftplus'),
167 'createbutton' => __('Create', 'updraftplus'),
168 'close' => __('Close', 'updraftplus'),
169 'restore' => __('Restore', 'updraftplus'),
170 ) );
171 }
172
173 public function core_upgrade_preamble() {
174 if (!class_exists('UpdraftPlus_Addon_Autobackup')) {
175 if (defined('UPDRAFTPLUS_NOADS_A')) return;
176 # TODO: Remove legacy/wrong use of transient any time from 1 Jun 2014
177 if (true == get_transient('updraftplus_dismissedautobackup')) return;
178 $dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismissedautobackup', 0);
179 if ($dismissed_until > time()) return;
180 }
181 ?>
182 <div id="updraft-autobackup" class="updated" style="padding: 6px; margin:8px 0px;">
183 <?php if (!class_exists('UpdraftPlus_Addon_Autobackup')) { ?>
184 <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 } ?>
185 <h3 style="margin-top: 0px;"><?php _e('Be safe with an automatic backup','updraftplus');?></h3>
186 <?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>'); ?>
187 </div>
188 <script>
189 jQuery(document).ready(function() {
190 jQuery('#updraft-autobackup').appendTo('.wrap p:first');
191 });
192 </script>
193 <?php
194 }
195
196 public function admin_head() {
197
198 global $pagenow;
199 if ($pagenow != UpdraftPlus_Options::admin_page() || !isset($_REQUEST['page']) || 'updraftplus' != $_REQUEST['page']) return;
200
201 $chunk_size = min(wp_max_upload_size()-1024, 1024*1024*2);
202
203 # The multiple_queues argument is ignored in plupload 2.x (WP3.9+) - http://make.wordpress.org/core/2014/04/11/plupload-2-x-in-wordpress-3-9/
204 # max_file_size is also in filters as of plupload 2.x, but in its default position is still supported for backwards-compatibility. Likewise, our use of filters.extensions below is supported by a backwards-compatibility option (the current way is filters.mime-types.extensions
205
206 $plupload_init = array(
207 'runtimes' => 'html5,flash,silverlight,html4',
208 'browse_button' => 'plupload-browse-button',
209 'container' => 'plupload-upload-ui',
210 'drop_element' => 'drag-drop-area',
211 'file_data_name' => 'async-upload',
212 'multiple_queues' => true,
213 'max_file_size' => '100Gb',
214 'chunk_size' => $chunk_size.'b',
215 'url' => admin_url('admin-ajax.php'),
216 'filters' => array(array('title' => __('Allowed Files'), 'extensions' => 'zip,tar,gz,bz2,crypt,sql,txt')),
217 'multipart' => true,
218 'multi_selection' => true,
219 'urlstream_upload' => true,
220 // additional post data to send to our ajax hook
221 'multipart_params' => array(
222 '_ajax_nonce' => wp_create_nonce('updraft-uploader'),
223 'action' => 'plupload_action'
224 )
225 );
226 // 'flash_swf_url' => includes_url('js/plupload/plupload.flash.swf'),
227 // 'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'),
228
229 # WP 3.9 updated to plupload 2.0 - https://core.trac.wordpress.org/ticket/25663
230 if (is_file(ABSPATH.'wp-includes/js/plupload/Moxie.swf')) {
231 $plupload_init['flash_swf_url'] = includes_url('js/plupload/Moxie.swf');
232 } else {
233 $plupload_init['flash_swf_url'] = includes_url('js/plupload/plupload.flash.swf');
234 }
235
236 if (is_file(ABSPATH.'wp-includes/js/plupload/Moxie.xap')) {
237 $plupload_init['silverlight_xap_url'] = includes_url('js/plupload/Moxie.xap');
238 } else {
239 $plupload_init['silverlight_xap_url'] = includes_url('js/plupload/plupload.silverlight.swf');
240 }
241
242 ?><script type="text/javascript">
243 var updraft_plupload_config=<?php echo json_encode($plupload_init); ?>;
244 var updraft_credentialtest_nonce='<?php echo wp_create_nonce('updraftplus-credentialtest-nonce');?>';
245 var updraft_download_nonce='<?php echo wp_create_nonce('updraftplus_download');?>';
246 var updraft_siteurl = '<?php echo esc_js(site_url());?>';
247 var updraft_accept_archivename = <?php echo apply_filters('updraftplus_accept_archivename_js', "[]");?>;
248 <?php
249 $plupload_init['browse_button'] = 'plupload-browse-button2';
250 $plupload_init['container'] = 'plupload-upload-ui2';
251 $plupload_init['drop_element'] = 'drag-drop-area2';
252 $plupload_init['multipart_params']['action'] = 'plupload_action2';
253 $plupload_init['filters'] = array(array('title' => __('Allowed Files'), 'extensions' => 'crypt'));
254 ?>
255 var updraft_plupload_config2=<?php echo json_encode($plupload_init); ?>;
256 var updraft_downloader_nonce = '<?php wp_create_nonce("updraftplus_download"); ?>'
257 <?php
258 $overdue = $this->howmany_overdue_crons();
259 if ($overdue >= 4) { ?>
260 jQuery(document).ready(function(){
261 setTimeout(function(){updraft_check_overduecrons();}, 11000);
262 function updraft_check_overduecrons() {
263 jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'checkoverduecrons', nonce: updraft_credentialtest_nonce }, function(data, response) {
264 if ('success' == response) {
265 try {
266 resp = jQuery.parseJSON(data);
267 if (resp.m) {
268 jQuery('#updraft-insert-admin-warning').html(resp.m);
269 }
270 } catch(err) {
271 console.log(data);
272 }
273 }
274 });
275 }
276 });
277 <?php } ?>
278 </script>
279 <style type="text/css">
280 .updraft-bigbutton {
281 padding: 2px 0px;
282 margin-right: 14px !important;
283 font-size:22px !important;
284 min-height: 32px;
285 min-width: 180px;
286 }
287 .updraft_debugrow th {
288 text-align: right;
289 font-weight: bold;
290 padding-right: 8px;
291 min-width: 140px;
292 }
293 .updraft_debugrow td {
294 min-width: 300px;
295 }
296 .updraftplus-morefiles-row-delete {
297 cursor: pointer;
298 color: red;
299 font-size: 100%;
300 font-weight: bold;
301 border: 0px;
302 border-radius: 3px;
303 padding: 2px;
304 margin: 0 6px;
305 }
306 .updraftplus-morefiles-row-delete:hover {
307 cursor: pointer;
308 color: white;
309 background: red;
310 }
311
312 #updraft-wrap .form-table th {
313 width: 230px;
314 }
315 .updraftplus-remove a {
316 color: red;
317 }
318 .updraftplus-remove:hover {
319 background-color: red;
320 }
321 .updraftplus-remove a:hover {
322 color: #fff;
323 }
324 .drag-drop #drag-drop-area2 {
325 border: 4px dashed #ddd;
326 height: 200px;
327 }
328 #drag-drop-area2 .drag-drop-inside {
329 margin: 36px auto 0;
330 width: 350px;
331 }
332 #filelist, #filelist2 {
333 width: 100%;
334 }
335 #filelist .file, #filelist2 .file, #ud_downloadstatus .file, #ud_downloadstatus2 .file {
336 padding: 5px;
337 background: #ececec;
338 border: solid 1px #ccc;
339 margin: 4px 0;
340 }
341 #filelist .fileprogress, #filelist2 .fileprogress, #ud_downloadstatus .dlfileprogress, #ud_downloadstatus2 .dlfileprogress {
342 width: 0%;
343 background: #f6a828;
344 height: 5px;
345 }
346 #ud_downloadstatus .raw, #ud_downloadstatus2 .raw {
347 margin-top: 8px;
348 clear:left;
349 }
350 #ud_downloadstatus .file, #ud_downloadstatus2 .file {
351 margin-top: 8px;
352 }
353 </style>
354 <?php
355
356 }
357
358 private function disk_space_check($space) {
359 global $updraftplus;
360 $updraft_dir = $updraftplus->backups_dir_location();
361 $disk_free_space = @disk_free_space($updraft_dir);
362 if ($disk_free_space == false) return -1;
363 return ($disk_free_space > $space) ? true : false;
364 }
365
366 # Adds the settings link under the plugin on the plugin screen.
367 public function plugin_action_links($links, $file) {
368 if ($file == 'updraftplus/updraftplus.php'){
369 $settings_link = '<a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__("Settings", "updraftplus").'</a>';
370 array_unshift($links, $settings_link);
371 // $settings_link = '<a href="http://david.dw-perspective.org.uk/donate">'.__("Donate","UpdraftPlus").'</a>';
372 // array_unshift($links, $settings_link);
373 $settings_link = '<a href="http://updraftplus.com">'.__("Add-Ons / Pro Support","updraftplus").'</a>';
374 array_unshift($links, $settings_link);
375 }
376 return $links;
377 }
378
379 public function admin_action_upgrade_pluginortheme() {
380
381 if (isset($_GET['action']) && ($_GET['action'] == 'upgrade-plugin' || $_GET['action'] == 'upgrade-theme') && !class_exists('UpdraftPlus_Addon_Autobackup') && !defined('UPDRAFTPLUS_NOADS_A')) {
382
383 # TODO: Remove legacy/erroneous use of transient any time after 1 Jun 2014
384 $dismissed = get_transient('updraftplus_dismissedautobackup');
385 if (true == $dismissed) return;
386 $dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismissedautobackup', 0);
387 if ($dismissed_until > time()) return;
388
389 if ( 'upgrade-plugin' == $_GET['action'] ) {
390 $title = __('Update Plugin');
391 $parent_file = 'plugins.php';
392 $submenu_file = 'plugins.php';
393 } else {
394 $title = __('Update Theme');
395 $parent_file = 'themes.php';
396 $submenu_file = 'themes.php';
397 }
398
399 require_once(ABSPATH.'wp-admin/admin-header.php');
400
401 ?>
402 <div id="updraft-autobackup" class="updated" style="float:left; padding: 6px; margin:8px 0px;">
403 <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>
404 <h3 style="margin-top: 0px;"><?php _e('Be safe with an automatic backup','updraftplus');?></h3>
405 <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>
406 </div>
407 <?php
408 }
409 }
410
411 public function show_admin_warning($message, $class = "updated") {
412 echo '<div class="updraftmessage '.$class.'">'."<p>$message</p></div>";
413 }
414
415 public function show_admin_nosettings_warning() {
416 $this->show_admin_warning('<strong>'.__('Welcome to UpdraftPlus!', 'updraftplus').'</strong> '.__('To make a backup, just press the Backup Now button.', 'updraftplus').' <a href="#" id="updraft-navtab-settings2">'.__('To change any of the default settings of what is backed up, to configure scheduled backups, to send your backups to remote storage (recommended), and more, go to the settings tab.', 'updraftplus').'</a>');
417 }
418
419 public function show_admin_warning_execution_time() {
420 $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));
421 }
422
423 public function show_admin_warning_disabledcron() {
424 $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>');
425 }
426
427 public function show_admin_warning_diskspace() {
428 $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'));
429 }
430
431 public function show_admin_warning_wordpressversion() {
432 $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('UpdraftPlus does not officially support versions of WordPress before %s. It may work for you, but if it does not, then please be aware that no support is available until you upgrade WordPress.', 'updraftplus'), '3.2'));
433 }
434
435 public function show_admin_warning_litespeed() {
436 $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>');
437 }
438
439 public function show_admin_debug_warning() {
440 $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>');
441 }
442
443 public function show_admin_warning_overdue_crons($howmany) {
444 $ret = '<div class="updraftmessage updated"><p>';
445 $ret .= '<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('WordPress has a number (%d) of scheduled tasks which are overdue. Unless this is a development site, this probably means that the scheduler in your WordPress install is not working.', 'updraftplus'), $howmany).' <a href="http://updraftplus.com/faqs/scheduler-wordpress-installation-working/">'.__('Read this page for a guide to possible causes and how to fix it.', 'updraftplus').'</a>';
446 $ret .= '</p></div>';
447 return $ret;
448 }
449
450 public function show_admin_warning_dropbox() {
451 $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>');
452 }
453
454 public function show_admin_warning_bitcasa() {
455 $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraftmethod-bitcasa-auth&updraftplus_bitcasaauth=doit">'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'),'Bitcasa','Bitcasa').'</a>');
456 }
457
458 public function show_admin_warning_googledrive() {
459 $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>');
460 }
461
462 // This options filter removes ABSPATH off the front of updraft_dir, if it is given absolutely and contained within it
463 public function prune_updraft_dir_prefix($updraft_dir) {
464 if ('/' == substr($updraft_dir, 0, 1) || "\\" == substr($updraft_dir, 0, 1) || preg_match('/^[a-zA-Z]:/', $updraft_dir)) {
465 $wcd = trailingslashit(WP_CONTENT_DIR);
466 if (strpos($updraft_dir, $wcd) === 0) {
467 $updraft_dir = substr($updraft_dir, strlen($wcd));
468 }
469 # Legacy
470 // if (strpos($updraft_dir, ABSPATH) === 0) {
471 // $updraft_dir = substr($updraft_dir, strlen(ABSPATH));
472 // }
473 }
474 return $updraft_dir;
475 }
476
477 public function updraft_download_backup() {
478
479 @set_time_limit(900);
480
481 global $updraftplus;
482
483 if (!isset($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'], 'updraftplus_download')) die;
484 if (!isset($_REQUEST['timestamp']) || !is_numeric($_REQUEST['timestamp']) || !isset($_REQUEST['type'])) exit;
485
486 $findex = (isset($_REQUEST['findex'])) ? $_REQUEST['findex'] : 0;
487 if (empty($findex)) $findex=0;
488
489 $backupable_entities = $updraftplus->get_backupable_file_entities(true);
490 $type_match = false;
491 foreach ($backupable_entities as $type => $info) {
492 if ($_REQUEST['type'] == $type) $type_match = true;
493 }
494
495 if (!$type_match && 'db' != substr($_REQUEST['type'], 0, 2)) exit;
496
497 // Get the information on what is wanted
498 $type = $_REQUEST['type'];
499 $timestamp = $_REQUEST['timestamp'];
500
501 // You need a nonce before you can set job data. And we certainly don't yet have one.
502 $updraftplus->backup_time_nonce($timestamp);
503
504 $debug_mode = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
505
506 // Set the job type before logging, as there can be different logging destinations
507 $updraftplus->jobdata_set('job_type', 'download');
508 $updraftplus->jobdata_set('job_time_ms', $updraftplus->job_time_ms);
509
510 // Retrieve the information from our backup history
511 $backup_history = $updraftplus->get_backup_history();
512 // Base name
513 $file = $backup_history[$timestamp][$type];
514
515 // Deal with multi-archive sets
516 if (is_array($file)) $file=$file[$findex];
517
518 // Where it should end up being downloaded to
519 $fullpath = $updraftplus->backups_dir_location().'/'.$file;
520
521 if (isset($_GET['stage']) && '2' == $_GET['stage']) {
522 $updraftplus->spool_file($type, $fullpath);
523 die;
524 }
525
526 if (isset($_POST['stage']) && 'delete' == $_POST['stage']) {
527 @unlink($fullpath);
528 echo 'deleted';
529 $updraftplus->log('The file has been deleted');
530 die;
531 }
532
533 // TODO: FIXME: Failed downloads may leave log files forever (though they are small)
534 // Note that log() assumes that the data is in _POST, not _GET
535 if ($debug_mode) $updraftplus->logfile_open($updraftplus->nonce);
536
537 set_error_handler(array($updraftplus, 'php_error'), E_ALL & ~E_STRICT);
538
539 $updraftplus->log("Requested to obtain file: timestamp=$timestamp, type=$type, index=$findex");
540
541 $itext = (empty($findex)) ? '' : $findex;
542 $known_size = isset($backup_history[$timestamp][$type.$itext.'-size']) ? $backup_history[$timestamp][$type.$itext.'-size'] : 0;
543
544 $services = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
545 if (is_string($services)) $services = array($services);
546
547 $updraftplus->jobdata_set('service', $services);
548
549 // Fetch it from the cloud, if we have not already got it
550
551 $needs_downloading = false;
552
553 if(!file_exists($fullpath)) {
554 //if the file doesn't exist and they're using one of the cloud options, fetch it down from the cloud.
555 $needs_downloading = true;
556 $updraftplus->log('File does not yet exist locally - needs downloading');
557 } elseif ($known_size>0 && filesize($fullpath) < $known_size) {
558 $updraftplus->log("The file was found locally (".filesize($fullpath).") but did not match the size in the backup history ($known_size) - will resume downloading");
559 $needs_downloading = true;
560 } elseif ($known_size>0) {
561 $updraftplus->log('The file was found locally and matched the recorded size from the backup history ('.round($known_size/1024,1).' Kb)');
562 } else {
563 $updraftplus->log('No file size was found recorded in the backup history. We will assume the local one is complete.');
564 $known_size = filesize($fullpath);
565 }
566
567 // The AJAX responder that updates on progress wants to see this
568 $updraftplus->jobdata_set('dlfile_'.$timestamp.'_'.$type.'_'.$findex, "downloading:$known_size:$fullpath");
569
570 if ($needs_downloading) {
571 $this->close_browser_connection();
572 $is_downloaded = false;
573 foreach ($services as $service) {
574 if ($is_downloaded) continue;
575 $download = $this->download_file($file, $service);
576 if (is_readable($fullpath) && $download !== false) {
577 clearstatcache();
578 $updraftplus->log('Remote fetch was successful (file size: '.round(filesize($fullpath)/1024,1).' Kb)');
579 $is_downloaded = true;
580 } else {
581 clearstatcache();
582 if (0 === @filesize($fullpath)) @unlink($fullpath);
583 $updraftplus->log('Remote fetch failed');
584 }
585 }
586 }
587
588 // Now, spool the thing to the browser
589 if(is_file($fullpath) && is_readable($fullpath)) {
590
591 // That message is then picked up by the AJAX listener
592 $updraftplus->jobdata_set('dlfile_'.$timestamp.'_'.$type.'_'.$findex, 'downloaded:'.filesize($fullpath).":$fullpath");
593
594 } else {
595 $updraftplus->jobdata_set('dlfile_'.$timestamp.'_'.$type.'_'.$findex, 'failed');
596 $updraftplus->jobdata_set('dlerrors_'.$timestamp.'_'.$type.'_'.$findex, $updraftplus->errors);
597 $updraftplus->log('Remote fetch failed. File '.$fullpath.' did not exist or was unreadable. If you delete local backups then remote retrieval may have failed.');
598 }
599
600 restore_error_handler();
601
602 @fclose($updraftplus->logfile_handle);
603 if (!$debug_mode) @unlink($updraftplus->logfile_name);
604
605 exit;
606
607 }
608
609 private function close_browser_connection($txt = '') {
610 // Close browser connection so that it can resume AJAX polling
611 header('Content-Length: '.((!empty($txt)) ? 4+strlen($txt) : '0'));
612 header('Connection: close');
613 header('Content-Encoding: none');
614 if (session_id()) session_write_close();
615 echo "\r\n\r\n";
616 echo $txt;
617 }
618
619 # Pass only a single service, as a string, into this function
620 private function download_file($file, $service) {
621
622 global $updraftplus;
623
624 @set_time_limit(900);
625
626 $updraftplus->log("Requested file from remote service: $service: $file");
627
628 $method_include = UPDRAFTPLUS_DIR.'/methods/'.$service.'.php';
629 if (file_exists($method_include)) require_once($method_include);
630
631 $objname = "UpdraftPlus_BackupModule_${service}";
632 if (method_exists($objname, "download")) {
633 $remote_obj = new $objname;
634 return $remote_obj->download($file);
635 } else {
636 $updraftplus->log("Automatic backup restoration is not available with the method: $service.");
637 $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');
638 return false;
639 }
640
641 }
642
643 // Called via AJAX
644 public function updraft_ajax_handler() {
645
646 global $updraftplus;
647
648 // Test the nonce
649 $nonce = (empty($_REQUEST['nonce'])) ? "" : $_REQUEST['nonce'];
650 if (!wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce') || empty($_REQUEST['subaction'])) die('Security check');
651 if (isset($_REQUEST['subaction']) && 'lastlog' == $_REQUEST['subaction']) {
652 echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', '('.__('Nothing yet logged', 'updraftplus').')'));
653 } elseif (isset($_GET['subaction']) && 'activejobs_list' == $_GET['subaction']) {
654 $download_status = array();
655 if (!empty($_GET['downloaders'])) {
656 foreach(explode(':', $_GET['downloaders']) as $downloader) {
657 # prefix, timestamp, entity, index
658 if (preg_match('/^([^,]+),(\d+),([-a-z]+|db[0-9]+),(\d+)$/', $downloader, $matches)) {
659 $updraftplus->nonce = $matches[2];
660 $status = $this->download_status($matches[2], $matches[3], $matches[4]);
661 if (is_array($status)) {
662 $status['base'] = $matches[1];
663 $status['timestamp'] = $matches[2];
664 $status['what'] = $matches[3];
665 $status['findex'] = (empty($matches[4])) ? '0' : $matches[4];
666 $download_status[] = $status;
667 }
668 }
669 }
670 }
671 if (!empty($_GET['oneshot'])) {
672 $job_id = get_site_option('updraft_oneshotnonce', false);
673 $active_jobs = (false === $job_id) ? '' : $this->print_active_job($job_id, true);
674 } else {
675 $active_jobs = $this->print_active_jobs();
676 }
677 echo json_encode(array(
678 'l' => htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', '('.__('Nothing yet logged', 'updraftplus').')')),
679 'j' => $active_jobs,
680 'ds' => $download_status
681 ));
682 } elseif (isset($_REQUEST['subaction']) && 'callwpaction' == $_REQUEST['subaction'] && !empty($_REQUEST['wpaction'])) {
683 ob_start();
684
685 $res = '<em>Request received: </em>';
686
687 if (preg_match('/^([^:]+)+:(.*)$/', stripslashes($_REQUEST['wpaction']), $matches)) {
688 $action = $matches[1];
689 if (null === ($args = json_decode($matches[2], true))) {
690 $res .= "The parameters (should be JSON) could not be decoded";
691 $action = false;
692 } else {
693 $res .= "Will despatch action: ".htmlspecialchars($action).", parameters: ".htmlspecialchars(implode(',', $args));
694 }
695 } else {
696 $action = $_REQUEST['wpaction'];
697 $res .= "Will despatch action: ".htmlspecialchars($action).", no parameters";
698 }
699
700 echo json_encode(array('r' => $res));
701 $ret = ob_get_clean();
702 ob_end_clean();
703 $this->close_browser_connection($ret);
704 if (!empty($action)) {
705 if (!empty($args)) {
706 do_action_ref_array($action, $args);
707 } else {
708 do_action($action);
709 }
710 }
711 die;
712 } elseif (isset($_REQUEST['subaction']) && 'httpget' == $_REQUEST['subaction']) {
713 if (empty($_REQUEST['uri'])) {
714 echo json_encode(array('r' => ''));
715 die;
716 }
717 $uri = $_REQUEST['uri'];
718 if (!empty($_REQUEST['curl'])) {
719 if (!function_exists('curl_exec')) {
720 echo json_encode(array('e' => 'No Curl installed'));
721 die;
722 }
723 $ch = curl_init();
724 curl_setopt($ch, CURLOPT_URL, $uri);
725 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
726 curl_setopt($ch, CURLOPT_FAILONERROR, true);
727 $output = curl_exec($ch);
728 $response = curl_exec($ch);
729 $error = curl_error($ch);
730 $getinfo = curl_getinfo($ch);
731 curl_close($ch);
732 if (false === $response) {
733 echo json_encode(array('e' => htmlspecialchars($error)));
734 die;
735 }
736 echo json_encode(array('r' => $getinfo['http_code'].': '.htmlspecialchars(substr($response, 0, 200))));
737 } else {
738 $response = wp_remote_get($uri, array('timeout' => 10));
739 if (is_wp_error($response)) {
740 echo json_encode(array('e' => htmlspecialchars($response->get_error_message())));
741 die;
742 }
743 echo json_encode(array('r' => $response['response']['code'].': '.htmlspecialchars(substr($response['body'], 0, 200))));
744 }
745 die;
746 } elseif (isset($_REQUEST['subaction']) && 'dismissautobackup' == $_REQUEST['subaction']) {
747 UpdraftPlus_Options::update_updraft_option('updraftplus_dismissedautobackup', time() + 84*86400);
748 } elseif (isset($_REQUEST['subaction']) && 'dismissexpiry' == $_REQUEST['subaction']) {
749 UpdraftPlus_Options::update_updraft_option('updraftplus_dismissedexpiry', time() + 14*86400);
750 } elseif (isset($_GET['subaction']) && 'restore_alldownloaded' == $_GET['subaction'] && isset($_GET['restoreopts']) && isset($_GET['timestamp'])) {
751
752 $backups = $updraftplus->get_backup_history();
753 $updraft_dir = $updraftplus->backups_dir_location();
754
755 $timestamp = (int)$_GET['timestamp'];
756 if (!isset($backups[$timestamp])) {
757 echo json_encode(array('m' => '', 'w' => '', 'e' => __('No such backup set exists', 'updraftplus')));
758 die;
759 }
760
761 $mess = array();
762 parse_str($_GET['restoreopts'], $res);
763
764 if (isset($res['updraft_restore'])) {
765
766 set_error_handler(array($this, 'get_php_errors'), E_ALL & ~E_STRICT);
767
768 $elements = array_flip($res['updraft_restore']);
769
770 $warn = array(); $err = array();
771
772 @set_time_limit(900);
773 $max_execution_time = (int)@ini_get('max_execution_time');
774
775 if ($max_execution_time>0 && $max_execution_time<61) {
776 $warn[] = sprintf(__('The PHP setup on this webserver allows only %s seconds for PHP to run, and does not allow this limit to be raised. If you have a lot of data to import, and if the restore operation times out, then you will need to ask your web hosting company for ways to raise this limit (or attempt the restoration piece-by-piece).', 'updraftplus'), $max_execution_time);
777 }
778
779 if (isset($backups[$timestamp]['native']) && false == $backups[$timestamp]['native']) {
780 $warn[] = __('This backup set was not known by UpdraftPlus to be created by the current WordPress installation, but was found in remote storage.', 'updraftplus').' '.__('You should make sure that this really is a backup set intended for use on this website, before you restore (rather than a backup set of an unrelated website that was using the same storage location).', 'updraftplus');
781 }
782
783 if (isset($elements['db'])) {
784 // Analyse the header of the database file + display results
785 list ($mess2, $warn2, $err2) = $this->analyse_db_file($timestamp, $res);
786 $mess = array_merge($mess, $mess2);
787 $warn = array_merge($warn, $warn2);
788 $err = array_merge($err, $err2);
789 foreach ($backups[$timestamp] as $bid => $bval) {
790 if ('db' != $bid && 'db' == substr($bid, 0, 2) && '-size' != substr($bid, -5, 5)) {
791 $warn[] = __('Only the WordPress database can be restored; you will need to deal with the external database manually.', 'updraftplus');
792 break;
793 }
794 }
795 }
796
797 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
798 $backupable_plus_db = $backupable_entities; $backupable_plus_db['db'] = array('path' => 'path-unused', 'description' => __('Database', 'updraftplus'));
799
800 if (!empty($backups[$timestamp]['meta_foreign'])) {
801 $foreign_known = apply_filters('updraftplus_accept_archivename', array());
802 if (!is_array($foreign_known) || empty($foreign_known[$backups[$timestamp]['meta_foreign']])) {
803 $err[] = sprintf(__('Backup created by unknown source (%s) - cannot be restored.', 'updraftplus'), $backups[$timestamp]['meta_foreign']);
804 } else {
805 $backupable_plus_db = apply_filters_ref_array("updraftplus_importforeign_backupable_plus_db", array($backupable_plus_db, $foreign_known[$backups[$timestamp]['meta_foreign']], &$mess, &$warn, &$err));
806 }
807 }
808
809 foreach ($backupable_plus_db as $type => $info) {
810 if (!isset($elements[$type])) continue;
811 $whatwegot = $backups[$timestamp][$type];
812 if (is_string($whatwegot)) $whatwegot = array($whatwegot);
813 $expected_index = 0;
814 $missing = '';
815 ksort($whatwegot);
816 $outof = false;
817 foreach ($whatwegot as $index => $file) {
818 if (preg_match('/\d+of(\d+)\.zip/', $file, $omatch)) { $outof = max($matches[1], 1); }
819 if ($index != $expected_index) {
820 $missing .= ($missing == '') ? (1+$expected_index) : ",".(1+$expected_index);
821 }
822 if (!file_exists($updraft_dir.'/'.$file)) {
823 $err[] = sprintf(__('File not found (you need to upload it): %s', 'updraftplus'), $updraft_dir.'/'.$file);
824 } elseif (filesize($updraft_dir.'/'.$file) == 0) {
825 $err[] = sprintf(__('File was found, but is zero-sized (you need to re-upload it): %s', 'updraftplus'), $file);
826 } else {
827 $itext = (0 == $index) ? '' : $index;
828 if (!empty($backups[$timestamp][$type.$itext.'-size']) && $backups[$timestamp][$type.$itext.'-size'] != filesize($updraft_dir.'/'.$file)) {
829 if (empty($warn['doublecompressfixed'])) {
830 $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']);
831 }
832 }
833 do_action_ref_array("updraftplus_checkzip_$type", array($updraft_dir.'/'.$file, &$mess, &$warn, &$err));
834 }
835 $expected_index++;
836 }
837 do_action_ref_array("updraftplus_checkzip_end_$type", array(&$mess, &$warn, &$err));
838 # Detect missing archives where they are missing from the end of the set
839 if ($outof>0 && $expected_index < $outof) {
840 for ($j = $expected_index; $j<$outof; $j++) {
841 $missing .= ($missing == '') ? (1+$j) : ",".(1+$j);
842 }
843 }
844 if ('' != $missing) {
845 $warn[] = sprintf(__("This multi-archive backup set appears to have the following archives missing: %s", 'updraftplus'), $missing.' ('.$info['description'].')');
846 }
847 }
848
849 if (0 == count($err) && 0 == count($warn)) {
850 $mess_first = __('The backup archive files have been successfully processed. Now press Restore again to proceed.', 'updraftplus');
851 } elseif (0 == count($err)) {
852 $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');
853 } else {
854 $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');
855 }
856
857 if (count($this->logged) >0) {
858 foreach ($this->logged as $lwarn) $warn[] = $lwarn;
859 }
860 restore_error_handler();
861
862 echo json_encode(array('m' => '<p>'.$mess_first.'</p>'.implode('<br>', $mess), 'w' => implode('<br>', $warn), 'e' => implode('<br>', $err)));
863 }
864
865 } elseif (isset($_POST['backup_timestamp']) && 'deleteset' == $_REQUEST['subaction']) {
866 $backups = $updraftplus->get_backup_history();
867 $timestamp = $_POST['backup_timestamp'];
868 if (!isset($backups[$timestamp])) {
869 echo json_encode(array('result' => 'error', 'message' => __('Backup set not found', 'updraftplus')));
870 die;
871 }
872
873 // You need a nonce before you can set job data. And we certainly don't yet have one.
874 $updraftplus->backup_time_nonce();
875 // Set the job type before logging, as there can be different logging destinations
876 $updraftplus->jobdata_set('job_type', 'delete');
877 $updraftplus->jobdata_set('job_time_ms', $updraftplus->job_time_ms);
878
879 if (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
880 $updraftplus->logfile_open($updraftplus->nonce);
881 set_error_handler(array($updraftplus, 'php_error'), E_ALL & ~E_STRICT);
882 }
883
884 $updraft_dir = $updraftplus->backups_dir_location();
885 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
886
887 $nonce = isset($backups[$timestamp]['nonce']) ? $backups[$timestamp]['nonce'] : '';
888
889 $delete_from_service = array();
890
891 if (isset($_POST['delete_remote']) && 1==$_POST['delete_remote']) {
892 // Locate backup set
893 if (isset($backups[$timestamp]['service'])) {
894 $services = is_string($backups[$timestamp]['service']) ? array($backups[$timestamp]['service']) : $backups[$timestamp]['service'];
895 if (is_array($services)) {
896 foreach ($services as $service) {
897 if ($service != 'none') $delete_from_service[] = $service;
898 }
899 }
900 }
901 }
902
903 $files_to_delete = array();
904 foreach ($backupable_entities as $key => $ent) {
905 if (isset($backups[$timestamp][$key])) {
906 $files_to_delete[$key] = $backups[$timestamp][$key];
907 }
908 }
909 // Delete DB
910 if (isset($backups[$timestamp]['db'])) $files_to_delete['db'] = $backups[$timestamp]['db'];
911
912 // Also delete the log
913 if ($nonce && !UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
914 $files_to_delete['log'] = "log.$nonce.txt";
915 }
916
917 unset($backups[$timestamp]);
918 UpdraftPlus_Options::update_updraft_option('updraft_backup_history', $backups);
919
920 $message = '';
921
922 $local_deleted = 0;
923 $remote_deleted = 0;
924 foreach ($files_to_delete as $key => $files) {
925 # Local deletion
926 if (is_string($files)) $files=array($files);
927 foreach ($files as $file) {
928 if (is_file($updraft_dir.'/'.$file)) {
929 if (@unlink($updraft_dir.'/'.$file)) $local_deleted++;
930 }
931 }
932 if ('log' != $key && count($delete_from_service) > 0) {
933 foreach ($delete_from_service as $service) {
934 if ('email' == $service) continue;
935 if (file_exists(UPDRAFTPLUS_DIR."/methods/$service.php")) require_once(UPDRAFTPLUS_DIR."/methods/$service.php");
936 $objname = "UpdraftPlus_BackupModule_".$service;
937 $deleted = -1;
938 if (class_exists($objname)) {
939 # TODO: Re-use the object (i.e. prevent repeated connection setup/teardown)
940 $remote_obj = new $objname;
941 $deleted = $remote_obj->delete($files);
942 }
943 if ($deleted === -1) {
944 //echo __('Did not know how to delete from this cloud service.', 'updraftplus');
945 } elseif ($deleted !== false) {
946 $remote_deleted = $remote_deleted + count($files);
947 } else {
948 // Do nothing
949 }
950 }
951 }
952 }
953 $message .= __('The backup set has been removed.', 'updraftplus')."\n";
954 $message .= sprintf(__('Local archives deleted: %d', 'updraftplus'),$local_deleted)."\n";
955 $message .= sprintf(__('Remote archives deleted: %d', 'updraftplus'),$remote_deleted)."\n";
956
957 $updraftplus->log("Local archives deleted: ".$local_deleted);
958 $updraftplus->log("Remote archives deleted: ".$remote_deleted);
959
960 print json_encode(array('result' => 'success', 'message' => $message));
961
962 if (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
963 restore_error_handler();
964 }
965
966
967 } elseif ('rawbackuphistory' == $_REQUEST['subaction']) {
968
969 echo '<h3 id="ud-debuginfo-rawbackups">'.__('Known backups (raw)', 'updraftplus').'</h3><pre>';
970 var_dump($updraftplus->get_backup_history());
971 echo '</pre>';
972
973 echo '<h3 id="ud-debuginfo-files">Files</h3><pre>';
974 $updraft_dir = $updraftplus->backups_dir_location();
975 $raw_output = array();
976 $d = dir($updraft_dir);
977 while (false !== ($entry = $d->read())) {
978 $fp = $updraft_dir.'/'.$entry;
979 $mtime = filemtime($fp);
980 if (is_dir($fp)) {
981 $size = ' d';
982 } elseif (is_link($fp)) {
983 $size = ' l';
984 } elseif (is_file($fp)) {
985 $size = sprintf("%8.1f", round(filesize($fp)/1024, 1)).' '.gmdate('r', $mtime);
986 } else {
987 $size = ' ?';
988 }
989 if (preg_match('/^log\.(.*)\.txt$/', $entry, $lmatch)) $entry = '<a target="_top" href="?action=downloadlog&page=updraftplus&updraftplus_backup_nonce='.htmlspecialchars($lmatch[1]).'">'.$entry.'</a>';
990 $raw_output[$mtime] = empty($raw_output[$mtime]) ? sprintf("%s %s\n", $size, $entry) : $raw_output[$mtime].sprintf("%s %s\n", $size, $entry);
991 }
992 @$d->close();
993 krsort($raw_output, SORT_NUMERIC);
994 foreach ($raw_output as $line) echo $line;
995 echo '</pre>';
996
997 echo '<h3 id="ud-debuginfo-options">'.__('Options (raw)', 'updraftplus').'</h3>';
998 $opts = $this->get_settings_keys();
999 asort($opts);
1000 // <tr><th>'.__('Key','updraftplus').'</th><th>'.__('Value','updraftplus').'</th></tr>
1001 echo '<table><thead></thead><tbody>';
1002 foreach ($opts as $opt) {
1003 echo '<tr><td>'.htmlspecialchars($opt).'</td><td>'.htmlspecialchars(print_r(UpdraftPlus_Options::get_updraft_option($opt), true)).'</td>';
1004 }
1005 echo '</tbody></table>';
1006
1007 } elseif ('countbackups' == $_REQUEST['subaction']) {
1008 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1009 $backup_history = (is_array($backup_history))?$backup_history:array();
1010 echo sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history));
1011 } elseif ('ping' == $_REQUEST['subaction']) {
1012 // 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
1013 echo 'pong';
1014 } elseif ('checkoverduecrons' == $_REQUEST['subaction']) {
1015 $how_many_overdue = $this->howmany_overdue_crons();
1016 if ($how_many_overdue >= 4) echo json_encode(array('m' => $this->show_admin_warning_overdue_crons($how_many_overdue)));
1017 } elseif ('delete_old_dirs' == $_REQUEST['subaction']) {
1018 $this->delete_old_dirs_go(false);
1019 } elseif ('phpinfo' == $_REQUEST['subaction']) {
1020 phpinfo(INFO_ALL ^ (INFO_CREDITS | INFO_LICENSE));
1021
1022 echo '<h3 id="ud-debuginfo-constants">'.__('Constants', 'updraftplus').'</h3>';
1023 $opts = @get_defined_constants();
1024 ksort($opts);
1025 // <tr><th>'.__('Key','updraftplus').'</th><th>'.__('Value','updraftplus').'</th></tr>
1026 echo '<table><thead></thead><tbody>';
1027 foreach ($opts as $key => $opt) {
1028 echo '<tr><td>'.htmlspecialchars($key).'</td><td>'.htmlspecialchars(print_r($opt, true)).'</td>';
1029 }
1030 echo '</tbody></table>';
1031
1032 } elseif ('doaction' == $_REQUEST['subaction'] && !empty($_REQUEST['subsubaction']) && 'updraft_' == substr($_REQUEST['subsubaction'], 0, 8)) {
1033 do_action($_REQUEST['subsubaction']);
1034 } elseif ('backupnow' == $_REQUEST['subaction']) {
1035 echo '<strong>',__('Schedule backup','updraftplus').':</strong> ';
1036 $backupnow_nocloud = (empty($_REQUEST['backupnow_nocloud'])) ? false : true;
1037 $event = (!empty($_REQUEST['backupnow_nofiles'])) ? 'updraft_backupnow_backup_database' : ((!empty($_REQUEST['backupnow_nodb'])) ? 'updraft_backupnow_backup' : 'updraft_backupnow_backup_all');
1038
1039 $msg = htmlspecialchars(__('OK. You should soon see activity in the "Last log message" field below.','updraftplus'));
1040 $updraftplus->log("A backup run has been started");
1041 $this->close_browser_connection($msg);
1042 do_action($event, $backupnow_nocloud);
1043
1044 # Old-style: schedule an event in 5 seconds time. This has the advantage of testing out the scheduler, and alerting the user if it doesn't work... but has the disadvantage of not working in that case.
1045 # I don't think the </div>s should be here - in case this is ever re-activated
1046 // if (wp_schedule_single_event(time()+5, $event, array($backupnow_nocloud)) === false) {
1047 // $updraftplus->log("A backup run failed to schedule");
1048 // echo __("Failed.", 'updraftplus')."</div>";
1049 // } else {
1050 // 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>";
1051 // $updraftplus->log("A backup run has been scheduled");
1052 // }
1053
1054 } elseif (isset($_GET['subaction']) && 'lastbackup' == $_GET['subaction']) {
1055 echo $this->last_backup_html();
1056 } elseif (isset($_GET['subaction']) && 'activejobs_delete' == $_GET['subaction'] && isset($_GET['jobid'])) {
1057
1058 $cron = get_option('cron');
1059 $found_it = 0;
1060 foreach ($cron as $time => $job) {
1061 if (isset($job['updraft_backup_resume'])) {
1062 foreach ($job['updraft_backup_resume'] as $hook => $info) {
1063 if (isset($info['args'][1]) && $info['args'][1] == $_GET['jobid']) {
1064 $args = $cron[$time]['updraft_backup_resume'][$hook]['args'];
1065 wp_unschedule_event($time, 'updraft_backup_resume', $args);
1066 if (!$found_it) echo json_encode(array('ok' => 'Y', 'm' => __('Job deleted', 'updraftplus')));
1067 $found_it = 1;
1068 }
1069 }
1070 }
1071 }
1072
1073 if (!$found_it) echo json_encode(array('ok' => 'N', 'm' => __('Could not find that job - perhaps it has already finished?', 'updraftplus')));
1074
1075 } elseif (isset($_GET['subaction']) && 'diskspaceused' == $_GET['subaction'] && isset($_GET['entity'])) {
1076 if ('updraft' == $_GET['entity']) {
1077 echo $this->recursive_directory_size($updraftplus->backups_dir_location());
1078 } else {
1079 $backupable_entities = $updraftplus->get_backupable_file_entities(true, false);
1080 if (!empty($backupable_entities[$_GET['entity']])) {
1081 # Might be an array
1082 $basedir = $backupable_entities[$_GET['entity']];
1083 $dirs = apply_filters('updraftplus_dirlist_'.$_GET['entity'], $basedir);
1084 echo $this->recursive_directory_size($dirs, $updraftplus->get_exclude($_GET['entity']), $basedir);
1085 } else {
1086 _e('Error', 'updraftplus');
1087 }
1088 }
1089 } elseif (isset($_GET['subaction']) && 'historystatus' == $_GET['subaction']) {
1090 $remotescan = (isset($_GET['remotescan']) && $_GET['remotescan'] == 1);
1091 $rescan = ($remotescan || (isset($_GET['rescan']) && $_GET['rescan'] == 1));
1092 if ($rescan) $messages = $this->rebuild_backup_history($remotescan);
1093
1094 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1095 $backup_history = (is_array($backup_history)) ? $backup_history : array();
1096 $output = $this->existing_backup_table($backup_history);
1097
1098 if (!empty($messages) && is_array($messages)) {
1099 $noutput = '<div style="margin-left: 100px; margin-top: 10px;"><ul style="list-style: disc inside;">';
1100 foreach ($messages as $msg) {
1101 $noutput .= '<li>'.(($msg['desc']) ? $msg['desc'].': ' : '').'<em>'.$msg['message'].'</em></li>';
1102 }
1103 $noutput .= '</ul></div>';
1104 $output = $noutput.$output;
1105 }
1106
1107 echo json_encode(array('n' => sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history)), 't' => $output));
1108 } elseif (isset($_GET['subaction']) && 'downloadstatus' == $_GET['subaction'] && isset($_GET['timestamp']) && isset($_GET['type'])) {
1109
1110 $findex = (isset($_GET['findex'])) ? $_GET['findex'] : '0';
1111 if (empty($findex)) $findex = '0';
1112 $updraftplus->nonce = $_GET['timestamp'];
1113
1114 echo json_encode($this->download_status($_GET['timestamp'], $_GET['type'], $findex));
1115
1116 } elseif (isset($_POST['subaction']) && $_POST['subaction'] == 'credentials_test') {
1117 $method = (preg_match("/^[a-z0-9]+$/", $_POST['method'])) ? $_POST['method'] : "";
1118
1119 // Test the credentials, return a code
1120 require_once(UPDRAFTPLUS_DIR."/methods/$method.php");
1121 $objname = "UpdraftPlus_BackupModule_$method";
1122
1123 $this->logged = array();
1124 set_error_handler(array($this, 'get_php_errors'), E_ALL & ~E_STRICT);
1125 if (method_exists($objname, "credentials_test")) {
1126 $obj = new $objname;
1127 $obj->credentials_test();
1128 }
1129 if (count($this->logged) >0) {
1130 echo "\n\n".__('Messages:', 'updraftplus')."\n";
1131 foreach ($this->logged as $err) {
1132 echo "* $err\n";
1133 }
1134 }
1135 restore_error_handler();
1136 }
1137 die;
1138
1139 }
1140
1141 public function howmany_overdue_crons() {
1142 $how_many_overdue = 0;
1143 if (function_exists('_get_cron_array') || (is_file(ABSPATH.'wp-includes/cron.php') && include_once(ABSPATH.'wp-includes/cron.php') && function_exists('_get_cron_array'))) {
1144 $crons = _get_cron_array();
1145 if (is_array($crons)) {
1146 $timenow = time();
1147 foreach ($crons as $jt => $job) {
1148 if ($jt < $timenow) {
1149 $how_many_overdue++;
1150 }
1151 }
1152 }
1153 }
1154 return $how_many_overdue;
1155 }
1156
1157 public function get_php_errors($errno, $errstr, $errfile, $errline) {
1158 global $updraftplus;
1159 if (0 == error_reporting()) return true;
1160 $logline = $updraftplus->php_error_to_logline($errno, $errstr, $errfile, $errline);
1161 $this->logged[] = $logline;
1162 # Don't pass it up the chain (since it's going to be output to the user always)
1163 return true;
1164 }
1165
1166 function download_status($timestamp, $type, $findex) {
1167
1168 global $updraftplus;
1169
1170 $response = array( 'm' => $updraftplus->jobdata_get('dlmessage_'.$timestamp.'_'.$type.'_'.$findex).'<br>' );
1171
1172 if ($file = $updraftplus->jobdata_get('dlfile_'.$timestamp.'_'.$type.'_'.$findex)) {
1173 if ('failed' == $file) {
1174 $response['e'] = __('Download failed','updraftplus').'<br>';
1175 $errs = $updraftplus->jobdata_get('dlerrors_'.$timestamp.'_'.$type.'_'.$findex);
1176 if (is_array($errs) && !empty($errs)) {
1177 $response['e'] .= '<ul style="list-style: disc inside;">';
1178 foreach ($errs as $err) {
1179 if (is_array($err)) {
1180 $response['e'] .= '<li>'.htmlspecialchars($err['message']).'</li>';
1181 } else {
1182 $response['e'] .= '<li>'.htmlspecialchars($err).'</li>';
1183 }
1184 }
1185 $response['e'] .= '</ul>';
1186 }
1187 } elseif (preg_match('/^downloaded:(\d+):(.*)$/', $file, $matches) && file_exists($matches[2])) {
1188 $response['p'] = 100;
1189 $response['f'] = $matches[2];
1190 $response['s'] = (int)$matches[1];
1191 $response['t'] = (int)$matches[1];
1192 $response['m'] = __('File ready.', 'updraftplus');
1193 } elseif (preg_match('/^downloading:(\d+):(.*)$/', $file, $matches) && file_exists($matches[2])) {
1194 // Convert to bytes
1195 $response['f'] = $matches[2];
1196 $total_size = (int)max($matches[1], 1);
1197 $cur_size = filesize($matches[2]);
1198 $response['s'] = $cur_size;
1199 $response['t'] = $total_size;
1200 $response['m'] .= __("Download in progress", 'updraftplus').' ('.round($cur_size/1024).' / '.round(($total_size/1024)).' Kb)';
1201 $response['p'] = round(100*$cur_size/$total_size);
1202 } else {
1203 $response['m'] .= __('No local copy present.', 'updraftplus');
1204 $response['p'] = 0;
1205 $response['s'] = 0;
1206 $response['t'] = 1;
1207 }
1208 }
1209 return $response;
1210 }
1211
1212 private function analyse_db_file($timestamp, $res) {
1213
1214 $mess = array(); $warn = array(); $err = array();
1215
1216 global $updraftplus, $wp_version;
1217 include(ABSPATH.'wp-includes/version.php');
1218
1219 # 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.
1220 $updraftplus->get_max_packet_size();
1221
1222 $backup = $updraftplus->get_backup_history($timestamp);
1223 if (!isset($backup['nonce']) || !isset($backup['db'])) return array($mess, $warn, $err);
1224
1225 $updraft_dir = $updraftplus->backups_dir_location();
1226
1227 $db_file = (is_string($backup['db'])) ? $updraft_dir.'/'.$backup['db'] : $updraft_dir.'/'.$backup['db'][0];
1228
1229 if (!is_readable($db_file)) return array($mess, $warn, $err);
1230
1231 // Encrypted - decrypt it
1232 if ($updraftplus->is_db_encrypted($db_file)) {
1233
1234 $encryption = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
1235
1236 if (!$encryption) {
1237 if (class_exists('UpdraftPlus_Addon_MoreDatabase')) {
1238 $err[] = sprintf(__('Error: %s', 'updraftplus'), __('Decryption failed. The database file is encrypted, but you have no encryption key entered.', 'updraftplus'));
1239 } else {
1240 $err[] = sprintf(__('Error: %s', 'updraftplus'), __('Decryption failed. The database file is encrypted.', 'updraftplus'));
1241 }
1242 return array($mess, $warn, $err);
1243 }
1244
1245 $ciphertext = $updraftplus->decrypt($db_file, $encryption);
1246
1247 if ($ciphertext) {
1248 $new_db_file = $updraft_dir.'/'.basename($db_file, '.crypt');
1249 if (!file_put_contents($new_db_file, $ciphertext)) {
1250 $err[] = __('Failed to write out the decrypted database to the filesystem.','updraftplus');
1251 return array($mess, $warn, $err);
1252 }
1253 $db_file = $new_db_file;
1254 } else {
1255 $err[] = __('Decryption failed. The most likely cause is that you used the wrong key.','updraftplus');
1256 return array($mess, $warn, $err);
1257 }
1258 }
1259
1260 # 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.
1261 if (filesize($db_file) < 1000) {
1262 $err[] = sprintf(__('The database is too small to be a valid WordPress database (size: %s Kb).','updraftplus'), round(filesize($db_file)/1024, 1));
1263 return array($mess, $warn, $err);
1264 }
1265
1266 $is_plain = ('.gz' == substr($db_file, -3, 3)) ? false : true;
1267
1268 $dbhandle = ($is_plain) ? fopen($db_file, 'r') : $this->gzopen_for_read($db_file, $warn, $err);
1269 if (!is_resource($dbhandle)) {
1270 $err[] = __('Failed to open database file.','updraftplus');
1271 return array($mess, $warn, $err);
1272 }
1273
1274 # Analyse the file, print the results.
1275
1276 $line = 0;
1277 $old_siteurl = '';
1278 $old_home = '';
1279 $old_table_prefix = '';
1280 $old_siteinfo = array();
1281 $gathering_siteinfo = true;
1282 $old_wp_version = '';
1283
1284 $tables_found = array();
1285
1286 // 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
1287
1288 $wanted_tables = array('terms', 'term_taxonomy', 'term_relationships', 'commentmeta', 'comments', 'links', 'options', 'postmeta', 'posts', 'users', 'usermeta');
1289
1290 $migration_warning = false;
1291
1292 # Don't set too high - we want a timely response returned to the browser
1293 @set_time_limit(90);
1294
1295 while ((($is_plain && !feof($dbhandle)) || (!$is_plain && !gzeof($dbhandle))) && ($line<100 || count($wanted_tables)>0)) {
1296 $line++;
1297 // Up to 1Mb
1298 $buffer = ($is_plain) ? rtrim(fgets($dbhandle, 1048576)) : rtrim(gzgets($dbhandle, 1048576));
1299 // Comments are what we are interested in
1300 if (substr($buffer, 0, 1) == '#') {
1301 if ('' == $old_siteurl && preg_match('/^\# Backup of: (http(.*))$/', $buffer, $matches)) {
1302 $old_siteurl = untrailingslashit($matches[1]);
1303 $mess[] = __('Backup of:', 'updraftplus').' '.htmlspecialchars($old_siteurl).((!empty($old_wp_version)) ? ' '.sprintf(__('(version: %s)', 'updraftplus'), $old_wp_version) : '');
1304 // Check for should-be migration
1305 if (!$migration_warning && $old_siteurl != untrailingslashit(site_url())) {
1306 $migration_warning = true;
1307 $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);
1308 if (!empty($powarn)) $warn[] = $powarn;
1309 }
1310 } elseif ('' == $old_home && preg_match('/^\# Home URL: (http(.*))$/', $buffer, $matches)) {
1311 $old_home = untrailingslashit($matches[1]);
1312 // Check for should-be migration
1313 if (!$migration_warning && $old_home != home_url()) {
1314 $migration_warning = true;
1315 $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);
1316 if (!empty($powarn)) $warn[] = $powarn;
1317 }
1318 } elseif ('' == $old_wp_version && preg_match('/^\# WordPress Version: ([0-9]+(\.[0-9]+)+)(-[-a-z0-9]+,)?/', $buffer, $matches)) {
1319 $old_wp_version = $matches[1];
1320 if (!empty($matches[3])) $old_wp_version .= substr($matches[3], 0, strlen($matches[3])-1);
1321 if (version_compare($old_wp_version, $wp_version, '>')) {
1322 //$mess[] = sprintf(__('%s version: %s', 'updraftplus'), 'WordPress', $old_wp_version);
1323 $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);
1324 }
1325 } elseif ('' == $old_table_prefix && (preg_match('/^\# Table prefix: (\S+)$/', $buffer, $matches) || preg_match('/^-- Table prefix: (\S+)$/i', $buffer, $matches))) {
1326 $old_table_prefix = $matches[1];
1327 // echo '<strong>'.__('Old table prefix:', 'updraftplus').'</strong> '.htmlspecialchars($old_table_prefix).'<br>';
1328 } elseif ($gathering_siteinfo && preg_match('/^\# Site info: (\S+)$/', $buffer, $matches)) {
1329 if ('end' == $matches[1]) {
1330 $gathering_siteinfo = false;
1331 // Sanity checks
1332 if (isset($old_siteinfo['multisite']) && !$old_siteinfo['multisite'] && is_multisite()) {
1333 // Just need to check that you're crazy
1334 if (!defined('UPDRAFTPLUS_EXPERIMENTAL_IMPORTINTOMULTISITE') || UPDRAFTPLUS_EXPERIMENTAL_IMPORTINTOMULTISITE != true) {
1335 $err[] = sprintf(__('Error: %s', 'updraftplus'), __('You are running on WordPress multisite - but your backup is not of a multisite site.', 'updraftplus'));
1336 return array($mess, $warn, $err);
1337 }
1338 // Got the needed code?
1339 if (!class_exists('UpdraftPlusAddOn_MultiSite') || !class_exists('UpdraftPlus_Addons_Migrator')) {
1340 $err[] = sprintf(__('Error: %s', 'updraftplus'), __('To import an ordinary WordPress site into a multisite installation requires both the multisite and migrator add-ons.', 'updraftplus'));
1341 return array($mess, $warn, $err);
1342 }
1343 }
1344 } elseif (preg_match('/^([^=]+)=(.*)$/', $matches[1], $kvmatches)) {
1345 $key = $kvmatches[1];
1346 $val = $kvmatches[2];
1347 if ('multisite' == $key && $val) {
1348 $mess[] = '<strong>'.__('Site information:','updraftplus').'</strong>'.' is a WordPress Network';
1349 }
1350 $old_siteinfo[$key]=$val;
1351 }
1352 }
1353
1354 } elseif (preg_match('/^\s*create table \`?([^\`\(]*)\`?\s*\(/i', $buffer, $matches)) {
1355 $table = $matches[1];
1356 $tables_found[] = $table;
1357 if ($old_table_prefix) {
1358 // Remove prefix
1359 $table = $updraftplus->str_replace_once($old_table_prefix, '', $table);
1360 if (in_array($table, $wanted_tables)) {
1361 $wanted_tables = array_diff($wanted_tables, array($table));
1362 }
1363 }
1364 }
1365 }
1366
1367 if ($is_plain) {
1368 @fclose($dbhandle);
1369 } else {
1370 @gzclose($dbhandle);
1371 }
1372
1373 /* $blog_tables = "CREATE TABLE $wpdb->terms (
1374 CREATE TABLE $wpdb->term_taxonomy (
1375 CREATE TABLE $wpdb->term_relationships (
1376 CREATE TABLE $wpdb->commentmeta (
1377 CREATE TABLE $wpdb->comments (
1378 CREATE TABLE $wpdb->links (
1379 CREATE TABLE $wpdb->options (
1380 CREATE TABLE $wpdb->postmeta (
1381 CREATE TABLE $wpdb->posts (
1382 $users_single_table = "CREATE TABLE $wpdb->users (
1383 $users_multi_table = "CREATE TABLE $wpdb->users (
1384 $usermeta_table = "CREATE TABLE $wpdb->usermeta (
1385 $ms_global_tables = "CREATE TABLE $wpdb->blogs (
1386 CREATE TABLE $wpdb->blog_versions (
1387 CREATE TABLE $wpdb->registration_log (
1388 CREATE TABLE $wpdb->site (
1389 CREATE TABLE $wpdb->sitemeta (
1390 CREATE TABLE $wpdb->signups (
1391 */
1392
1393 $missing_tables = array();
1394 if ($old_table_prefix) {
1395 foreach ($wanted_tables as $table) {
1396 if (!in_array($old_table_prefix.$table, $tables_found)) {
1397 $missing_tables[] = $table;
1398 }
1399 }
1400 if (count($missing_tables)>0) {
1401 $warn[] = sprintf(__('This database backup is missing core WordPress tables: %s', 'updraftplus'), implode(', ', $missing_tables));
1402 }
1403 } else {
1404 if (empty($backup['meta_foreign'])) {
1405 $warn[] = __('UpdraftPlus was unable to find the table prefix when scanning the database backup.', 'updraftplus');
1406 }
1407 }
1408
1409 return array($mess, $warn, $err);
1410
1411 }
1412
1413 private function gzopen_for_read($file, &$warn, &$err) {
1414 if (!function_exists('gzopen') || !function_exists('gzread')) {
1415 $missing = '';
1416 if (!function_exists('gzopen')) $missing .= 'gzopen';
1417 if (!function_exists('gzread')) $missing .= ($missing) ? ', gzread' : 'gzread';
1418 $err[] = sprintf(__("Your web server's PHP installation has these functions disabled: %s.", 'updraftplus'), implode(', ', $missing)).' '.sprintf(__('Your hosting company must enable these functions before %s can work.', 'updraftplus'), __('restoration', 'updraftplus'));
1419 return false;
1420 }
1421 if (false === ($dbhandle = gzopen($file, 'r'))) return false;
1422 if (false === ($bytes = gzread($dbhandle, 3))) return false;
1423 # Double-gzipped?
1424 if ('H4sI' != base64_encode($bytes)) {
1425 if (0 === gzseek($dbhandle, 0)) {
1426 return $dbhandle;
1427 } else {
1428 @gzclose($dbhandle);
1429 return gzopen($file, 'r');
1430 }
1431 }
1432 # Yes, it's double-gzipped
1433
1434 $what_to_return = false;
1435 $mess = __('The database file appears to have been compressed twice - probably the website you downloaded it from had a mis-configured webserver.', 'updraftplus');
1436 $messkey = 'doublecompress';
1437 $err_msg = '';
1438
1439 if (false === ($fnew = fopen($file.".tmp", 'w')) || !is_resource($fnew)) {
1440
1441 @gzclose($dbhandle);
1442 $err_msg = __('The attempt to undo the double-compression failed.', 'updraftplus');
1443
1444 } else {
1445
1446 @fwrite($fnew, $bytes);
1447 $emptimes = 0;
1448 while (!gzeof($dbhandle)) {
1449 $bytes = @gzread($dbhandle, 131072);
1450 if (empty($bytes)) {
1451 global $updraftplus;
1452 $emptimes++;
1453 $updraftplus->log("Got empty gzread ($emptimes times)");
1454 if ($emptimes>2) break;
1455 } else {
1456 @fwrite($fnew, $bytes);
1457 }
1458 }
1459
1460 gzclose($dbhandle);
1461 fclose($fnew);
1462 # On some systems (all Windows?) you can't rename a gz file whilst it's gzopened
1463 if (!rename($file.".tmp", $file)) {
1464 $err_msg = __('The attempt to undo the double-compression failed.', 'updraftplus');
1465 } else {
1466 $mess .= ' '.__('The attempt to undo the double-compression succeeded.', 'updraftplus');
1467 $messkey = 'doublecompressfixed';
1468 $what_to_return = gzopen($file, 'r');
1469 }
1470
1471 }
1472
1473 $warn[$messkey] = $mess;
1474 if (!empty($err_msg)) $err[] = $err_msg;
1475 return $what_to_return;
1476 }
1477
1478 public function upload_dir($uploads) {
1479 global $updraftplus;
1480 $updraft_dir = $updraftplus->backups_dir_location();
1481 if (is_writable($updraft_dir)) $uploads['path'] = $updraft_dir;
1482 return $uploads;
1483 }
1484
1485 // We do actually want to over-write
1486 public function unique_filename_callback($dir, $name, $ext) {
1487 return $name.$ext;
1488 }
1489
1490 public function sanitize_file_name($filename) {
1491 // WordPress 3.4.2 on multisite (at least) adds in an unwanted underscore
1492 return preg_replace('/-db(.*)\.gz_\.crypt$/', '-db$1.gz.crypt', $filename);
1493 }
1494
1495 public function plupload_action() {
1496 // check ajax nonce
1497
1498 global $updraftplus;
1499 @set_time_limit(900);
1500
1501 check_ajax_referer('updraft-uploader');
1502
1503 $updraft_dir = $updraftplus->backups_dir_location();
1504 if (!is_writable($updraft_dir)) exit;
1505
1506 add_filter('upload_dir', array($this, 'upload_dir'));
1507 add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
1508 // handle file upload
1509
1510 $farray = array('test_form' => true, 'action' => 'plupload_action');
1511
1512 $farray['test_type'] = false;
1513 $farray['ext'] = 'x-gzip';
1514 $farray['type'] = 'application/octet-stream';
1515
1516 if (isset($_POST['chunks'])) {
1517
1518 } else {
1519 $farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
1520 }
1521
1522 $status = wp_handle_upload(
1523 $_FILES['async-upload'],
1524 $farray
1525 );
1526 remove_filter('upload_dir', array($this, 'upload_dir'));
1527 remove_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
1528
1529 if (isset($status['error'])) {
1530 echo json_encode(array('e' => $status['error']));
1531 exit;
1532 }
1533
1534 // If this was the chunk, then we should instead be concatenating onto the final file
1535 if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
1536 $final_file = $_POST['name'];
1537 rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
1538 $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
1539
1540 // Final chunk? If so, then stich it all back together
1541 if ($_POST['chunk'] == $_POST['chunks']-1) {
1542 if ($wh = fopen($updraft_dir.'/'.$final_file, 'wb')) {
1543 for ($i=0 ; $i<$_POST['chunks']; $i++) {
1544 $rf = $updraft_dir.'/'.$final_file.'.'.$i.'.zip.tmp';
1545 if ($rh = fopen($rf, 'rb')) {
1546 while ($line = fread($rh, 32768)) fwrite($wh, $line);
1547 fclose($rh);
1548 @unlink($rf);
1549 }
1550 }
1551 fclose($wh);
1552 $status['file'] = $updraft_dir.'/'.$final_file;
1553 if ('.tar' == substr($final_file, -4, 4)) {
1554 if (file_exists($status['file'].'.gz')) unlink($status['file'].'.gz');
1555 if (file_exists($status['file'].'.bz2')) unlink($status['file'].'.bz2');
1556 } elseif ('.tar.gz' == substr($final_file, -7, 7)) {
1557 if (file_exists(substr($status['file'], 0, strlen($status['file'])-3))) unlink(substr($status['file'], 0, strlen($status['file'])-3));
1558 if (file_exists(substr($status['file'], 0, strlen($status['file'])-3).'.bz2')) unlink(substr($status['file'], 0, strlen($status['file'])-3).'.bz2');
1559 } elseif ('.tar.bz2' == substr($final_file, -8, 8)) {
1560 if (file_exists(substr($status['file'], 0, strlen($status['file'])-4))) unlink(substr($status['file'], 0, strlen($status['file'])-4));
1561 if (file_exists(substr($status['file'], 0, strlen($status['file'])-4).'.gz')) unlink(substr($status['file'], 0, strlen($status['file'])-3).'.gz');
1562 }
1563 }
1564 }
1565
1566 }
1567
1568 $response = array();
1569 if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
1570 $file = basename($status['file']);
1571 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)) {
1572 $accept = apply_filters('updraftplus_accept_archivename', array());
1573 if (is_array($accept)) {
1574 foreach ($accept as $acc) {
1575 if (preg_match('/'.$acc['pattern'].'/i', $file)) $accepted = $acc['desc'];
1576 }
1577 }
1578 if (!empty($accepted)) {
1579 $response['dm'] = sprintf(__('This backup was created by %s, and can be imported.', 'updraftplus'), $accepted);
1580 } else {
1581 @unlink($status['file']);
1582 echo json_encode(array('e' => sprintf(__('Error: %s', 'updraftplus'),__('Bad filename format - this does not look like a file created by UpdraftPlus','updraftplus'))));
1583 exit;
1584 }
1585 } else {
1586 $backupable_entities = $updraftplus->get_backupable_file_entities(true);
1587 $type = $matches[3];
1588 if ('db' != $type && !isset($backupable_entities[$type]) && !preg_match('/^log\.[a-f0-9]{12}\.txt/', $file)) {
1589 @unlink($status['file']);
1590 echo json_encode(array('e' => sprintf(__('Error: %s', 'updraftplus'),sprintf(__('This looks like a file created by UpdraftPlus, but this install does not know about this type of object: %s. Perhaps you need to install an add-on?','updraftplus'), htmlspecialchars($type)))));
1591 exit;
1592 }
1593 }
1594 }
1595
1596 // send the uploaded file url in response
1597 $response['m'] = $status['url'];
1598 echo json_encode($response);
1599 exit;
1600 }
1601
1602 # Database decrypter
1603 public function plupload_action2() {
1604
1605 @set_time_limit(900);
1606 global $updraftplus;
1607
1608 // check ajax nonce
1609 check_ajax_referer('updraft-uploader');
1610
1611 $updraft_dir = $updraftplus->backups_dir_location();
1612 if (!is_writable($updraft_dir)) exit;
1613
1614 add_filter('upload_dir', array($this, 'upload_dir'));
1615 add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
1616 // handle file upload
1617
1618 $farray = array( 'test_form' => true, 'action' => 'plupload_action2' );
1619
1620 $farray['test_type'] = false;
1621 $farray['ext'] = 'crypt';
1622 $farray['type'] = 'application/octet-stream';
1623
1624 if (isset($_POST['chunks'])) {
1625 // $farray['ext'] = 'zip';
1626 // $farray['type'] = 'application/zip';
1627 } else {
1628 $farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
1629 }
1630
1631 $status = wp_handle_upload(
1632 $_FILES['async-upload'],
1633 $farray
1634 );
1635 remove_filter('upload_dir', array($this, 'upload_dir'));
1636 remove_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
1637
1638 if (isset($status['error'])) {
1639 echo 'ERROR:'.$status['error'];
1640 exit;
1641 }
1642
1643 // If this was the chunk, then we should instead be concatenating onto the final file
1644 if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
1645 $final_file = $_POST['name'];
1646 rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
1647 $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
1648
1649 // Final chunk? If so, then stich it all back together
1650 if ($_POST['chunk'] == $_POST['chunks']-1) {
1651 if ($wh = fopen($updraft_dir.'/'.$final_file, 'wb')) {
1652 for ($i=0 ; $i<$_POST['chunks']; $i++) {
1653 $rf = $updraft_dir.'/'.$final_file.'.'.$i.'.zip.tmp';
1654 if ($rh = fopen($rf, 'rb')) {
1655 while ($line = fread($rh, 32768)) fwrite($wh, $line);
1656 fclose($rh);
1657 @unlink($rf);
1658 }
1659 }
1660 fclose($wh);
1661 $status['file'] = $updraft_dir.'/'.$final_file;
1662 }
1663 }
1664
1665 }
1666
1667 if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
1668 $file = basename($status['file']);
1669 if (!preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-db([0-9]+)?\.(gz\.crypt)$/i', $file)) {
1670
1671 @unlink($status['file']);
1672 echo 'ERROR:'.__('Bad filename format - this does not look like an encrypted database file created by UpdraftPlus','updraftplus');
1673
1674 exit;
1675 }
1676 }
1677
1678 // send the uploaded file url in response
1679 // echo 'OK:'.$status['url'];
1680 echo 'OK:'.$file;
1681 exit;
1682 }
1683
1684
1685 public function settings_output() {
1686
1687 global $updraftplus;
1688
1689 /*
1690 we use request here because the initial restore is triggered by a POSTed form. we then may need to obtain credentials
1691 for the WP_Filesystem. to do this WP outputs a form, but we don't pass our parameters via that. So the values are
1692 passed back in as GET parameters.
1693 */
1694 if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_restore' && isset($_REQUEST['backup_timestamp'])) {
1695 $backup_success = $this->restore_backup($_REQUEST['backup_timestamp']);
1696 if(empty($updraftplus->errors) && $backup_success === true) {
1697 // If we restored the database, then that will have out-of-date information which may confuse the user - so automatically re-scan for them.
1698 $this->rebuild_backup_history();
1699 echo '<p><strong>';
1700 $updraftplus->log_e('Restore successful!');
1701 echo '</strong></p>';
1702 $updraftplus->log("Restore successful");
1703 echo '<strong>'.__('Actions','updraftplus').':</strong> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&updraft_restore_success=true">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1704 return;
1705 } elseif (is_wp_error($backup_success)) {
1706 echo '<p>';
1707 $updraftplus->log_e('Restore failed...');
1708 echo '</p>';
1709 $updraftplus->log_wp_error($backup_success);
1710 $updraftplus->log("Restore failed");
1711 $updraftplus->list_errors();
1712 echo '<strong>'.__('Actions','updraftplus').':</strong> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1713 return;
1714 } elseif (false === $backup_success) {
1715 # 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"
1716 return;
1717 }
1718 }
1719
1720 if(isset($_REQUEST['action']) && 'updraft_delete_old_dirs' == $_REQUEST['action']) {
1721 $nonce = (empty($_REQUEST['_wpnonce'])) ? "" : $_REQUEST['_wpnonce'];
1722 if (!wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce')) die('Security check');
1723 $this->delete_old_dirs_go();
1724 return;
1725 }
1726
1727 if(!empty($_REQUEST['action']) && 'updraftplus_broadcastaction' == $_REQUEST['action'] && !empty($_REQUEST['subaction'])) {
1728 $nonce = (empty($_REQUEST['nonce'])) ? "" : $_REQUEST['nonce'];
1729 if (!wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce')) die('Security check');
1730 do_action($_REQUEST['subaction']);
1731 return;
1732 }
1733
1734 if(isset($_GET['error'])) $this->show_admin_warning(htmlspecialchars($_GET['error']), 'error');
1735 if(isset($_GET['message'])) $this->show_admin_warning(htmlspecialchars($_GET['message']));
1736
1737 if(isset($_GET['action']) && $_GET['action'] == 'updraft_create_backup_dir' && isset($_GET['nonce']) && wp_verify_nonce($_GET['nonce'], 'create_backup_dir')) {
1738 $created = $this->create_backup_dir();
1739 if(is_wp_error($created)) {
1740 echo '<p>'.__('Backup directory could not be created', 'updraftplus').'...<br/>';
1741 echo '<ul style="list-style: disc inside;">';
1742 foreach ($created->get_error_messages() as $key => $msg) {
1743 echo '<li>'.htmlspecialchars($msg).'</li>';
1744 }
1745 echo '</ul></p>';
1746 } elseif ($created !== false) {
1747 echo '<p>'.__('Backup directory successfully created.', 'updraftplus').'</p><br/>';
1748 }
1749 echo '<b>'.__('Actions','updraftplus').':</b> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__('Return to UpdraftPlus Configuration', 'updraftplus').'</a>';
1750 return;
1751 }
1752
1753 do_action('updraftplus_settings_page_init');
1754
1755 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>';
1756
1757 if(isset($_POST['action']) && 'updraft_backup_debug_all' == $_POST['action']) {
1758 $updraftplus->boot_backup(true,true);
1759 } elseif (isset($_POST['action']) && 'updraft_backup_debug_db' == $_POST['action']) {
1760 $updraftplus->boot_backup(false, true, false, true);
1761 } elseif (isset($_POST['action']) && 'updraft_wipesettings' == $_POST['action']) {
1762 $settings = $this->get_settings_keys();
1763 foreach ($settings as $s) UpdraftPlus_Options::delete_updraft_option($s);
1764
1765 # These aren't in get_settings_keys() because they are always in the options table, regardless of context
1766 global $wpdb;
1767 $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_%')");
1768
1769 $site_options = array('updraft_oneshotnonce');
1770 foreach ($site_options as $s) delete_site_option($s);
1771
1772 $this->show_admin_warning(__("Your settings have been wiped.", 'updraftplus'));
1773 }
1774 ?>
1775
1776 <div class="wrap" id="updraft-wrap">
1777 <h1><?php echo $updraftplus->plugin_title; ?></h1>
1778
1779 <?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/updraftplus-premium/"><?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="https://www.simbahosting.co.uk/s3/shop/"><?php _e('More plugins', 'updraftplus');?></a> ) <?php _e('Version','updraftplus');?>: <?php echo $updraftplus->version; ?>
1780 <br>
1781
1782 <div id="updraft-hidethis">
1783 <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>
1784 </p>
1785 </div>
1786
1787 <?php
1788 if(isset($_GET['updraft_restore_success'])) {
1789 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>";
1790 }
1791
1792 $ws_advert = $updraftplus->wordshell_random_advert(1);
1793 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>'; }
1794
1795 if(!$updraftplus->memory_check(64)) {?>
1796 <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>
1797 <?php
1798 }
1799 if($this->scan_old_dirs()) $this->print_delete_old_dirs_form();
1800 if(!empty($updraftplus->errors)) {
1801 echo '<div class="error fade" style="padding:8px;">';
1802 $updraftplus->list_errors();
1803 echo '</div>';
1804 }
1805 ?>
1806
1807 <h2 class="nav-tab-wrapper" style="margin: 14px 0px;">
1808 <a class="nav-tab nav-tab-active" href="#updraft-navtab-status-content" id="updraft-navtab-status"><?php _e('Current Status', 'updraftplus');?></a>
1809 <a class="nav-tab" href="#updraft-navtab-backups-contents" id="updraft-navtab-backups"><?php _e('Existing Backups', 'updraftplus');?></a>
1810 <a class="nav-tab" id="updraft-navtab-settings" href="#updraft-navtab-settings-content"><?php _e('Settings', 'updraftplus');?></a>
1811 <a class="nav-tab" id="updraft-navtab-expert" href="#updraft-navtab-expert-content"><?php _e('Debugging / Expert Tools', 'updraftplus');?></a>
1812 </h2>
1813
1814 <?php
1815 $updraft_dir = $updraftplus->backups_dir_location();
1816 $backup_disabled = ($updraftplus->really_is_writable($updraft_dir)) ? '' : 'disabled="disabled"';
1817 ?>
1818
1819 <div id="updraft-navtab-status-content">
1820
1821 <div id="updraft-insert-admin-warning"></div>
1822
1823 <table class="form-table" style="float:left; clear: both;">
1824 <noscript>
1825 <tr>
1826 <th><?php _e('JavaScript warning','updraftplus');?>:</th>
1827 <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>
1828 </tr>
1829 </noscript>
1830
1831 <tr>
1832 <th><?php _e('Actions', 'updraftplus');?>:</th>
1833 <td>
1834
1835 <button type="button" <?php echo $backup_disabled ?> class="button-primary updraft-bigbutton" <?php if ($backup_disabled) echo 'title="'.esc_attr(__('This button is disabled because your backup directory is not writable (see the settings).', 'updraftplus')).'" ';?> onclick="jQuery('#updraft-backupnow-modal').dialog('open');"><?php _e('Backup Now', 'updraftplus');?></button>
1836
1837 <button type="button" class="button-primary updraft-bigbutton" onclick="updraft_openrestorepanel();">
1838 <?php _e('Restore','updraftplus');?>
1839 </button>
1840
1841 <button type="button" class="button-primary updraft-bigbutton" onclick="jQuery('#updraft-migrate-modal').dialog('open');"><?php _e('Clone/Migrate','updraftplus');?></button>
1842
1843 </td>
1844 </tr>
1845
1846 <?php
1847 // UNIX timestamp
1848 $next_scheduled_backup = wp_next_scheduled('updraft_backup');
1849 if ($next_scheduled_backup) {
1850 // Convert to GMT
1851 $next_scheduled_backup_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup);
1852 // Convert to blog time zone
1853 $next_scheduled_backup = get_date_from_gmt($next_scheduled_backup_gmt, 'D, F j, Y H:i');
1854 } else {
1855 $next_scheduled_backup = __('Nothing currently scheduled','updraftplus');
1856 }
1857
1858 $next_scheduled_backup_database = wp_next_scheduled('updraft_backup_database');
1859 if (UpdraftPlus_Options::get_updraft_option('updraft_interval_database',UpdraftPlus_Options::get_updraft_option('updraft_interval')) == UpdraftPlus_Options::get_updraft_option('updraft_interval')) {
1860 $next_scheduled_backup_database = ('Nothing currently scheduled' == $next_scheduled_backup) ? $next_scheduled_backup : __("At the same time as the files backup", 'updraftplus');
1861 } else {
1862 if ($next_scheduled_backup_database) {
1863 // Convert to GMT
1864 $next_scheduled_backup_database_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup_database);
1865 // Convert to blog time zone
1866 $next_scheduled_backup_database = get_date_from_gmt($next_scheduled_backup_database_gmt, 'D, F j, Y H:i');
1867 } else {
1868 $next_scheduled_backup_database = __('Nothing currently scheduled','updraftplus');
1869 }
1870 }
1871 $current_time = get_date_from_gmt(gmdate('Y-m-d H:i:s'), 'D, F j, Y H:i');
1872
1873 $last_backup_html = $this->last_backup_html();
1874
1875 ?>
1876
1877 <script>var lastbackup_laststatus = '<?php echo esc_js($last_backup_html);?>';</script>
1878
1879 <tr>
1880 <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>
1881 <td>
1882 <table style="border: 0px; padding: 0px; margin: 0 10px 0 0;">
1883 <tr>
1884 <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>
1885 </tr><tr>
1886 <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>
1887 </tr><tr>
1888 <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>
1889 </table>
1890 </td>
1891 </tr>
1892 <tr>
1893 <th><?php _e('Last backup job run:','updraftplus');?></th>
1894 <td id="updraft_last_backup"><?php echo $last_backup_html ?></td>
1895 </tr>
1896 </table>
1897
1898 <?php
1899 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1900 if (empty($backup_history)) {
1901 $this->rebuild_backup_history();
1902 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1903 }
1904 $backup_history = (is_array($backup_history))?$backup_history:array();
1905 ?>
1906
1907 <br style="clear:both" />
1908 <table class="form-table">
1909
1910 <?php $active_jobs = $this->print_active_jobs();?>
1911 <tr id="updraft_activejobsrow" style="<?php if (!$active_jobs) echo 'display:none;'; ?>">
1912 <th><?php _e('Backups in progress:', 'updraftplus');?></th>
1913 <td id="updraft_activejobs"><?php echo $active_jobs;?></td>
1914 </tr>
1915
1916 <tr id="updraft_lastlogmessagerow">
1917 <th><?php _e('Last log message','updraftplus');?>:</th>
1918 <td>
1919 <span id="updraft_lastlogcontainer"><?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', __('(Nothing yet logged)','updraftplus'))); ?></span><br>
1920 <a href="?page=updraftplus&action=downloadlatestmodlog&wpnonce=<?php echo wp_create_nonce('updraftplus_download') ?>"><?php _e('Download most recently modified log file','updraftplus');?></a>
1921 </td>
1922 </tr>
1923
1924 <tr>
1925 <th><?php echo htmlspecialchars(__('Backups, logs & restoring','updraftplus')); ?>:</th>
1926 <td><a id="updraft_showbackups" href="#" title="<?php _e('Press to see available backups','updraftplus');?>" onclick="updraft_openrestorepanel(0); return false;"><?php echo sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history)); ?></a></td>
1927 </tr>
1928 <?php
1929 # Currently disabled - not sure who we want to show this to
1930 if (1==0 && !defined('UPDRAFTPLUS_NOADS_A')) {
1931 $feed = $updraftplus->get_updraftplus_rssfeed();
1932 if (is_a($feed, 'SimplePie')) {
1933 echo '<tr><th style="vertical-align:top;">'.__('Latest UpdraftPlus.com news:', 'updraftplus').'</th><td style="vertical-align:top;">';
1934 echo '<ul style="list-style: disc inside;">';
1935 foreach ($feed->get_items(0, 5) as $item) {
1936 echo '<li>';
1937 echo '<a href="'.esc_attr($item->get_permalink()).'">';
1938 echo htmlspecialchars($item->get_title());
1939 # D, F j, Y H:i
1940 echo "</a> (".htmlspecialchars($item->get_date('j F Y')).")";
1941 echo '</li>';
1942 }
1943 echo '</ul></td></tr>';
1944 }
1945 }
1946 ?>
1947 </table>
1948
1949 <div id="updraft-migrate-modal" title="<?php _e('Migrate Site', 'updraftplus'); ?>">
1950
1951 <?php
1952 if (class_exists('UpdraftPlus_Addons_Migrator')) {
1953 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/');
1954 } else {
1955 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>';
1956 }
1957 ?>
1958 </p>
1959 </div>
1960
1961 <div id="updraft-iframe-modal">
1962 <div id="updraft-iframe-modal-innards">
1963 </div>
1964 </div>
1965
1966 <div id="updraft-backupnow-modal" title="UpdraftPlus - <?php _e('Perform a one-time backup','updraftplus'); ?>">
1967 <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>
1968
1969 <p>
1970 <input type="checkbox" id="backupnow_nodb"> <label for="backupnow_nodb"><?php _e("Don't include the database in the backup", 'updraftplus'); ?></label><br>
1971 <input type="checkbox" id="backupnow_nofiles"> <label for="backupnow_nofiles"><?php _e("Don't include any files in the backup", 'updraftplus'); ?></label><br>
1972 <input type="checkbox" id="backupnow_nocloud"> <label for="backupnow_nocloud"><?php _e("Don't send this backup to remote storage", 'updraftplus'); ?></label>
1973 </p>
1974
1975 <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>
1976 </div>
1977
1978 <?php
1979 if (is_multisite() && !file_exists(UPDRAFTPLUS_DIR.'/addons/multisite.php')) {
1980 ?>
1981 <h2>UpdraftPlus <?php _e('Multisite','updraftplus');?></h2>
1982 <table>
1983 <tr>
1984 <td>
1985 <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>
1986 </td>
1987 </tr>
1988 </table>
1989 <?php } ?>
1990
1991 </div>
1992
1993 <div id="updraft-navtab-backups-content" style="display:none;">
1994 <?php $this->settings_downloadingandrestoring($backup_history); ?>
1995 </div>
1996
1997 <div id="updraft-navtab-settings-content" style="display:none;">
1998 <h2 style="margin-top: 6px;"><?php _e('Configure Backup Contents And Schedule','updraftplus');?></h2>
1999 <?php UpdraftPlus_Options::options_form_begin(); ?>
2000 <?php $this->settings_formcontents($last_backup_html); ?>
2001 </form>
2002 </div>
2003
2004 <div id="updraft-navtab-expert-content" style="display:none;">
2005 <?php $this->settings_expertsettings($backup_disabled); ?>
2006 </div>
2007
2008 <?php
2009 }
2010
2011 private function settings_downloadingandrestoring($backup_history = array()) {
2012 global $updraftplus;
2013 //<td class="download-backups" style="display:none; border: 2px dashed #aaa;">
2014 ?>
2015 <div class="download-backups form-table">
2016 <h2><?php echo __('Existing Backups: Downloading And Restoring', 'updraftplus'); ?></h2>
2017 <p style="display:none; background-color:pink; padding:8px; margin:4px;border: 1px dotted;" id="ud-whitespace-warning">
2018 <?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>';?>
2019 </p>
2020 <p>
2021 <ul style="list-style: disc inside; max-width: 1000px;">
2022 <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>
2023 <li>
2024 <strong><?php _e('Restoring:','updraftplus');?></strong> <?php _e('Press the Restore button next to the chosen backup set.', 'updraftplus');?>
2025 </li>
2026 <li>
2027 <strong><?php _e('More tasks:','updraftplus');?></strong>
2028 <a href="#" onclick="jQuery('#updraft-plupload-modal').slideToggle(); return false;"><?php _e('Upload backup files','updraftplus');?></a>
2029 | <a href="#" onclick="updraft_updatehistory(1, 0); 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 local folder for new backup sets','updraftplus');?></a>
2030 | <a href="#" onclick="updraft_updatehistory(1, 1); return false;" title="<?php _e('Press here to look inside any remote storage methods for any existing backup sets.','updraftplus'); ?>"><?php _e('Rescan remote storage','updraftplus');?></a>
2031 </li>
2032 <?php
2033 if (false !== strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') || false !== strpos($_SERVER['HTTP_USER_AGENT'], 'OPR/')) { ?>
2034 <li><strong><?php _e('Opera web browser','updraftplus');?>:</strong> <?php _e('If you are using this, then turn Turbo/Road mode off.','updraftplus');?></li>
2035 <?php } ?>
2036 <?php
2037 $service = UpdraftPlus_Options::get_updraft_option('updraft_service');
2038 if ($service === 'googledrive' || (is_array($service) && in_array('googledrive', $service))) {
2039 ?><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>
2040 <?php } ?>
2041
2042 <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>
2043 </p>
2044
2045 <div id="updraft-plupload-modal" title="<?php _e('UpdraftPlus - Upload backup files','updraftplus'); ?>" style="width: 75%; margin: 16px; display:none; margin-left: 100px;">
2046 <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>
2047 <?php
2048 global $wp_version;
2049 if (version_compare($wp_version, '3.3', '<')) {
2050 echo '<em>'.sprintf(__('This feature requires %s version %s or later', 'updraftplus'), 'WordPress', '3.3').'</em>';
2051 } else {
2052 ?>
2053 <div id="plupload-upload-ui" style="width: 70%;">
2054 <div id="drag-drop-area">
2055 <div class="drag-drop-inside">
2056 <p class="drag-drop-info"><?php _e('Drop backup files here', 'updraftplus'); ?></p>
2057 <p><?php _ex('or', 'Uploader: Drop backup files here - or - Select Files'); ?></p>
2058 <p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
2059 </div>
2060 </div>
2061 <div id="filelist">
2062 </div>
2063 </div>
2064 <?php
2065 }
2066 ?>
2067
2068 </div>
2069
2070 <div id="ud_downloadstatus"></div>
2071 <div id="updraft_existing_backups" style="margin-bottom:12px;">
2072 <?php
2073 print $this->existing_backup_table($backup_history);
2074 ?>
2075 </div>
2076 </div>
2077
2078 <div id="updraft-message-modal" title="UpdraftPlus">
2079 <div id="updraft-message-modal-innards" style="padding: 4px;">
2080 </div>
2081 </div>
2082
2083 <div id="updraft-delete-modal" title="<?php _e('Delete backup set', 'updraftplus');?>">
2084 <form id="updraft_delete_form" method="post">
2085 <p style="margin-top:3px; padding-top:0">
2086 <?php _e('Are you sure that you wish to remove this backup set from UpdraftPlus?', 'updraftplus'); ?>
2087 </p>
2088 <fieldset>
2089 <input type="hidden" name="nonce" value="<?php echo wp_create_nonce('updraftplus-credentialtest-nonce');?>">
2090 <input type="hidden" name="action" value="updraft_ajax">
2091 <input type="hidden" name="subaction" value="deleteset">
2092 <input type="hidden" name="backup_timestamp" value="0" id="updraft_delete_timestamp">
2093 <input type="hidden" name="backup_nonce" value="0" id="updraft_delete_nonce">
2094 <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>
2095 <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>
2096 </div>
2097 </fieldset>
2098 </form>
2099 </div>
2100
2101 <div id="updraft-restore-modal" title="UpdraftPlus - <?php _e('Restore backup','updraftplus');?>">
2102 <p><strong><?php _e('Restore backup from','updraftplus');?>:</strong> <span class="updraft_restore_date"></span></p>
2103
2104 <div id="updraft-restore-modal-stage2">
2105
2106 <p><strong><?php _e('Retrieving (if necessary) and preparing backup files...', 'updraftplus');?></strong></p>
2107 <div id="ud_downloadstatus2"></div>
2108
2109 <div id="updraft-restore-modal-stage2a"></div>
2110
2111 </div>
2112
2113 <div id="updraft-restore-modal-stage1">
2114 <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>
2115 <form id="updraft_restore_form" method="post">
2116 <fieldset>
2117 <input type="hidden" name="action" value="updraft_restore">
2118 <input type="hidden" name="backup_timestamp" value="0" id="updraft_restore_timestamp">
2119 <input type="hidden" name="meta_foreign" value="0" id="updraft_restore_meta_foreign">
2120 <?php
2121
2122 # 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
2123 if($updraftplus->detect_safe_mode()) {
2124 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/>";
2125 }
2126
2127 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2128 foreach ($backupable_entities as $type => $info) {
2129 if (!isset($info['restorable']) || $info['restorable'] == true) {
2130 echo '<div><input id="updraft_restore_'.$type.'" type="checkbox" name="updraft_restore[]" value="'.$type.'"> <label id="updraft_restore_label_'.$type.'" for="updraft_restore_'.$type.'">'.$info['description'].'</label><br>';
2131
2132 do_action("updraftplus_restore_form_$type");
2133
2134 echo '</div>';
2135 } else {
2136 $sdescrip = isset($info['shortdescription']) ? $info['shortdescription'] : $info['description'];
2137 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>';
2138 }
2139 }
2140 ?>
2141 <div><input id="updraft_restore_db" type="checkbox" name="updraft_restore[]" value="db"> <label for="updraft_restore_db"><?php _e('Database','updraftplus'); ?></label><br>
2142
2143
2144 <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>
2145
2146 <?php
2147
2148 do_action("updraftplus_restore_form_db");
2149
2150 if (!class_exists('UpdraftPlus_Addons_Migrator')) {
2151
2152 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>';
2153
2154 }
2155
2156 ?>
2157
2158 </div>
2159
2160 </div>
2161 </fieldset>
2162 </form>
2163 <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>
2164 </div>
2165
2166 </div>
2167
2168 <?php
2169 }
2170
2171 public function settings_debugrow($head, $content) {
2172 echo "<tr class=\"updraft_debugrow\"><th>$head</th><td>$content</td></tr>";
2173 }
2174
2175 private function settings_expertsettings($backup_disabled) {
2176 global $updraftplus, $wpdb;
2177 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2178 ?>
2179 <div class="expertmode">
2180 <!-- <h2><?php _e('Debug Information And Expert Options','updraftplus');?></h2> -->
2181 <table>
2182 <?php
2183
2184 $this->settings_debugrow(__('Web server:','updraftplus'), htmlspecialchars($_SERVER["SERVER_SOFTWARE"]).' ('.htmlspecialchars(php_uname()).')');
2185
2186 $this->settings_debugrow('ABSPATH:', htmlspecialchars(ABSPATH));
2187 $this->settings_debugrow('WP_CONTENT_DIR:', htmlspecialchars(WP_CONTENT_DIR));
2188 $this->settings_debugrow('WP_PLUGIN_DIR:', htmlspecialchars(WP_PLUGIN_DIR));
2189 $this->settings_debugrow('Table prefix:', htmlspecialchars($updraftplus->get_table_prefix()));
2190 $peak_memory_usage = memory_get_peak_usage(true)/1024/1024;
2191 $memory_usage = memory_get_usage(true)/1024/1024;
2192 $this->settings_debugrow(__('Peak memory usage','updraftplus').':', $peak_memory_usage.' MB');
2193 $this->settings_debugrow(__('Current memory usage','updraftplus').':', $memory_usage.' MB');
2194 $this->settings_debugrow(__('Memory limit', 'updraftplus').':', htmlspecialchars(ini_get('memory_limit')));
2195 $this->settings_debugrow(sprintf(__('%s version:','updraftplus'), 'PHP'), htmlspecialchars(phpversion()).' - <a href="admin-ajax.php?page=updraftplus&action=updraft_ajax&subaction=phpinfo&nonce='.wp_create_nonce('updraftplus-credentialtest-nonce').'" id="updraftplus-phpinfo">'.__('show PHP information (phpinfo)', 'updraftplus').'</a>');
2196 $this->settings_debugrow(sprintf(__('%s version:','updraftplus'), 'MySQL'), htmlspecialchars($wpdb->db_version()));
2197 if (function_exists('curl_version') && function_exists('curl_exec')) {
2198 $cv = curl_version();
2199 $cvs = $cv['version'].' / SSL: '.$cv['ssl_version'].' / libz: '.$cv['libz_version'];
2200 } else {
2201 $cvs = '-';
2202 }
2203 $this->settings_debugrow(sprintf(__('%s version:','updraftplus'), 'Curl'), htmlspecialchars($cvs));
2204 if (version_compare(phpversion(), '5.2.0', '>=') && extension_loaded('zip')) {
2205 $ziparchive_exists = __('Yes', 'updraftplus');
2206 } else {
2207 # First do class_exists, because method_exists still sometimes segfaults due to a rare PHP bug
2208 $ziparchive_exists = (class_exists('ZipArchive') && method_exists('ZipArchive', 'addFile')) ? __('Yes', 'updraftplus') : __('No', 'updraftplus');
2209 }
2210 $this->settings_debugrow('ZipArchive::addFile:', $ziparchive_exists);
2211 $binzip = $updraftplus->find_working_bin_zip(false, false);
2212 $this->settings_debugrow(__('zip executable found:', 'updraftplus'), __('zip executable found:', 'updraftplus').' '.((is_string($binzip)) ? __('Yes').': '.$binzip : __('No')));
2213 $hosting_bytes_free = $updraftplus->get_hosting_disk_quota_free();
2214 if (is_array($hosting_bytes_free)) {
2215 $perc = round(100*$hosting_bytes_free[1]/(max($hosting_bytes_free[2], 1)), 1);
2216 $this->settings_debugrow(__('Free disk space in account:', 'updraftplus'), sprintf(__('%s (%s used)', 'updraftplus'), round($hosting_bytes_free[3]/1048576, 1)." Mb", "$perc %"));
2217 }
2218
2219 $this->settings_debugrow(__('Plugins for debugging:', 'updraftplus'),'<a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=wp-crontrol'), 'install-plugin_wp-crontrol').'">WP Crontrol</a> | <a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=sql-executioner'), 'install-plugin_sql-executioner').'">SQL Executioner</a> | <a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=advanced-code-editor'), 'install-plugin_advanced-code-editor').'">Advanced Code Editor</a> | <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>');
2220
2221 $this->settings_debugrow("HTTP Get: ", '<input id="updraftplus_httpget_uri" type="text" style="width: 300px; height: 22px;"> <a href="#" id="updraftplus_httpget_go">'.__('Fetch', 'updraftplus').'</a> <a href="#" id="updraftplus_httpget_gocurl">'.__('Fetch', 'updraftplus').' (Curl)</a><p id="updraftplus_httpget_results"></p>');
2222
2223 $this->settings_debugrow("Call WordPress action:", '<input id="updraftplus_callwpaction" type="text" style="width: 300px; height: 22px;"> <a href="#" id="updraftplus_callwpaction_go">'.__('Call', 'updraftplus').'</a><div id="updraftplus_callwpaction_results"></div>');
2224
2225 $this->settings_debugrow('', '<a href="admin-ajax.php?page=updraftplus&action=updraft_ajax&subaction=backuphistoryraw&nonce='.wp_create_nonce('updraftplus-credentialtest-nonce').'" id="updraftplus-rawbackuphistory">'.__('Show raw backup and file list', 'updraftplus').'</a>');
2226
2227 echo '</table>';
2228
2229 do_action('updraftplus_debugtools_dashboard');
2230
2231 echo '<h3>'.__('Total (uncompressed) on-disk data:','updraftplus').'</h3>';
2232 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><table>';
2233
2234 foreach ($backupable_entities as $key => $info) {
2235
2236 $sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']);
2237 if (strlen($sdescrip) > 20 && isset($info['shortdescription'])) $sdescrip = $info['shortdescription'];
2238
2239 // 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>';
2240 $this->settings_debugrow(ucfirst($sdescrip).':', '<span id="updraft_diskspaceused_'.$key.'"><em></em></span> <a href="#" onclick="updraftplus_diskspace_entity(\''.$key.'\'); return false;">'.__('count','updraftplus').'</a>');
2241 }
2242
2243 ?>
2244
2245 </table></p>
2246 <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 do absolutely nothing (i.e. not even produce a log file), then it means that your scheduler is broken.','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 more information.', 'updraftplus'); ?></a></p>
2247
2248 <table border="0" style="border: none;">
2249 <tbody>
2250 <tr>
2251 <td>
2252 <form method="post">
2253 <input type="hidden" name="action" value="updraft_backup_debug_all" />
2254 <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>
2255 </form>
2256 </td><td>
2257 <form method="post">
2258 <input type="hidden" name="action" value="updraft_backup_debug_db" />
2259 <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>
2260 </form>
2261 </td>
2262 </tr>
2263 </tbody>
2264 </table>
2265 <h3><?php _e('Wipe Settings','updraftplus');?></h3>
2266 <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>
2267 <form method="post">
2268 <input type="hidden" name="action" value="updraft_wipesettings" />
2269 <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>
2270 </form>
2271 </div>
2272 <?php
2273 }
2274
2275 function print_delete_old_dirs_form($include_blurb = true) {
2276 ?>
2277 <?php if ($include_blurb) {
2278 ?>
2279 <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 } ?>
2280 <form method="post" onsubmit="return updraft_delete_old_dirs();" action="<?php echo add_query_arg(array('updraft_restore_success' => false, 'action' => false, 'page' => 'updraftplus')); ?>">
2281 <?php wp_nonce_field('updraftplus-credentialtest-nonce'); ?>
2282 <input type="hidden" name="action" value="updraft_delete_old_dirs">
2283 <input type="submit" class="button-primary" value="<?php echo esc_attr(__('Delete Old Directories', 'updraftplus'));?>" />
2284 </form>
2285 <?php
2286 if ($include_blurb) echo '</div>';
2287 }
2288
2289
2290 private function print_active_jobs() {
2291 $cron = get_option('cron');
2292 if (!is_array($cron)) $cron = array();
2293 // $found_jobs = 0;
2294
2295 $ret = '';
2296
2297 foreach ($cron as $time => $job) {
2298 if (isset($job['updraft_backup_resume'])) {
2299 foreach ($job['updraft_backup_resume'] as $hook => $info) {
2300 if (isset($info['args'][1])) {
2301 // $found_jobs++;
2302 $job_id = $info['args'][1];
2303 $ret .= $this->print_active_job($job_id, false, $time, $info['args'][0]);
2304 }
2305 }
2306 }
2307 }
2308
2309 // if (0 == $found_jobs) {
2310 // $ret .= '<p><em>'.__('(None)', 'updraftplus').'</em></p>';
2311 // }
2312 return $ret;
2313 }
2314
2315 private function print_active_job($job_id, $is_oneshot = false, $time = false, $next_resumption = false) {
2316
2317 $ret = '';
2318
2319 global $updraftplus;
2320 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2321
2322 $jobdata = $updraftplus->jobdata_getarray($job_id);
2323
2324 #if (!is_array($jobdata)) $jobdata = array();
2325 if (!isset($jobdata['backup_time'])) return '';
2326
2327 $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') : '?';
2328
2329 $jobstatus = empty($jobdata['jobstatus']) ? 'unknown' : $jobdata['jobstatus'];
2330 $stage = 0;
2331 switch ($jobstatus) {
2332 # Stage 0
2333 case 'begun':
2334 $curstage = __('Backup begun', 'updraftplus');
2335 break;
2336 # Stage 1
2337 case 'filescreating':
2338 $stage = 1;
2339 $curstage = __('Creating file backup zips', 'updraftplus');
2340 if (!empty($jobdata['filecreating_substatus']) && isset($backupable_entities[$jobdata['filecreating_substatus']['e']]['description'])) {
2341
2342 $sdescrip = preg_replace('/ \(.*\)$/', '', $backupable_entities[$jobdata['filecreating_substatus']['e']]['description']);
2343 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'];
2344 $curstage .= ' ('.$sdescrip.')';
2345 if (isset($jobdata['filecreating_substatus']['i']) && isset($jobdata['filecreating_substatus']['t'])) {
2346 $stage = min(2, 1 + ($jobdata['filecreating_substatus']['i']/max($jobdata['filecreating_substatus']['t'],1)));
2347 }
2348 }
2349 break;
2350 case 'filescreated':
2351 $stage = 2;
2352 $curstage = __('Created file backup zips', 'updraftplus');
2353 break;
2354
2355 # Stage 4
2356 case 'clouduploading':
2357 $stage = 4;
2358 $curstage = __('Uploading files to remote storage', 'updraftplus');
2359 if (isset($jobdata['uploading_substatus']['t']) && isset($jobdata['uploading_substatus']['i'])) {
2360 $t = max((int)$jobdata['uploading_substatus']['t'], 1);
2361 $i = min($jobdata['uploading_substatus']['i']/$t, 1);
2362 $p = min($jobdata['uploading_substatus']['p'], 1);
2363 $pd = $i + $p/$t;
2364 $stage = 4 + $pd;
2365 $curstage .= ' '.sprintf(__('(%s%%, file %s of %s)', 'updraftplus'), floor(100*$pd), $jobdata['uploading_substatus']['i']+1, $t);
2366 }
2367 break;
2368 case 'pruning':
2369 $stage = 5;
2370 $curstage = __('Pruning old backup sets', 'updraftplus');
2371 break;
2372 case 'resumingforerrors':
2373 $stage = -1;
2374 $curstage = __('Waiting until scheduled time to retry because of errors', 'updraftplus');
2375 break;
2376 # Stage 6
2377 case 'finished':
2378 $stage = 6;
2379 $curstage = __('Backup finished', 'updraftplus');
2380 break;
2381 default:
2382
2383 # Database creation and encryption occupies the space from 2 to 4. Databases are created then encrypted, then the next databae is created/encrypted, etc.
2384 if ('dbcreated' == substr($jobstatus, 0, 9)) {
2385 $jobstatus = 'dbcreated';
2386 $whichdb = substr($jobstatus, 9);
2387 if (!is_numeric($whichdb)) $whichdb = 0;
2388 $howmanydbs = max((empty($jobdata['backup_database']) || !is_array($jobdata['backup_database'])) ? 1 : count($jobdata['backup_database']), 1);
2389 $perdbspace = 2/$howmanydbs;
2390
2391 $stage = min(4, 2 + ($whichdb+2)*$perdbspace);
2392
2393 $curstage = __('Created database backup', 'updraftplus');
2394
2395 } elseif ('dbcreating' == substr($jobstatus, 0, 10)) {
2396 $whichdb = substr($jobstatus, 10);
2397 if (!is_numeric($whichdb)) $whichdb = 0;
2398 $howmanydbs = (empty($jobdata['backup_database']) || !is_array($jobdata['backup_database'])) ? 1 : count($jobdata['backup_database']);
2399 $perdbspace = 2/$howmanydbs;
2400 $jobstatus = 'dbcreating';
2401
2402 $stage = min(4, 2 + $whichdb*$perdbspace);
2403
2404 $curstage = __('Creating database backup', 'updraftplus');
2405 if (!empty($jobdata['dbcreating_substatus']['t'])) {
2406 $curstage .= ' ('.sprintf(__('table: %s', 'updraftplus'), $jobdata['dbcreating_substatus']['t']).')';
2407 if (!empty($jobdata['dbcreating_substatus']['i']) && !empty($jobdata['dbcreating_substatus']['a'])) {
2408 $substage = max(0.001, ($jobdata['dbcreating_substatus']['i'] / max($jobdata['dbcreating_substatus']['a'],1)));
2409 $stage += $substage * $perdbspace * 0.5;
2410 }
2411 }
2412 } elseif ('dbencrypting' == substr($jobstatus, 0, 12)) {
2413 $whichdb = substr($jobstatus, 12);
2414 if (!is_numeric($whichdb)) $whichdb = 0;
2415 $howmanydbs = (empty($jobdata['backup_database']) || !is_array($jobdata['backup_database'])) ? 1 : count($jobdata['backup_database']);
2416 $perdbspace = 2/$howmanydbs;
2417 $stage = min(4, 2 + $whichdb*$perdbspace + $perdbspace*0.5);
2418 $jobstatus = 'dbencrypting';
2419 $curstage = __('Encrypting database', 'updraftplus');
2420 } elseif ('dbencrypted' == substr($jobstatus, 0, 11)) {
2421 $whichdb = substr($jobstatus, 11);
2422 if (!is_numeric($whichdb)) $whichdb = 0;
2423 $howmanydbs = (empty($jobdata['backup_database']) || !is_array($jobdata['backup_database'])) ? 1 : count($jobdata['backup_database']);
2424 $jobstatus = 'dbencrypted';
2425 $perdbspace = 2/$howmanydbs;
2426 $stage = min(4, 2 + $whichdb*$perdbspace + $perdbspace);
2427 $curstage = __('Encrypted database', 'updraftplus');
2428 } else {
2429 $curstage = __('Unknown', 'updraftplus');
2430 }
2431 }
2432
2433 $runs_started = (empty($jobdata['runs_started'])) ? array() : $jobdata['runs_started'];
2434 $time_passed = (empty($jobdata['run_times'])) ? array() : $jobdata['run_times'];
2435 $last_checkin_ago = -1;
2436 if (is_array($time_passed)) {
2437 foreach ($time_passed as $run => $passed) {
2438 if (isset($runs_started[$run])) {
2439 $time_ago = microtime(true) - ($runs_started[$run] + $time_passed[$run]);
2440 if ($time_ago < $last_checkin_ago || $last_checkin_ago == -1) $last_checkin_ago = $time_ago;
2441 }
2442 }
2443 }
2444
2445 $next_res_after = $time-time();
2446 $next_res_txt = ($is_oneshot) ? '' : ' - '.sprintf(__("next resumption: %d (after %ss)", 'updraftplus'), $next_resumption, $next_res_after). ' ';
2447 $last_activity_txt = ($last_checkin_ago >= 0) ? ' - '.sprintf(__('last activity: %ss ago', 'updraftplus'), floor($last_checkin_ago)).' ' : '';
2448
2449 if (($last_checkin_ago < 50 && $next_res_after>30) || $is_oneshot) {
2450 $show_inline_info = $last_activity_txt;
2451 $title_info = $next_res_txt;
2452 } else {
2453 $show_inline_info = $next_res_txt;
2454 $title_info = $last_activity_txt;
2455 }
2456
2457 $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> ';
2458
2459 $ret .= $show_inline_info;
2460
2461 $ret .= '- <a href="?page=updraftplus&action=downloadlog&updraftplus_backup_nonce='.$job_id.'">'.__('show log', 'updraftplus').'</a>';
2462
2463 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>';
2464
2465 if (!empty($jobdata['warnings']) && is_array($jobdata['warnings'])) {
2466 $ret .= '<ul style="list-style: disc inside;">';
2467 foreach ($jobdata['warnings'] as $warning) {
2468 $ret .= '<li>'.sprintf(__('Warning: %s', 'updraftplus'), make_clickable(htmlspecialchars($warning))).'</li>';
2469 }
2470 $ret .= '</ul>';
2471 }
2472
2473 $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;">';
2474 $ret .= htmlspecialchars($curstage);
2475 $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>';
2476 $ret .= '</div></div>';
2477
2478 $ret .= '</div>';
2479
2480 return $ret;
2481
2482 }
2483
2484 private function delete_old_dirs_go($show_return = true) {
2485 echo ($show_return) ? '<h1>UpdraftPlus - '.__('Remove old directories', 'updraftplus').'</h1>' : '<h2>'.__('Remove old directories', 'updraftplus').'</h2>';
2486
2487 if($this->delete_old_dirs()) {
2488 echo '<p>'.__('Old directories successfully removed.','updraftplus').'</p><br/>';
2489 } else {
2490 echo '<p>',__('Old directory removal failed for some reason. You may want to do this manually.','updraftplus').'</p><br/>';
2491 }
2492 if ($show_return) echo '<b>'.__('Actions','updraftplus').':</b> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
2493 }
2494
2495 //deletes the -old directories that are created when a backup is restored.
2496 private function delete_old_dirs() {
2497 global $wp_filesystem, $updraftplus;
2498 $credentials = request_filesystem_credentials(wp_nonce_url(UpdraftPlus_Options::admin_page_url()."?page=updraftplus&action=updraft_delete_old_dirs", 'updraftplus-credentialtest-nonce'));
2499 WP_Filesystem($credentials);
2500 if ($wp_filesystem->errors->get_error_code()) {
2501 foreach ($wp_filesystem->errors->get_error_messages() as $message)
2502 show_message($message);
2503 exit;
2504 }
2505 // From WP_CONTENT_DIR - which contains 'themes'
2506 $ret = $this->delete_old_dirs_dir($wp_filesystem->wp_content_dir());
2507
2508 $updraft_dir = $updraftplus->backups_dir_location();
2509 if ($updraft_dir) {
2510 $ret4 = ($updraft_dir) ? $this->delete_old_dirs_dir($updraft_dir, false) : true;
2511 } else {
2512 $ret4 = true;
2513 }
2514
2515 // $ret2 = $this->delete_old_dirs_dir($wp_filesystem->abspath());
2516 $plugs = untrailingslashit($wp_filesystem->wp_plugins_dir());
2517 if ($wp_filesystem->is_dir($plugs.'-old')) {
2518 print "<strong>".__('Delete','updraftplus').": </strong>plugins-old: ";
2519 if(!$wp_filesystem->delete($plugs.'-old', true)) {
2520 $ret3 = false;
2521 print "<strong>".__('Failed', 'updraftplus')."</strong><br>";
2522 } else {
2523 $ret3 = true;
2524 print "<strong>".__('OK', 'updraftplus')."</strong><br>";
2525 }
2526 } else {
2527 $ret3 = true;
2528 }
2529
2530 return $ret && $ret3 && $ret4;
2531 }
2532
2533 private function delete_old_dirs_dir($dir, $wpfs = true) {
2534
2535 $dir = trailingslashit($dir);
2536
2537 global $wp_filesystem, $updraftplus;
2538
2539 if ($wpfs) {
2540 $list = $wp_filesystem->dirlist($dir);
2541 } else {
2542 $list = scandir($dir);
2543 }
2544 if (!is_array($list)) return false;
2545
2546 $ret = true;
2547 foreach ($list as $item) {
2548 $name = (is_array($item)) ? $item['name'] : $item;
2549 if ("-old" == substr($name, -4, 4)) {
2550 //recursively delete
2551 print "<strong>".__('Delete','updraftplus').": </strong>".htmlspecialchars($name).": ";
2552
2553 if ($wpfs) {
2554 if(!$wp_filesystem->delete($dir.$name, true)) {
2555 $ret = false;
2556 echo "<strong>".__('Failed', 'updraftplus')."</strong><br>";
2557 } else {
2558 echo "<strong>".__('OK', 'updraftplus')."</strong><br>";
2559 }
2560 } else {
2561 if ($updraftplus->remove_local_directory($dir.$name)) {
2562 echo "<strong>".__('OK', 'updraftplus')."</strong><br>";
2563 } else {
2564 $ret = false;
2565 echo "<strong>".__('Failed', 'updraftplus')."</strong><br>";
2566 }
2567 }
2568 }
2569 }
2570 return $ret;
2571 }
2572
2573 // The aim is to get a directory that is writable by the webserver, because that's the only way we can create zip files
2574 private function create_backup_dir() {
2575
2576 global $wp_filesystem, $updraftplus;
2577
2578 if (false === ($credentials = request_filesystem_credentials(UpdraftPlus_Options::admin_page().'?page=updraftplus&action=updraft_create_backup_dir&nonce='.wp_create_nonce('create_backup_dir')))) {
2579 return false;
2580 }
2581
2582 if ( ! WP_Filesystem($credentials) ) {
2583 // our credentials were no good, ask the user for them again
2584 request_filesystem_credentials(UpdraftPlus_Options::admin_page().'?page=updraftplus&action=updraft_create_backup_dir&nonce='.wp_create_nonce('create_backup_dir'), '', true);
2585 return false;
2586 }
2587
2588 $updraft_dir = $updraftplus->backups_dir_location();
2589
2590 $default_backup_dir = $wp_filesystem->find_folder(dirname($updraft_dir)).basename($updraft_dir);
2591
2592 $updraft_dir = ($updraft_dir) ? $wp_filesystem->find_folder(dirname($updraft_dir)).basename($updraft_dir) : $default_backup_dir;
2593
2594 if (!$wp_filesystem->is_dir($default_backup_dir) && !$wp_filesystem->mkdir($default_backup_dir, 0775)) {
2595 $wperr = new WP_Error;
2596 if ( $wp_filesystem->errors->get_error_code() ) {
2597 foreach ( $wp_filesystem->errors->get_error_messages() as $message ) {
2598 $wperr->add('mkdir_error', $message);
2599 }
2600 return $wperr;
2601 } else {
2602 return new WP_Error('mkdir_error', __('The request to the filesystem to create the directory failed.', 'updraftplus'));
2603 }
2604 }
2605
2606 if ($wp_filesystem->is_dir($default_backup_dir)) {
2607
2608 if ($updraftplus->really_is_writable($updraft_dir)) return true;
2609
2610 @$wp_filesystem->chmod($default_backup_dir, 0775);
2611 if ($updraftplus->really_is_writable($updraft_dir)) return true;
2612
2613 @$wp_filesystem->chmod($default_backup_dir, 0777);
2614
2615 if ($updraftplus->really_is_writable($updraft_dir)) {
2616 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>';
2617 return true;
2618 } else {
2619 @$wp_filesystem->chmod($default_backup_dir, 0775);
2620 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'));
2621 }
2622 }
2623
2624 return true;
2625 }
2626
2627 //scans the content dir to see if any -old dirs are present
2628 private function scan_old_dirs() {
2629 global $updraftplus;
2630 $dirs = scandir(untrailingslashit(WP_CONTENT_DIR));
2631 if (!is_array($dirs)) $dirs = array();
2632 $dirs_u = @scandir($updraftplus->backups_dir_location());
2633 if (!is_array($dirs_u)) $dirs_u = array();
2634 foreach (array_merge($dirs, $dirs_u) as $dir) { if (preg_match('/-old$/', $dir)) return true; }
2635 # No need to scan ABSPATH - we don't backup there
2636 if (is_dir(untrailingslashit(WP_PLUGIN_DIR).'-old')) return true;
2637 return false;
2638 }
2639
2640 public function storagemethod_row($method, $header, $contents) {
2641 ?>
2642 <tr class="updraftplusmethod <?php echo $method;?>">
2643 <th><?php echo $header;?></th>
2644 <td><?php echo $contents;?></td>
2645 </tr>
2646 <?php
2647 }
2648
2649 private function last_backup_html() {
2650
2651 global $updraftplus;
2652
2653 $updraft_last_backup = UpdraftPlus_Options::get_updraft_option('updraft_last_backup');
2654
2655 if($updraft_last_backup) {
2656
2657 // Convert to GMT, then to blog time
2658 $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>';
2659
2660 if (is_array($updraft_last_backup['errors'])) {
2661 foreach ($updraft_last_backup['errors'] as $err) {
2662 $level = (is_array($err)) ? $err['level'] : 'error';
2663 $message = (is_array($err)) ? $err['message'] : $err;
2664
2665 $last_backup_text .= ('warning' == $level) ? "<span style=\"color:orange;\">" : "<span style=\"color:red;\">";
2666
2667 if ('warning' == $level) {
2668 $message = sprintf(__("Warning: %s", 'updraftplus'), make_clickable(htmlspecialchars($message)));
2669 } else {
2670 $message = htmlspecialchars($message);
2671 }
2672
2673 $last_backup_text .= $message;
2674
2675 $last_backup_text .= '</span><br>';
2676 }
2677 }
2678
2679 if (!empty($updraft_last_backup['backup_nonce'])) {
2680 $updraft_dir = $updraftplus->backups_dir_location();
2681
2682 $potential_log_file = $updraft_dir."/log.".$updraft_last_backup['backup_nonce'].".txt";
2683
2684 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>";
2685 }
2686
2687 } else {
2688 $last_backup_text = "<span style=\"color:blue;\">".__('No backup has been completed.','updraftplus')."</span>";
2689 }
2690
2691 return $last_backup_text;
2692
2693 }
2694
2695 public function get_intervals() {
2696 return apply_filters('updraftplus_backup_intervals', array(
2697 "manual" => _x("Manual", 'i.e. Non-automatic', 'updraftplus'),
2698 'every4hours' => sprintf(__("Every %s hours", 'updraftplus'), '4'),
2699 'every8hours' => sprintf(__("Every %s hours", 'updraftplus'), '8'),
2700 'twicedaily' => sprintf(__("Every %s hours", 'updraftplus'), '12'),
2701 'daily' => __("Daily", 'updraftplus'),
2702 'weekly' => __("Weekly", 'updraftplus'),
2703 'fortnightly' => __("Fortnightly", 'updraftplus'),
2704 'monthly' => __("Monthly", 'updraftplus')
2705 ));
2706 }
2707
2708 private function settings_formcontents($last_backup_html) {
2709
2710 global $updraftplus;
2711
2712 $updraft_dir = $updraftplus->backups_dir_location();
2713
2714 ?>
2715 <table class="form-table">
2716 <tr>
2717 <th><?php _e('File backup intervals','updraftplus'); ?>:</th>
2718 <td><select id="updraft_interval" name="updraft_interval" onchange="jQuery(document).trigger('updraftplus_interval_changed'); updraft_check_same_times();">
2719 <?php
2720 $intervals = $this->get_intervals();
2721 $selected_interval = UpdraftPlus_Options::get_updraft_option('updraft_interval','manual');
2722 foreach ($intervals as $cronsched => $descrip) {
2723 echo "<option value=\"$cronsched\" ";
2724 if ($cronsched == $selected_interval) echo 'selected="selected"';
2725 echo ">".htmlspecialchars($descrip)."</option>\n";
2726 }
2727 ?>
2728 </select> <span id="updraft_files_timings"><?php echo apply_filters('updraftplus_schedule_showfileopts', '<input type="hidden" name="updraftplus_starttime_files" value="">'); ?></span>
2729 <?php
2730 echo __('and retain this many backups', 'updraftplus').': ';
2731 $updraft_retain = (int)UpdraftPlus_Options::get_updraft_option('updraft_retain', 2);
2732 $updraft_retain = ($updraft_retain > 0) ? $updraft_retain : 1;
2733 ?> <input type="number" min="1" step="1" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:48px;" />
2734 </td>
2735 </tr>
2736 <?php apply_filters('updraftplus_after_file_intervals', false, $selected_interval); ?>
2737 <tr>
2738 <th><?php _e('Database backup intervals','updraftplus'); ?>:</th>
2739 <td><select id="updraft_interval_database" name="updraft_interval_database" onchange="updraft_check_same_times();">
2740 <?php
2741 foreach ($intervals as $cronsched => $descrip) {
2742 echo "<option value=\"$cronsched\" ";
2743 if ($cronsched == UpdraftPlus_Options::get_updraft_option('updraft_interval_database', UpdraftPlus_Options::get_updraft_option('updraft_interval'))) echo 'selected="selected"';
2744 echo ">$descrip</option>\n";
2745 }
2746 ?>
2747 </select> <span id="updraft_db_timings"><?php echo apply_filters('updraftplus_schedule_showdbopts', '<input type="hidden" name="updraftplus_starttime_db" value="">'); ?></span>
2748 <?php
2749 echo __('and retain this many backups', 'updraftplus').': ';
2750 $updraft_retain_db = (int)UpdraftPlus_Options::get_updraft_option('updraft_retain_db', $updraft_retain);
2751 $updraft_retain_db = ($updraft_retain_db > 0) ? $updraft_retain_db : 1;
2752 ?> <input type="number" min="1" step="1" name="updraft_retain_db" value="<?php echo $updraft_retain_db ?>" style="width:48px" />
2753 </td>
2754 </tr>
2755 <tr class="backup-interval-description">
2756 <td></td><td><div style="max-width:670px;"><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>
2757 <?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/updraftplus-premium/">'.htmlspecialchars(__('use UpdraftPlus Premium', 'updraftplus')).'</a></p>'); ?>
2758 </div></td>
2759 </tr>
2760 <tr>
2761 <th><?php _e('Include in files backup','updraftplus');?>:</th>
2762 <td>
2763
2764 <?php
2765 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2766 # The true (default value if non-existent) here has the effect of forcing a default of on.
2767 foreach ($backupable_entities as $key => $info) {
2768 $included = (UpdraftPlus_Options::get_updraft_option("updraft_include_$key", apply_filters("updraftplus_defaultoption_include_".$key, true))) ? 'checked="checked"' : "";
2769 if ('others' == $key || 'uploads' == $key) {
2770
2771 $include_exclude = UpdraftPlus_Options::get_updraft_option('updraft_include_'.$key.'_exclude', ('others' == $key) ? UPDRAFT_DEFAULT_OTHERS_EXCLUDE : UPDRAFT_DEFAULT_UPLOADS_EXCLUDE);
2772
2773 ?><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
2774
2775 $display = ($included) ? '' : 'style="display:none;"';
2776
2777 echo "<div id=\"updraft_include_".$key."_exclude\" $display>";
2778
2779 echo '<label for="updraft_include_'.$key.'_exclude">'.__('Exclude these:', 'updraftplus').'</label>';
2780
2781 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).'" />';
2782
2783 echo '<br>';
2784
2785 echo '</div>';
2786
2787 } else {
2788 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>";
2789 do_action("updraftplus_config_option_include_$key");
2790 }
2791 }
2792 ?>
2793 <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>
2794 <?php if (1==0 && !defined('UPDRAFTPLUS_NOADS_A')) echo '<p><a href="http://wordshell.net">('.__('Use WordShell for automatic backup, version control and patching', 'updraftplus').').</a></p>';?>
2795 </td>
2796 </tr>
2797
2798 </table>
2799
2800 <h2><?php _e('Database Options','updraftplus');?></h2>
2801
2802 <table class="form-table" style="width:900px;">
2803
2804 <tr>
2805 <th><?php _e('Database encryption phrase','updraftplus');?>:</th>
2806
2807 <td>
2808 <?php
2809 echo apply_filters('updraft_database_encryption_config', '<a href="http://updraftplus.com/shop/updraftplus-premium/">'.__("Don't want to be spied on? UpdraftPlus Premium can encrypt your database backup.", 'updraftplus').'</a> '.__('It can also backup external databases.', 'updraftplus'));
2810 ?>
2811 </td>
2812 </tr>
2813 <tr class="backup-crypt-description">
2814 <td></td>
2815
2816 <td>
2817
2818 <a href="#" onclick="jQuery('#updraftplus_db_decrypt').val(jQuery('#updraft_encryptionphrase').val()); jQuery('#updraft-manualdecrypt-modal').slideToggle(); return false;"><?php _e('You can manually decrypt an encrypted database here.','updraftplus');?></a>
2819
2820 <div id="updraft-manualdecrypt-modal" style="width: 85%; margin: 6px; display:none; margin-left: 100px;">
2821 <p><h3><?php _e("Manually decrypt a database backup file" ,'updraftplus');?></h3></p>
2822
2823 <?php
2824 global $wp_version;
2825 if (version_compare($wp_version, '3.3', '<')) {
2826 echo '<em>'.sprintf(__('This feature requires %s version %s or later', 'updraftplus'), 'WordPress', '3.3').'</em>';
2827 } else {
2828 ?>
2829
2830 <div id="plupload-upload-ui2" style="width: 80%;">
2831 <div id="drag-drop-area2">
2832 <div class="drag-drop-inside">
2833 <p class="drag-drop-info"><?php _e('Drop encrypted database files (db.gz.crypt files) here to upload them for decryption'); ?></p>
2834 <p><?php _ex('or', 'Uploader: Drop db.gz.crypt files here to upload them for decryption - or - Select Files'); ?></p>
2835 <p class="drag-drop-buttons"><input id="plupload-browse-button2" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
2836 <p style="margin-top: 18px;"><?php _e('First, enter the decryption key','updraftplus')?>: <input id="updraftplus_db_decrypt" type="text" size="12"></input></p>
2837 </div>
2838 </div>
2839 <div id="filelist2">
2840 </div>
2841 </div>
2842
2843 <?php } ?>
2844
2845 </div>
2846
2847
2848 </td>
2849 </tr>
2850
2851 <?php
2852 #'<a href="http://updraftplus.com/shop/updraftplus-premium/">'.__("This feature is part of UpdraftPlus Premium.", 'updraftplus').'</a>'
2853 $moredbs_config = apply_filters('updraft_database_moredbs_config', false);
2854 if (!empty($moredbs_config)) {
2855 ?>
2856
2857 <tr>
2858 <th><?php _e('Back up more databases', 'updraftplus');?>:</th>
2859
2860 <td><?php
2861
2862 echo $moredbs_config;
2863
2864 ?>
2865
2866 </td>
2867 </tr>
2868
2869 <?php } ?>
2870
2871 </table>
2872
2873 <h2><?php _e('Reporting','updraftplus');?></h2>
2874
2875 <table class="form-table" style="width:900px;">
2876
2877 <?php
2878 $report_rows = apply_filters('updraftplus_report_form', false);
2879 if (is_string($report_rows)) {
2880 echo $report_rows;
2881 } else {
2882 ?>
2883
2884 <tr>
2885 <th><?php _e('Email', 'updraftplus'); ?>:</th>
2886 <td>
2887 <?php
2888 $updraft_email = UpdraftPlus_Options::get_updraft_option('updraft_email');
2889 ?>
2890 <input type="checkbox" id="updraft_email" name="updraft_email" value="<?php esc_attr_e(get_bloginfo('admin_email')); ?>"<?php if (!empty($updraft_email)) echo ' checked="checked"';?> > <br><label for="updraft_email"><?php echo sprintf(__("Check this box to have a basic report sent to your site's admin address (%s).",'updraftplus'), htmlspecialchars(get_bloginfo('admin_email'))); ?></label>
2891 <?php
2892 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>';
2893 ?>
2894 </td>
2895 </tr>
2896
2897 <?php } ?>
2898
2899 </table>
2900
2901 <h2><?php _e('Copying Your Backup To Remote Storage','updraftplus');?></h2>
2902
2903 <?php
2904 $debug_mode = (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) ? 'checked="checked"' : "";
2905 // Should be one of s3, dropbox, ftp, googledrive, email, or whatever else is added
2906 $active_service = UpdraftPlus_Options::get_updraft_option('updraft_service');
2907 ?>
2908
2909 <table class="form-table" style="width:900px;">
2910 <tr>
2911 <th><?php _e('Choose your remote storage','updraftplus');?>:</th>
2912 <td><?php
2913
2914 if (false === apply_filters('updraftplus_storage_printoptions', false, $active_service)) {
2915 if (is_array($active_service)) $active_service = $updraftplus->just_one($active_service);
2916 ?>
2917
2918 <select name="updraft_service" id="updraft-service">
2919 <option value="none" <?php
2920 if ('none' === $active_service) echo ' selected="selected"'; ?>><?php _e('None','updraftplus'); ?></option>
2921 <?php
2922 foreach ($updraftplus->backup_methods as $method => $description) {
2923 echo "<option value=\"$method\"";
2924 if ($active_service === $method || (is_array($active_service) && in_array($method, $active_service))) echo ' selected="selected"';
2925 echo '>'.$description;
2926 echo "</option>\n";
2927 }
2928 ?>
2929 </select>
2930
2931 <?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>'; ?>
2932
2933 </td>
2934 </tr>
2935
2936 <?php } ?>
2937
2938 <tr class="updraftplusmethod none" style="display:none;">
2939 <td></td>
2940 <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>
2941 </tr>
2942
2943 <?php
2944 $method_objects = array();
2945 foreach ($updraftplus->backup_methods as $method => $description) {
2946 do_action('updraftplus_config_print_before_storage', $method);
2947 require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
2948 $call_method = 'UpdraftPlus_BackupModule_'.$method;
2949 $method_objects[$method] = new $call_method;
2950 $method_objects[$method]->config_print();
2951 do_action('updraftplus_config_print_after_storage', $method);
2952 }
2953 ?>
2954
2955 </table>
2956 <script type="text/javascript">
2957 /* <![CDATA[ */
2958
2959 jQuery(document).ready(function() {
2960 <?php
2961 $really_is_writable = $updraftplus->really_is_writable($updraft_dir);
2962 if (!$really_is_writable) echo "jQuery('.backupdirrow').show();\n";
2963 ?>
2964 <?php
2965 if (!empty($active_service)) {
2966 if (is_array($active_service)) {
2967 foreach ($active_service as $serv) {
2968 echo "jQuery('.${serv}').show();\n";
2969 }
2970 } else {
2971 echo "jQuery('.${active_service}').show();\n";
2972 }
2973 } else {
2974 echo "jQuery('.none').show();\n";
2975 }
2976 foreach ($updraftplus->backup_methods as $method => $description) {
2977 // already done: require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
2978 $call_method = "UpdraftPlus_BackupModule_$method";
2979 if (method_exists($call_method, 'config_print_javascript_onready')) {
2980 $method_objects[$method]->config_print_javascript_onready();
2981 }
2982 }
2983 ?>
2984 });
2985 /* ]]> */
2986 </script>
2987 <table class="form-table" style="width:900px;">
2988 <tr>
2989 <td colspan="2"><h2><?php _e('Advanced / Debugging Settings','updraftplus'); ?></h2></td>
2990 </tr>
2991
2992 <tr>
2993 <th><?php _e('Expert settings','updraftplus');?>:</th>
2994 <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>
2995 </tr>
2996 <?php
2997 $delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
2998 $split_every_mb = UpdraftPlus_Options::get_updraft_option('updraft_split_every', 1*800);
2999 if (!is_numeric($split_every_mb)) $split_every_mb = 1*800;
3000 if ($split_every_mb < UPDRAFTPLUS_SPLIT_MIN) $split_every_mb = UPDRAFTPLUS_SPLIT_MIN;
3001 ?>
3002
3003 <tr class="expertmode" style="display:none;">
3004 <th><?php _e('Debug mode','updraftplus');?>:</th>
3005 <td><input type="checkbox" id="updraft_debug_mode" name="updraft_debug_mode" value="1" <?php echo $debug_mode; ?> /> <br><label for="updraft_debug_mode"><?php _e('Check this to receive more information and emails on the backup process - useful if something is going wrong.','updraftplus');?> <?php _e('This will also cause debugging output from all plugins to be shown upon this screen - please do not be surprised to see these.', 'updraftplus');?></label></td>
3006 </tr>
3007
3008 <tr class="expertmode" style="display:none;">
3009 <th><?php _e('Split archives every:','updraftplus');?></th>
3010 <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>
3011 </tr>
3012
3013 <tr class="deletelocal expertmode" style="display:none;">
3014 <th><?php _e('Delete local backup','updraftplus');?>:</th>
3015 <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>
3016 </tr>
3017
3018 <tr class="expertmode backupdirrow" style="display:none;">
3019 <th><?php _e('Backup directory','updraftplus');?>:</th>
3020 <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>
3021 </tr>
3022 <tr class="expertmode backupdirrow" style="display:none;">
3023 <td></td><td><?php
3024
3025 if($really_is_writable) {
3026 $dir_info = '<span style="color:green">'.__('Backup directory specified is writable, which is good.','updraftplus').'</span>';
3027 } else {
3028 $dir_info = '<span style="color:red">';
3029 if (!is_dir($updraft_dir)) {
3030 $dir_info .= __('Backup directory specified does <b>not</b> exist.','updraftplus');
3031 } else {
3032 $dir_info .= __('Backup directory specified exists, but is <b>not</b> writable.','updraftplus');
3033 }
3034 $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>';
3035 }
3036
3037 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>
3038 </tr>
3039
3040 <tr class="expertmode" style="display:none;">
3041 <th><?php _e('Use the server\'s SSL certificates','updraftplus');?>:</th>
3042 <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>
3043 </tr>
3044
3045 <tr class="expertmode" style="display:none;">
3046 <th><?php _e('Do not verify SSL certificates','updraftplus');?>:</th>
3047 <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>
3048 </tr>
3049
3050 <tr class="expertmode" style="display:none;">
3051 <th><?php _e('Disable SSL entirely where possible', 'updraftplus');?>:</th>
3052 <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>
3053 </tr>
3054
3055 <?php do_action('updraftplus_configprint_expertoptions'); ?>
3056
3057 <tr>
3058 <td></td>
3059 <td>
3060 <?php
3061 $ws_ad = $updraftplus->wordshell_random_advert(1);
3062 if ($ws_ad) {
3063 ?>
3064 <p style="margin: 10px 0; padding: 10px; font-size: 140%; background-color: lightYellow; border-color: #E6DB55; border: 1px solid; border-radius: 4px;">
3065 <?php echo $ws_ad; ?>
3066 </p>
3067 <?php
3068 }
3069 ?>
3070 </td>
3071 </tr>
3072 <tr>
3073 <td></td>
3074 <td>
3075 <input type="hidden" name="action" value="update" />
3076 <input type="submit" class="button-primary" value="<?php _e('Save Changes','updraftplus');?>" />
3077 </td>
3078 </tr>
3079 </table>
3080 <?php
3081 }
3082
3083 public function show_double_warning($text, $extraclass = '', $echo = true) {
3084
3085 $ret = "<div class=\"error updraftplusmethod $extraclass\"><p>$text</p></div>";
3086 $ret .= "<p style=\"border:1px solid; padding: 6px;\">$text</p>";
3087
3088 if ($echo) echo $ret;
3089 return $ret;
3090
3091 }
3092
3093 public function optionfilter_split_every($value) {
3094 $value = absint($value);
3095 if (!$value >= UPDRAFTPLUS_SPLIT_MIN) $value = UPDRAFTPLUS_SPLIT_MIN;
3096 return $value;
3097 }
3098
3099 public function curl_check($service, $has_fallback = false, $extraclass = '', $echo = true) {
3100
3101 $ret = '';
3102
3103 // Check requirements
3104 if (!function_exists("curl_init") || !function_exists('curl_exec')) {
3105
3106 $ret .= $this->show_double_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('Your web server\'s PHP installation does not included a <strong>required</strong> (for %s) module (%s). Please contact your web hosting provider\'s support and ask for them to enable it.', 'updraftplus'), $service, 'Curl').' '.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, false);
3107
3108 } else {
3109 $curl_version = curl_version();
3110 $curl_ssl_supported= ($curl_version['features'] & CURL_VERSION_SSL);
3111 if (!$curl_ssl_supported) {
3112 if ($has_fallback) {
3113 $ret .= '<p><strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__("Your web server's PHP/Curl installation does not support https access. Communications with %s will be unencrypted. ask your web host to install Curl/SSL in order to gain the ability for encryption (via an add-on).",'updraftplus'),$service).'</p>';
3114 } else {
3115 $ret .= $this->show_double_warning('<p><strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__("Your web server's PHP/Curl installation does not support https access. We cannot access %s without this support. Please contact your web hosting provider's support. %s <strong>requires</strong> Curl+https. Please do not file any support requests; there is no alternative.",'updraftplus'),$service).'</p>', $extraclass, false);
3116 }
3117 } else {
3118 $ret .= '<p><em>'.sprintf(__("Good news: Your site's communications with %s can be encrypted. If you see any errors to do with encryption, then look in the 'Expert Settings' for more help.", 'updraftplus'),$service).'</em></p>';
3119 }
3120 }
3121 if ($echo) {
3122 echo $ret;
3123 } else {
3124 return $ret;
3125 }
3126 }
3127
3128 # If $basedirs is passed as an array, then $directorieses must be too
3129 function recursive_directory_size($directorieses, $exclude = array(), $basedirs = '') {
3130
3131 $size = 0;
3132
3133 if (is_string($directorieses)) {
3134 $basedirs = $directorieses;
3135 $directorieses = array($directorieses);
3136 }
3137
3138 if (is_string($basedirs)) $basedirs = array($basedirs);
3139
3140 foreach ($basedirs as $ind => $basedir) {
3141
3142 $directories = $directorieses[$ind];
3143 if (!is_array($directories)) $directories=array($directories);
3144
3145 foreach ($directories as $dir) {
3146 if (is_file($dir)) {
3147 $size += @filesize($dir);
3148 } else {
3149 $suffix = ('' != $basedir) ? ((0 === strpos($dir, $basedir.'/')) ? substr($dir, 1+strlen($basedir)) : '') : '';
3150 $size += $this->recursive_directory_size_raw($basedir, $exclude, $suffix);
3151 }
3152 }
3153
3154 }
3155
3156 if ($size > 1073741824) {
3157 return round($size / 1073741824, 1).' Gb';
3158 } elseif ($size > 1048576) {
3159 return round($size / 1048576, 1).' Mb';
3160 } elseif ($size > 1024) {
3161 return round($size / 1024, 1).' Kb';
3162 } else {
3163 return round($size, 1).' b';
3164 }
3165
3166 }
3167
3168 function recursive_directory_size_raw($prefix_directory, &$exclude = array(), $suffix_directory = '') {
3169
3170 $directory = $prefix_directory.('' == $suffix_directory ? '' : '/'.$suffix_directory);
3171 $size = 0;
3172 if(substr($directory, -1) == '/') $directory = substr($directory,0,-1);
3173
3174 if(!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) return -1;
3175
3176 if($handle = opendir($directory)) {
3177 while (($file = readdir($handle)) !== false) {
3178 if ($file != '.' && $file != '..') {
3179 $spath = ('' == $suffix_directory) ? $file : $suffix_directory.'/'.$file;
3180 if (false !== ($fkey = array_search($spath, $exclude))) {
3181 unset($exclude[$fkey]);
3182 continue;
3183 }
3184 $path = $directory.'/'.$file;
3185 if(is_file($path)) {
3186 $size += filesize($path);
3187 } elseif(is_dir($path)) {
3188 $handlesize = $this->recursive_directory_size_raw($prefix_directory, $exclude, $suffix_directory.('' == $suffix_directory ? '' : '/').$file);
3189 if($handlesize >= 0) { $size += $handlesize; }# else { return -1; }
3190 }
3191 }
3192 }
3193 closedir($handle);
3194 }
3195
3196 return $size;
3197
3198 }
3199
3200 private function existing_backup_table($backup_history = false) {
3201
3202 global $updraftplus;
3203 $ret = '';
3204
3205 // Fetch it if it was not passed
3206 if (false === $backup_history) $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
3207 if (!is_array($backup_history)) $backup_history=array();
3208
3209 $updraft_dir = $updraftplus->backups_dir_location();
3210
3211 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
3212
3213 $ret .= '<table>';
3214
3215 $accept = apply_filters('updraftplus_accept_archivename', array());
3216 if (!is_array($accept)) $accept = array();
3217
3218 krsort($backup_history);
3219
3220 $nonce_field = wp_nonce_field('updraftplus_download', '_wpnonce', true, false);
3221
3222 if (empty($backup_history)) {
3223 $ret .= "<p><em>".__('You have not yet made any backups.', 'updraftplus')."</em></p>";
3224 }
3225
3226 foreach ($backup_history as $key=>$backup) {
3227 # https://core.trac.wordpress.org/ticket/25331
3228 # $pretty_date = date_i18n('Y-m-d G:i',$key);
3229 // Convert to blog time zone
3230 $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', (int)$key), 'Y-m-d G:i');
3231
3232 $esc_pretty_date = esc_attr($pretty_date);
3233 $entities = '';
3234 $sval = ((isset($backup['service']) && $backup['service'] != 'email' && $backup['service'] != 'none')) ? '1' : '0';
3235 $title = __('Delete this backup set', 'updraftplus');
3236 $non=$backup['nonce'];
3237 $ret .= <<<ENDHERE
3238 <tr id="updraft_existing_backups_row_$key">
3239 <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>
3240 ENDHERE;
3241
3242 $jobdata = $updraftplus->jobdata_getarray($non);
3243 if (is_array($jobdata) && !empty($jobdata['resume_interval']) && (empty($jobdata['jobstatus']) || 'finished' != $jobdata['jobstatus'])) {
3244 $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>';
3245 }
3246
3247 $ret .= "</td>\n";
3248
3249 if (empty($backup['meta_foreign']) || !empty($accept[$backup['meta_foreign']]['separatedb'])) {
3250 $ret .= "<td>";
3251 if (isset($backup['db'])) {
3252 $entities .= '/db=0/';
3253 $sdescrip = preg_replace('/ \(.*\)$/', '', __('Database','updraftplus'));
3254
3255
3256 if (isset($accept[$backup['meta_foreign']])) {
3257 $desc_source = $accept[$backup['meta_foreign']]['desc'];
3258 } else {
3259 $desc_source = __('unknown source', 'updraftplus');
3260 }
3261
3262 $dbt = empty($backup['meta_foreign']) ? __('Database','updraftplus') : sprintf(__('Database (created by %s)', 'updraftplus'), $desc_source);
3263
3264 $ret .= <<<ENDHERE
3265 <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">
3266 $nonce_field
3267 <input type="hidden" name="action" value="updraft_download_backup" />
3268 <input type="hidden" name="type" value="db" />
3269 <input type="hidden" name="timestamp" value="$key" />
3270 <input type="submit" value="$dbt" />
3271 </form>
3272 ENDHERE;
3273 } else {
3274 $ret .= sprintf(_x('(No %s)','Message shown when no such object is available','updraftplus'), __('database', 'updraftplus'));
3275 }
3276 # External databases
3277 foreach ($backup as $bkey => $binfo) {
3278 if ('db' == $bkey || 'db' != substr($bkey, 0, 2) || '-size' == substr($bkey, -5, 5)) continue;
3279 $dbt = __('External database','updraftplus').' ('.substr($bkey, 2).')';
3280 $ret .= <<<ENDHERE
3281 <form id="uddownloadform_${bkey}_${key}_0" action="admin-ajax.php" onsubmit="return updraft_downloader('uddlstatus_', $key, '$bkey', '#ud_downloadstatus', '0', '$esc_pretty_date', true)" method="post">
3282 $nonce_field
3283 <input type="hidden" name="action" value="updraft_download_backup" />
3284 <input type="hidden" name="type" value="$bkey" />
3285 <input type="hidden" name="timestamp" value="$key" />
3286 <input type="submit" value="$dbt" />
3287 </form>
3288 ENDHERE;
3289 }
3290 $ret .="</td>";
3291 } else {
3292 # Foreign without separate db
3293 $entities = '/db=0/meta_foreign=1/';
3294 }
3295
3296 if (!empty($backup['meta_foreign']) && !empty($accept[$backup['meta_foreign']]['separatedb'])) {
3297 $entities .= '/meta_foreign=2/';
3298 }
3299
3300 // Now go through each of the file entities
3301 foreach ($backupable_entities as $type => $info) {
3302 if (!empty($backup['meta_foreign']) && 'wpcore' != $type) continue;
3303 $colspan = 1;
3304 if (!empty($backup['meta_foreign'])) {
3305 $colspan = (1+count($backupable_entities));
3306 if (empty($accept[$backup['meta_foreign']]['separatedb'])) $colspan++;
3307 }
3308 $ret .= (1 == $colspan) ? '<td>' : '<td colspan="'.$colspan.'">';
3309 $ide = '';
3310 if ('wpcore' == $type) $wpcore_restore_descrip = $info['description'];
3311 if (empty($backup['meta_foreign'])) {
3312 $sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']);
3313 if (strlen($sdescrip) > 20 && isset($info['shortdescription'])) $sdescrip = $info['shortdescription'];
3314 } else {
3315 $info['description'] = 'WordPress';
3316
3317 if (isset($accept[$backup['meta_foreign']])) {
3318 $desc_source = $accept[$backup['meta_foreign']]['desc'];
3319 $ide .= sprintf(__('Backup created by: %s.', 'updraftplus'), $accept[$backup['meta_foreign']]['desc']).' ';
3320 } else {
3321 $desc_source = __('unknown source', 'updraftplus');
3322 $ide .= __('Backup created by unknown source (%s) - cannot be restored.', 'updraftplus').' ';
3323 }
3324
3325
3326 $sdescrip = (empty($accept[$backup['meta_foreign']]['separatedb'])) ? sprintf(__('Files and database WordPress backup (created by %s)', 'updraftplus'), $desc_source) : sprintf(__('Files backup (created by %s)', 'updraftplus'), $desc_source);
3327 if ('wpcore' == $type) $wpcore_restore_descrip = $sdescrip;
3328 }
3329 if (isset($backup[$type])) {
3330 if (!is_array($backup[$type])) $backup[$type]=array($backup[$type]);
3331 $howmanyinset = count($backup[$type]);
3332 $expected_index = 0;
3333 $index_missing = false;
3334 $set_contents = '';
3335 $entities .= "/$type=";
3336 $whatfiles = $backup[$type];
3337 ksort($whatfiles);
3338 foreach ($whatfiles as $findex => $bfile) {
3339 $set_contents .= ($set_contents == '') ? $findex : ",$findex";
3340 if ($findex != $expected_index) $index_missing = true;
3341 $expected_index++;
3342 }
3343 $entities .= $set_contents.'/';
3344 if (!empty($backup['meta_foreign'])) {
3345 $entities .= '/plugins=0//themes=0//uploads=0//others=0/';
3346 }
3347 $first_printed = true;
3348 foreach ($whatfiles as $findex => $bfile) {
3349 $ide .= __('Press here to download', 'updraftplus').' '.strtolower($info['description']);
3350 $pdescrip = ($findex > 0) ? $sdescrip.' ('.($findex+1).')' : $sdescrip;
3351 if (!$first_printed) {
3352 $ret .= '<div style="display:none;">';
3353 }
3354 if (count($backup[$type]) >0) {
3355 $ide .= ' '.sprintf(__('(%d archive(s) in set).', 'updraftplus'), $howmanyinset);
3356 }
3357 if ($index_missing) {
3358 $ide .= ' '.__('You appear to be missing one or more archives from this multi-archive set.', 'updraftplus');
3359 }
3360 $ret .= <<<ENDHERE
3361 <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">
3362 $nonce_field
3363 <input type="hidden" name="action" value="updraft_download_backup" />
3364 <input type="hidden" name="type" value="$type" />
3365 <input type="hidden" name="timestamp" value="$key" />
3366 <input type="hidden" name="findex" value="$findex" />
3367 <input type="submit" title="$ide" value="$pdescrip" />
3368 </form>
3369 ENDHERE;
3370 if (!$first_printed) {
3371 $ret .= '</div>';
3372 } else {
3373 $first_printed = false;
3374 }
3375 }
3376 } else {
3377 $ret .= sprintf(_x('(No %s)','Message shown when no such object is available','updraftplus'), preg_replace('/\s\(.{12,}\)/', '', strtolower($sdescrip)));
3378 }
3379 $ret .= '</td>';
3380 };
3381
3382 if (empty($backup['meta_foreign'])) {
3383 $ret .= '<td>';
3384 if (isset($backup['nonce']) && preg_match("/^[0-9a-f]{12}$/",$backup['nonce']) && is_readable($updraft_dir.'/log.'.$backup['nonce'].'.txt')) {
3385 $nval = $backup['nonce'];
3386 $lt = esc_attr(__('Backup Log','updraftplus'));
3387 $url = UpdraftPlus_Options::admin_page();
3388 $ret .= <<<ENDHERE
3389 <form action="$url" method="get">
3390 <input type="hidden" name="action" value="downloadlog" />
3391 <input type="hidden" name="page" value="updraftplus" />
3392 <input type="hidden" name="updraftplus_backup_nonce" value="$nval" />
3393 <input type="submit" value="$lt" />
3394 </form>
3395 ENDHERE;
3396 } else {
3397 $ret .= "(No&nbsp;backup&nbsp;log)";
3398 }
3399 $ret .= "</td>";
3400 }
3401
3402 $ret .= <<<ENDHERE
3403 <td>
3404 <form method="post" action="">
3405 <input type="hidden" name="backup_timestamp" value="$key">
3406 <input type="hidden" name="action" value="updraft_restore" />
3407 ENDHERE;
3408 if ($entities) {
3409 $show_data = $pretty_date;
3410 if (isset($backup['native']) && false == $backup['native']) {
3411 $show_data .= ' '.__('(backup set imported from remote storage)', 'updraftplus');
3412 }
3413 # jQuery('#updraft_restore_label_wpcore').html('".esc_js($wpcore_restore_descrip)."');
3414 $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');
3415 jQuery('#updraft_restore_timestamp').val('$key'); jQuery('.updraft_restore_date').html('$show_data'); ";
3416 $ret .= "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>';
3417 }
3418 $ret .= <<<ENDHERE
3419 </form>
3420 </td>
3421 </tr>
3422 ENDHERE;
3423 }
3424 $ret .= '</table>';
3425 return $ret;
3426 }
3427
3428 // 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').
3429 // If $remotescan is set, then remote storage is also scanned
3430 public function rebuild_backup_history($remotescan = false) {
3431
3432 global $updraftplus;
3433 $messages = array();
3434 $gmt_offset = get_option('gmt_offset');
3435
3436 $known_files = array();
3437 $known_nonces = array();
3438 $changes = false;
3439
3440 $backupable_entities = $updraftplus->get_backupable_file_entities(true, false);
3441
3442 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
3443 if (!is_array($backup_history)) $backup_history = array();
3444 $updraft_dir = $updraftplus->backups_dir_location();
3445 if (!is_dir($updraft_dir)) return;
3446
3447 $accept = apply_filters('updraftplus_accept_archivename', array());
3448 if (!is_array($accept)) $accept = array();
3449 // Accumulate a list of known files in the database backup history
3450 foreach ($backup_history as $btime => $bdata) {
3451 $found_file = false;
3452 foreach ($bdata as $key => $values) {
3453 if ('db' != $key && !isset($backupable_entities[$key])) continue;
3454 // Record which set this file is found in
3455 if (!is_array($values)) $values=array($values);
3456 foreach ($values as $val) {
3457 if (!is_string($val)) continue;
3458 if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+([0-9]+(of[0-9]+)?)?+\.(zip|gz|gz\.crypt)$/i', $val, $matches)) {
3459 $nonce = $matches[2];
3460 if (isset($bdata['service']) && ($bdata['service'] === 'none' || (is_array($bdata['service']) && array('none') === $bdata['service'])) && !is_file($updraft_dir.'/'.$val)) {
3461 # File without remote storage is no longer present
3462 } else {
3463 $found_file = true;
3464 $known_files[$val] = $nonce;
3465 $known_nonces[$nonce] = $btime;
3466 }
3467 } else {
3468 $accepted = false;
3469 foreach ($accept as $fkey => $acc) {
3470 if (preg_match('/'.$acc['pattern'].'/i', $val)) $accepted = $fkey;
3471 }
3472 if (!empty($accepted) && (false != ($btime = apply_filters('updraftplus_foreign_gettime', false, $fkey, $val))) && $btime > 0) {
3473 $found_file = true;
3474 $nonce = substr(md5($val), 0, 12);
3475 $known_files[$val] = $nonce;
3476 $known_nonces[$nonce] = $btime;
3477 }
3478 }
3479 }
3480 }
3481 if (!$found_file) {
3482 # File recorded as being without remote storage is no longer present - though it may in fact exist in remote storage, and this will be picked up later
3483 unset($backup_history[$btime]);
3484 $changes = true;
3485 }
3486 }
3487
3488 $remotefiles = array();
3489 $remotesizes = array();
3490 # Scan remote storage and get back lists of files and their sizes
3491 if ($remotescan) {
3492 foreach ($updraftplus->backup_methods as $method => $desc) {
3493 require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
3494 $objname = 'UpdraftPlus_BackupModule_'.$method;
3495 $obj = new $objname;
3496 if (!method_exists($obj, 'listfiles')) continue;
3497 $files = $obj->listfiles('backup_');
3498 if (is_array($files)) {
3499 foreach ($files as $entry) {
3500 $n = $entry['name'];
3501 if (!preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)([0-9]+(of[0-9]+)?)?\.(zip|gz|gz\.crypt)$/i', $n, $matches)) continue;
3502 if (isset($remotefiles[$n])) {
3503 $remotefiles[$n][] = $method;
3504 } else {
3505 $remotefiles[$n] = array($method);
3506 }
3507 if (!empty($entry['size'])) {
3508 if (empty($remotesizes[$n]) || $remotesizes[$n] < $entry['size']) $remotesizes[$n] = $entry['size'];
3509 }
3510 }
3511 } elseif (is_wp_error($files)) {
3512 foreach ($files->get_error_codes() as $code) {
3513 if ('no_settings' == $code || 'no_addon' == $code || 'insufficient_php' == $code) continue;
3514 $messages[] = array(
3515 'method' => $method,
3516 'desc' => $desc,
3517 'code' => $code,
3518 'message' => $files->get_error_message($code)
3519 );
3520 }
3521 }
3522 }
3523 }
3524
3525 if (!$handle = opendir($updraft_dir)) return;
3526
3527 // See if there are any more files in the local directory than the ones already known about
3528 while (false !== ($entry = readdir($handle))) {
3529 $accepted_foreign = false;
3530 $potmessage = false;
3531 if ('.' == $entry || '..' == $entry) continue;
3532 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)) {
3533
3534 // Interpret the time as one from the blog's local timezone, rather than as UTC
3535 # $matches[1] is YYYY-MM-DD-HHmm, to be interpreted as being the local timezone
3536 $btime2 = strtotime($matches[1]);
3537 $btime = (!empty($offset)) ? $btime2 - $gmt_offset*3600 : $btime2;
3538
3539 $nonce = $matches[2];
3540 $type = $matches[3];
3541 if ('db' == $type) {
3542 $type .= $matches[4];
3543 $index = 0;
3544 } else {
3545 $index = (empty($matches[4])) ? '0' : (max((int)$matches[4]-1,0));
3546 }
3547 $itext = ($index == 0) ? '' : $index;
3548 } elseif (false != ($accepted_foreign = apply_filters('updraftplus_accept_foreign', false, $entry)) && false != ($btime = apply_filters('updraftplus_foreign_gettime', false, $accepted_foreign, $entry))) {
3549 $nonce = substr(md5($entry), 0, 12);
3550 $type = preg_match('/\.sql(\.(bz2|gz))?$/', $entry) ? 'db' : 'wpcore';
3551 $index = '0';
3552 $itext = '';
3553 $potmessage = array(
3554 'code' => 'foundforeign_'.md5($entry),
3555 'desc' => $entry,
3556 'method' => '',
3557 'message' => sprintf(__('Backup created by: %s.', 'updraftplus'), $accept[$accepted_foreign]['desc'])
3558 );
3559 } elseif ('.zip' == substr($entry, -4, 4) || preg_match('/\.sql(\.(bz2|gz))?$/', $entry)) {
3560 $potmessage = array(
3561 'code' => 'possibleforeign_'.md5($entry),
3562 'desc' => $entry,
3563 'method' => '',
3564 'message' => __('This file does not appear to be an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)).', 'updraftplus').' <a href="http://updraftplus.com/shop/updraftplus-premium/">'.__('If this is a backup created by a different backup plugin, then UpdraftPlus Premium may be able to help you.', 'updraftplus').'</a>'
3565 );
3566 $messages[$potmessage['code']] = $potmessage;
3567 continue;
3568 } else {
3569 continue;
3570 }
3571 // The time from the filename does not include seconds. Need to identify the seconds to get the right time
3572 if (isset($known_nonces[$nonce])) $btime = $known_nonces[$nonce];
3573 if ($btime <= 100) continue;
3574 $fs = @filesize($updraft_dir.'/'.$entry);
3575
3576 if (!isset($known_files[$entry])) {
3577 $changes = true;
3578 if (is_array($potmessage)) $messages[$potmessage['code']] = $potmessage;
3579 }
3580
3581 # Make sure we have the right list of services
3582 $current_services = (!empty($backup_history[$btime]) && !empty($backup_history[$btime]['service'])) ? $backup_history[$btime]['service'] : array();
3583 if (is_string($current_services)) $current_services = array($current_services);
3584 if (!is_array($current_services)) $current_services = array();
3585 if (!empty($remotefiles[$entry])) {
3586 if (0 == count(array_diff($current_services, $remotefiles[$entry]))) {
3587 $backup_history[$btime]['service'] = $remotefiles[$entry];
3588 $changes = true;
3589 }
3590 # Get the right size (our local copy may be too small)
3591 foreach ($remotefiles[$entry] as $rem) {
3592 if (!empty($rem['size']) && $rem['size'] > $fs) {
3593 $fs = $rem['size'];
3594 $changes = true;
3595 }
3596 }
3597 # Remove from $remotefiles, so that we can later see what was left over
3598 unset($remotefiles[$entry]);
3599 } else {
3600 # Not known remotely
3601 if (!empty($backup_history[$btime])) {
3602 if (empty($backup_history[$btime]['service']) || ('none' !== $backup_history[$btime]['service'] && '' !== $backup_history[$btime]['service'] && array('none') !== $backup_history[$btime]['service'])) {
3603 $backup_history[$btime]['service'] = 'none';
3604 $changes = true;
3605 }
3606 } else {
3607 $backup_history[$btime]['service'] = 'none';
3608 $changes = true;
3609 }
3610 }
3611
3612 $backup_history[$btime][$type][$index] = $entry;
3613 if ($fs > 0) $backup_history[$btime][$type.$itext.'-size'] = $fs;
3614 $backup_history[$btime]['nonce'] = $nonce;
3615 if (!empty($accepted_foreign)) $backup_history[$btime]['meta_foreign'] = $accepted_foreign;
3616 }
3617
3618 # Any found in remote storage that we did not previously know about?
3619 # Compare $remotefiles with $known_files / $known_nonces, and adjust $backup_history
3620 if (count($remotefiles) > 0) {
3621
3622 # $backup_history[$btime]['nonce'] = $nonce
3623 foreach ($remotefiles as $file => $services) {
3624 if (!preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)([0-9]+(of[0-9]+)?)?\.(zip|gz|gz\.crypt)$/i', $file, $matches)) continue;
3625 $nonce = $matches[2];
3626 $type = $matches[3];
3627 if ('db' == $type) {
3628 $index = 0;
3629 $type .= $matches[4];
3630 } else {
3631 $index = (empty($matches[4])) ? '0' : (max((int)$matches[4]-1,0));
3632 }
3633 $itext = ($index == 0) ? '' : $index;
3634 $btime2 = strtotime($matches[1]);
3635 $btime = (!empty($offset)) ? $btime2 - $gmt_offset*3600 : $btime2;
3636
3637 if (isset($known_nonces[$nonce])) $btime = $known_nonces[$nonce];
3638 if ($btime <= 100) continue;
3639 # Remember that at this point, we already know that the file is not known about locally
3640 if (isset($backup_history[$btime])) {
3641 if (!isset($backup_history[$btime]['service']) || ((is_array($backup_history[$btime]['service']) && $backup_history[$btime]['service'] !== $services) || is_string($backup_history[$btime]['service']) && (1 != count($services) || $services[0] !== $backup_history[$btime]['service']))) {
3642 $changes = true;
3643 $backup_history[$btime]['service'] = $services;
3644 $backup_history[$btime]['nonce'] = $nonce;
3645 }
3646 if (!isset($backup_history[$btime][$type][$index])) {
3647 $changes = true;
3648 $backup_history[$btime][$type][$index] = $file;
3649 $backup_history[$btime]['nonce'] = $nonce;
3650 if (!empty($remotesizes[$file])) $backup_history[$btime][$type.$itext.'-size'] = $remotesizes[$file];
3651 }
3652 } else {
3653 $changes = true;
3654 $backup_history[$btime]['service'] = $services;
3655 $backup_history[$btime][$type][$index] = $file;
3656 $backup_history[$btime]['nonce'] = $nonce;
3657 if (!empty($remotesizes[$file])) $backup_history[$btime][$type.$itext.'-size'] = $remotesizes[$file];
3658 $backup_history[$btime]['native'] = false;
3659 $messages['nonnative'] = array(
3660 'message' => __('One or more backups has been added from scanning remote storage; note that these backups will not be automatically deleted through the "retain" settings; if/when you wish to delete them then you must do so manually.', 'updraftplus'),
3661 'code' => 'nonnative',
3662 'desc' => '',
3663 'method' => ''
3664 );
3665 }
3666
3667 }
3668 }
3669
3670 if ($changes) UpdraftPlus_Options::update_updraft_option('updraft_backup_history', $backup_history);
3671
3672 return $messages;
3673
3674 }
3675
3676 // Return values: false = 'not yet' (not necessarily terminal); WP_Error = terminal failure; true = success
3677 function restore_backup($timestamp) {
3678
3679 @set_time_limit(900);
3680
3681 global $wp_filesystem, $updraftplus;
3682 $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
3683 if(!is_array($backup_history[$timestamp])) {
3684 echo '<p>'.__('This backup does not exist in the backup history - restoration aborted. Timestamp:','updraftplus')." $timestamp</p><br/>";
3685 return new WP_Error('does_not_exist', __('Backup does not exist in the backup history', 'updraftplus'));
3686 }
3687
3688 // request_filesystem_credentials passes on fields just via hidden name/value pairs.
3689 // Build array of parameters to be passed via this
3690 $extra_fields = array();
3691 if (isset($_POST['updraft_restore']) && is_array($_POST['updraft_restore'])) {
3692 foreach ($_POST['updraft_restore'] as $entity) {
3693 $_POST['updraft_restore_'.$entity] = 1;
3694 $extra_fields[] = 'updraft_restore_'.$entity;
3695 }
3696 }
3697 // Now make sure that updraft_restorer_ option fields get passed along to request_filesystem_credentials
3698 foreach ($_POST as $key => $value) {
3699 if (0 === strpos($key, 'updraft_restorer_')) $extra_fields[] = $key;
3700 }
3701
3702 $credentials = request_filesystem_credentials(UpdraftPlus_Options::admin_page()."?page=updraftplus&action=updraft_restore&backup_timestamp=$timestamp", '', false, false, $extra_fields);
3703 WP_Filesystem($credentials);
3704 if ( $wp_filesystem->errors->get_error_code() ) {
3705 foreach ( $wp_filesystem->errors->get_error_messages() as $message ) show_message($message);
3706 exit;
3707 }
3708
3709 # Set up logging
3710 $updraftplus->backup_time_nonce();
3711 $updraftplus->jobdata_set('job_type', 'restore');
3712 $updraftplus->jobdata_set('job_time_ms', $updraftplus->job_time_ms);
3713 $updraftplus->logfile_open($updraftplus->nonce);
3714
3715 # Provide download link for the log file
3716
3717 #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>';
3718
3719 # TODO: Automatic purging of old log files
3720 # TODO: Provide option to auto-email the log file
3721
3722 //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?)
3723 echo '<h1>'.__('UpdraftPlus Restoration: Progress', 'updraftplus').'</h1><div id="updraft-restore-progress">';
3724
3725 $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>');
3726
3727 $updraft_dir = trailingslashit($updraftplus->backups_dir_location());
3728 $foreign_known = apply_filters('updraftplus_accept_archivename', array());
3729
3730 $service = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
3731 if (!is_array($service)) $service = array($service);
3732
3733 // 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)
3734 if (empty($_POST['updraft_restore']) || (!is_array($_POST['updraft_restore']))) $_POST['updraft_restore'] = array();
3735
3736 $backup_set = $backup_history[$timestamp];
3737 $entities_to_restore = array();
3738 foreach ($_POST['updraft_restore'] as $entity) {
3739 if (empty($backup_set['meta_foreign'])) {
3740 $entities_to_restore[$entity] = $entity;
3741 } else {
3742 if ('db' == $entity && !empty($foreign_known[$backup_set['meta_foreign']]['separatedb'])) {
3743 $entities_to_restore[$entity] = 'db';
3744 } else {
3745 $entities_to_restore[$entity] = 'wpcore';
3746 }
3747 }
3748 }
3749
3750 foreach ($_POST as $key => $value) {
3751 if (0 === strpos($key, 'updraft_restore_')) {
3752 $nkey = substr($key, 16);
3753 if (!isset($entities_to_restore[$nkey])) {
3754 $_POST['updraft_restore'][] = $nkey;
3755 if (empty($backup_set['meta_foreign'])) {
3756 $entities_to_restore[$nkey] = $nkey;
3757 } else {
3758 if ('db' == $entity && !empty($foreign_known[$backup_set['meta_foreign']]['separatedb'])) {
3759 $entities_to_restore[$nkey] = 'db';
3760 } else {
3761 $entities_to_restore[$nkey] = 'wpcore';
3762 }
3763 }
3764 }
3765 }
3766 }
3767
3768 if (0 == count($_POST['updraft_restore'])) {
3769 echo '<p>'.__('ABORT: Could not find the information on which entities to restore.', 'updraftplus').'</p>';
3770 echo '<p>'.__('If making a request for support, please include this information:','updraftplus').' '.count($_POST).' : '.htmlspecialchars(serialize($_POST)).'</p>';
3771 return new WP_Error('missing_info', 'Backup information not found');
3772 }
3773
3774 $updraftplus->log("Restore job started. Entities to restore: ".implode(', ', array_flip($entities_to_restore)));
3775
3776 set_error_handler(array($updraftplus, 'php_error'), E_ALL & ~E_STRICT);
3777
3778 /*
3779 $_POST['updraft_restore'] is typically something like: array( 0=>'db', 1=>'plugins', 2=>'themes'), etc.
3780 i.e. array ( 'db', 'plugins', themes')
3781 */
3782
3783 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
3784
3785 uksort($backup_set, array($this, 'sort_restoration_entities'));
3786
3787 // We use a single object for each entity, because we want to store information about the backup set
3788 require_once(UPDRAFTPLUS_DIR.'/restorer.php');
3789
3790 global $updraftplus_restorer;
3791 $updraftplus_restorer = new Updraft_Restorer(new Updraft_Restorer_Skin, $backup_set);
3792
3793 $second_loop = array();
3794
3795 echo "<h2>".__('Final checks', 'updraftplus').'</h2>';
3796
3797 if (empty($backup_set['meta_foreign'])) {
3798 $entities_to_download = $entities_to_restore;
3799 } else {
3800 if (!empty($foreign_known[$backup_set['meta_foreign']]['separatedb'])) {
3801 $entities_to_download = array();
3802 if (in_array('db', $entities_to_restore)) {
3803 $entities_to_download['db'] = 1;
3804 }
3805 if (count($entities_to_restore) > 1 || !in_array('db', $entities_to_restore)) {
3806 $entities_to_download['wpcore'] = 1;
3807 }
3808 } else {
3809 $entities_to_download = array('wpcore' => 1);
3810 }
3811 }
3812
3813 // First loop: make sure that files are present + readable; and populate array for second loop
3814 foreach ($backup_set as $type => $files) {
3815 // All restorable entities must be given explicitly, as we can store other arbitrary data in the history array
3816 if (!isset($backupable_entities[$type]) && 'db' != $type) continue;
3817 if (isset($backupable_entities[$type]['restorable']) && $backupable_entities[$type]['restorable'] == false) continue;
3818
3819 if (!isset($entities_to_download[$type])) continue;
3820 if ('wpcore' == $type && is_multisite() && 0 === $updraftplus_restorer->ud_backup_is_multisite) {
3821 echo "<p>$type: <strong>";
3822 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');
3823 #TODO
3824 #$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.');
3825 echo "</strong></p>";
3826 continue;
3827 }
3828
3829 if (is_string($files)) $files=array($files);
3830
3831 foreach ($files as $ind => $file) {
3832 $fullpath = $updraft_dir.$file;
3833 echo sprintf(__("Looking for %s archive: file name: %s", 'updraftplus'), $type, htmlspecialchars($file))."<br>";
3834
3835 foreach ($service as $serv) {
3836 if(!is_readable($fullpath)) {
3837 $sd = (empty($updraftplus->backup_methods[$serv])) ? $serv : $updraftplus->backup_methods[$serv];
3838 echo __("File is not locally present - needs retrieving from remote storage",'updraftplus')." ($sd)";
3839 $this->download_file($file, $serv);
3840 echo ": ";
3841 if (!is_readable($fullpath)) {
3842 echo __("Error", 'updraftplus');
3843 } else {
3844 echo __("OK", 'updraftplus');
3845 }
3846 echo '<br>';
3847 }
3848 }
3849
3850 $index = ($ind == 0) ? '' : $ind;
3851 // If a file size is stored in the backup data, then verify correctness of the local file
3852 if (isset($backup_history[$timestamp][$type.$index.'-size'])) {
3853 $fs = $backup_history[$timestamp][$type.$index.'-size'];
3854 echo __("Archive is expected to be size:",'updraftplus')." ".round($fs/1024, 1)." Kb: ";
3855 $as = @filesize($fullpath);
3856 if ($as == $fs) {
3857 echo __('OK','updraftplus').'<br>';
3858 } else {
3859 echo "<strong>".__('Error:','updraftplus')."</strong> ".__('file is size:', 'updraftplus')." ".round($as/1024)." ($fs, $as)<br>";
3860 }
3861 } else {
3862 echo __("The backup records do not contain information about the proper size of this file.",'updraftplus')."<br>";
3863 }
3864 if (!is_readable($fullpath)) {
3865 echo __('Could not find one of the files for restoration', 'updraftplus')." ($file)<br>";
3866 $updraftplus->log("$file: ".__('Could not find one of the files for restoration', 'updraftplus'), 'error');
3867 echo '</div>';
3868 restore_error_handler();
3869 return false;
3870 }
3871 }
3872
3873 if (empty($updraftplus_restorer->ud_foreign)) {
3874 $types = array($type);
3875 } else {
3876 if ('db' != $type || empty($foreign_known[$updraftplus_restorer->ud_foreign]['separatedb'])) {
3877 $types = array('wpcore');
3878 } else {
3879 $types = array('db');
3880 }
3881 }
3882
3883 foreach ($types as $check_type) {
3884 $info = (isset($backupable_entities[$check_type])) ? $backupable_entities[$check_type] : array();
3885 $val = $updraftplus_restorer->pre_restore_backup($files, $check_type, $info);
3886 if (is_wp_error($val)) {
3887 $updraftplus->log_wp_error($val);
3888 foreach ($val->get_error_messages() as $msg) {
3889 echo '<strong>'.__('Error:', 'updraftplus').'</strong> '.htmlspecialchars($msg).'<br>';
3890 }
3891 foreach ($val->get_error_codes() as $code) {
3892 if ('already_exists' == $code) $this->print_delete_old_dirs_form(false);
3893 }
3894 echo '</div>'; //close the updraft_restore_progress div even if we error
3895 restore_error_handler();
3896 return $val;
3897 } elseif (false === $val) {
3898 echo '</div>'; //close the updraft_restore_progress div even if we error
3899 restore_error_handler();
3900 return false;
3901 }
3902 }
3903
3904 foreach ($entities_to_restore as $entity => $via) {
3905 if ($via == $type) $second_loop[$entity] = $files;
3906 }
3907
3908 }
3909
3910 $updraftplus_restorer->delete = (UpdraftPlus_Options::get_updraft_option('updraft_delete_local')) ? true : false;
3911 if ('none' === $service || 'email' === $service || empty($service) || (is_array($service) && 1 == count($service) && (in_array('none', $service) || in_array('', $service) || in_array('email', $service))) || !empty($updraftplus_restorer->ud_foreign)) {
3912 if ($updraftplus_restorer->delete) $updraftplus->log_e('Will not delete any archives after unpacking them, because there was no cloud storage for this backup');
3913 $updraftplus_restorer->delete = false;
3914 }
3915
3916 if (!empty($updraftplus_restorer->ud_foreign)) $updraftplus->log("Foreign backup; created by: ".$updraftplus_restorer->ud_foreign);
3917
3918 // Second loop: now actually do the restoration
3919 uksort($second_loop, array($this, 'sort_restoration_entities'));
3920 foreach ($second_loop as $type => $files) {
3921 # Types: uploads, themes, plugins, others, db
3922 $info = (isset($backupable_entities[$type])) ? $backupable_entities[$type] : array();
3923
3924 echo ('db' == $type) ? "<h2>".__('Database','updraftplus')."</h2>" : "<h2>".$info['description']."</h2>";
3925 $updraftplus->log("Entity: ".$type);
3926
3927 if (is_string($files)) $files = array($files);
3928 foreach ($files as $fkey => $file) {
3929 $last_one = (1 == count($second_loop) && 1 == count($files));
3930 $val = $updraftplus_restorer->restore_backup($file, $type, $info, $last_one);
3931
3932 if(is_wp_error($val)) {
3933 $updraftplus->log_e($val);
3934 foreach ($val->get_error_messages() as $msg) {
3935 echo '<strong>'.__('Error message', 'updraftplus').':</strong> '.htmlspecialchars($msg).'<br>';
3936 }
3937 $codes = $val->get_error_codes();
3938 if (is_array($codes)) {
3939 foreach ($codes as $code) {
3940 $data = $val->get_error_data($code);
3941 if (!empty($data)) {
3942 $pdata = (is_string($data)) ? $data : serialize($data);
3943 echo '<strong>'.__('Error data:', 'updraftplus').'</strong> '.htmlspecialchars($pdata).'<br>';
3944 }
3945 }
3946 }
3947 echo '</div>'; //close the updraft_restore_progress div even if we error
3948 if (false !== strpos($val->get_error_data(), 'PCLZIP_ERR_BAD_FORMAT (-10)')) {
3949 echo '<a href="http://updraftplus.com/faqs/error-message-pclzip_err_bad_format-10-invalid-archive-structure-mean/"><strong>'.__('Please consult this FAQ for help on what to do about it.', 'updraftplus').'</strong></a><br>';
3950 }
3951 restore_error_handler();
3952 return $val;
3953 } elseif (false === $val) {
3954 echo '</div>'; //close the updraft_restore_progress div even if we error
3955 restore_error_handler();
3956 return false;
3957 }
3958 unset($files[$fkey]);
3959 }
3960 unset($second_loop[$type]);
3961 }
3962
3963 foreach (array('template', 'stylesheet', 'template_root', 'stylesheet_root') as $opt) {
3964 add_filter('pre_option_'.$opt, array($this, 'option_filter_'.$opt));
3965 }
3966 if (!function_exists('validate_current_theme')) require_once(ABSPATH.'wp-includes/themes');
3967
3968 # Have seen a case where the current theme in the DB began with a capital, but not on disk - and this breaks migrating from Windows to a case-sensitive system
3969 $template = get_option('template');
3970 if (!empty($template) && $template != WP_DEFAULT_THEME && $template != strtolower($template)) {
3971
3972 $theme_root = get_theme_root($template);
3973 $theme_root2 = get_theme_root(strtolower($template));
3974
3975 if (!file_exists("$theme_root/$template/style.css") && file_exists("$theme_root/".strtolower($template)."/style.css")) {
3976 $updraftplus->log_e("Theme directory (%s) not found, but lower-case version exists; updating database option accordingly", $template);
3977 update_option('template', strtolower($template));
3978 }
3979
3980 }
3981
3982
3983 if (!validate_current_theme()) {
3984 global $updraftplus;
3985 echo '<strong>';
3986 $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");
3987 echo '</strong>';
3988 }
3989 #foreach (array('template', 'stylesheet', 'template_root', 'stylesheet_root') as $opt) {
3990 # remove_filter('pre_option_'.$opt, array($this, 'option_filter_'.$opt));
3991 #}
3992
3993 echo '</div>'; //close the updraft_restore_progress div
3994
3995 restore_error_handler();
3996 return true;
3997 }
3998
3999 public function option_filter_template($val) { global $updraftplus; return $updraftplus->option_filter_get('template'); }
4000
4001 public function option_filter_stylesheet($val) { global $updraftplus; return $updraftplus->option_filter_get('stylesheet'); }
4002
4003 public function option_filter_template_root($val) { global $updraftplus; return $updraftplus->option_filter_get('template_root'); }
4004
4005 public function option_filter_stylesheet_root($val) { global $updraftplus; return $updraftplus->option_filter_get('stylesheet_root'); }
4006
4007 function sort_restoration_entities($a, $b) {
4008 if ($a == $b) return 0;
4009 # Put the database first
4010 # Put wpcore after plugins/uploads/themes (needed for restores of foreign all-in-one formats)
4011 if ('db' == $a || 'wpcore' == $b) return -1;
4012 if ('db' == $b || 'wpcore' == $a) return 1;
4013 # After wpcore, next last is others
4014 if ('others' == $b) return -1;
4015 if ('others' == $a) return 1;
4016 return strcmp($a, $b);
4017 }
4018
4019 public function return_array($input) {
4020 if (!is_array($input)) $input = array();
4021 return $input;
4022 }
4023
4024 # TODO: Remove legacy storage setting keys from here
4025 private function get_settings_keys() {
4026 return array('updraft_autobackup_default', 'updraft_dropbox', 'updraft_googledrive', 'updraftplus_tmp_googledrive_access_token', 'updraftplus_dismissedautobackup', 'updraftplus_dismissedexpiry', 'updraft_interval', 'updraft_interval_increments', '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',
4027 'updraft_lastmessage', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder',
4028 '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_openstack', 'updraft_bitcasa', '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', 'updraft_extradatabases');
4029 }
4030
4031 }
4032