PluginProbe ʕ •ᴥ•ʔ
UpdraftPlus: WP Backup & Migration Plugin / 1.15.0
UpdraftPlus: WP Backup & Migration Plugin v1.15.0
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 / includes / class-wpadmin-commands.php
updraftplus / includes Last commit date
Dropbox2 7 years ago Google 8 years ago cloudfiles 12 years ago handlebars 7 years ago images 9 years ago jquery.serializeJSON 8 years ago jstree 8 years ago labelauty 7 years ago tether 7 years ago tether-shepherd 7 years ago updraftclone 7 years ago S3.php 8 years ago S3compat.php 8 years ago cacert.pem 8 years ago class-backup-history.php 7 years ago class-commands.php 7 years ago class-database-utility.php 8 years ago class-manipulation-functions.php 7 years ago class-partialfileservlet.php 9 years ago class-remote-send.php 7 years ago class-semaphore.php 8 years ago class-udrpc.php 8 years ago class-updraft-dashboard-news.php 7 years ago class-updraftcentral-updraftplus-commands.php 8 years ago class-updraftplus-encryption.php 7 years ago class-wpadmin-commands.php 7 years ago class-zip.php 7 years ago deprecated-actions.php 8 years ago ftp.class.php 8 years ago get-cpanel-quota-usage.pl 12 years ago google-extensions.php 9 years ago jquery-ui.custom.css 7 years ago jquery-ui.custom.min.css 7 years ago jquery-ui.custom.min.css.map 7 years ago jquery.blockUI.js 8 years ago jquery.blockUI.min.js 8 years ago updraft-notices.php 8 years ago updraft-restorer-skin.php 7 years ago updraftcentral.php 7 years ago updraftplus-admin-common.js 7 years ago updraftplus-admin-common.min.js 7 years ago updraftplus-clone.php 7 years ago updraftplus-login.php 8 years ago updraftplus-notices.php 8 years ago updraftplus-tour.php 7 years ago updraftvault.php 8 years ago
class-wpadmin-commands.php
727 lines
1 <?php
2
3 if (!defined('UPDRAFTPLUS_DIR')) die('No access.');
4
5 /*
6 See class-commands.php for explanation about how these classes work.
7 */
8
9 if (!class_exists('UpdraftPlus_Commands')) require_once(UPDRAFTPLUS_DIR.'/includes/class-commands.php');
10
11 /**
12 * An extension, because commands available via wp-admin are a super-set of those which are available through all mechanisms
13 */
14 class UpdraftPlus_WPAdmin_Commands extends UpdraftPlus_Commands {
15
16 private $_uc_helper;
17
18 private $_updraftplus_admin;
19
20 private $_updraftplus;
21
22 /**
23 * Constructor
24 *
25 * @param string $uc_helper The 'helper' needs to provide the method _updraftplus_background_operation_started
26 */
27 public function __construct($uc_helper) {
28 $this->_uc_helper = $uc_helper;
29 global $updraftplus_admin, $updraftplus;
30 $this->_updraftplus_admin = $updraftplus_admin;
31 $this->_updraftplus = $updraftplus;
32 parent::__construct($uc_helper);
33 }
34
35 /**
36 * Forces a resumption of a backup where the resumption is overdue (so apparently cron is not working)
37 *
38 * @param Array $info - keys 'job_id' and 'resumption'
39 *
40 * @return Array - if there is an error. Otherwise, dies.
41 */
42 public function forcescheduledresumption($info) {
43
44 // Casting $resumption to int is absolutely necessary, as the WP cron system uses a hashed serialisation of the parameters for identifying jobs. Different type => different hash => does not match
45 $resumption = (int) $info['resumption'];
46 $job_id = $info['job_id'];
47 $get_cron = $this->_updraftplus_admin->get_cron($job_id);
48 if (!is_array($get_cron)) {
49 return array('r' => false);
50 } else {
51 $this->_updraftplus->log("Forcing resumption: job id=$job_id, resumption=$resumption");
52 $time = $get_cron[0];
53 wp_clear_scheduled_hook('updraft_backup_resume', array($resumption, $job_id));
54 $this->_updraftplus->close_browser_connection(json_encode(array('r' => true)));
55 $this->_updraftplus->jobdata_set_from_array($get_cron[1]);
56 $this->_updraftplus->backup_resume($resumption, $job_id);
57 // We don't want to return. The close_browser_connection call already returned a result.
58 die;
59 }
60 }
61
62 /**
63 * Calls a WordPress action and dies
64 *
65 * @param Array $data - must have at least the key 'wpaction' with a string value
66 *
67 * @return WP_Error if no command was included
68 */
69 public function call_wordpress_action($data) {
70
71 if (empty($data['wpaction'])) return new WP_Error('error', '', 'no command sent');
72
73 $response = $this->_updraftplus_admin->call_wp_action($data, array($this->_uc_helper, '_updraftplus_background_operation_started'));
74
75 die;
76
77 // return array('response' => $response['response'], 'status' => $response['status'], 'log' => $response['log'] );
78 }
79
80 public function updraftcentral_delete_key($params) {
81
82 global $updraftplus_updraftcentral_main;
83 if (!is_a($updraftplus_updraftcentral_main, 'UpdraftPlus_UpdraftCentral_Main')) {
84 return array('error' => 'UpdraftPlus_UpdraftCentral_Main object not found');
85 }
86
87 return $updraftplus_updraftcentral_main->delete_key($params['key_id']);
88
89 }
90
91 public function updraftcentral_get_log($params) {
92 global $updraftplus_updraftcentral_main;
93 if (!is_a($updraftplus_updraftcentral_main, 'UpdraftPlus_UpdraftCentral_Main')) {
94 return array('error' => 'UpdraftPlus_UpdraftCentral_Main object not found');
95 }
96 return call_user_func(array($updraftplus_updraftcentral_main, 'get_log'), $params);
97 }
98
99 public function updraftcentral_create_key($params) {
100 global $updraftplus_updraftcentral_main;
101 if (!is_a($updraftplus_updraftcentral_main, 'UpdraftPlus_UpdraftCentral_Main')) {
102 return array('error' => 'UpdraftPlus_UpdraftCentral_Main object not found');
103 }
104 return call_user_func(array($updraftplus_updraftcentral_main, 'create_key'), $params);
105 }
106
107 public function restore_alldownloaded($params) {
108
109 $backups = UpdraftPlus_Backup_History::get_history();
110 $updraft_dir = $this->_updraftplus->backups_dir_location();
111
112 $timestamp = (int) $params['timestamp'];
113 if (!isset($backups[$timestamp])) {
114 return array('m' => '', 'w' => '', 'e' => __('No such backup set exists', 'updraftplus'));
115 }
116
117 $mess = array();
118 parse_str(stripslashes($params['restoreopts']), $res);
119
120 if (isset($res['updraft_restore'])) {
121
122 set_error_handler(array($this->_updraftplus_admin, 'get_php_errors'), E_ALL & ~E_STRICT);
123
124 $elements = array_flip($res['updraft_restore']);
125
126 $warn = array();
127 $err = array();
128
129 @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
130 $max_execution_time = (int) @ini_get('max_execution_time');
131
132 if ($max_execution_time>0 && $max_execution_time<61) {
133 $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);
134 }
135
136 if (isset($backups[$timestamp]['native']) && false == $backups[$timestamp]['native']) {
137 $warn[] = __('This backup set was not known by UpdraftPlus to be created by the current WordPress installation, but was either found in remote storage, or was sent from a remote site.', 'updraftplus').' '.__('You should make sure that this really is a backup set intended for use on this website, before you restore (rather than a backup set of an unrelated website).', 'updraftplus');
138 }
139
140 if (isset($elements['db'])) {
141
142 // Analyse the header of the database file + display results
143 list ($mess2, $warn2, $err2, $info) = $this->_updraftplus->analyse_db_file($timestamp, $res);
144 $mess = array_merge($mess, $mess2);
145 $warn = array_merge($warn, $warn2);
146 $err = array_merge($err, $err2);
147 foreach ($backups[$timestamp] as $bid => $bval) {
148 if ('db' != $bid && 'db' == substr($bid, 0, 2) && '-size' != substr($bid, -5, 5)) {
149 $warn[] = __('Only the WordPress database can be restored; you will need to deal with the external database manually.', 'updraftplus');
150 break;
151 }
152 }
153 }
154
155 $backupable_entities = $this->_updraftplus->get_backupable_file_entities(true, true);
156 $backupable_plus_db = $backupable_entities;
157 $backupable_plus_db['db'] = array('path' => 'path-unused', 'description' => __('Database', 'updraftplus'));
158
159 if (!empty($backups[$timestamp]['meta_foreign'])) {
160 $foreign_known = apply_filters('updraftplus_accept_archivename', array());
161 if (!is_array($foreign_known) || empty($foreign_known[$backups[$timestamp]['meta_foreign']])) {
162 $err[] = sprintf(__('Backup created by unknown source (%s) - cannot be restored.', 'updraftplus'), $backups[$timestamp]['meta_foreign']);
163 } else {
164 // For some reason, on PHP 5.5 passing by reference in a single array stopped working with apply_filters_ref_array (though not with do_action_ref_array).
165 $backupable_plus_db = apply_filters_ref_array("updraftplus_importforeign_backupable_plus_db", array($backupable_plus_db, array($foreign_known[$backups[$timestamp]['meta_foreign']], &$mess, &$warn, &$err)));
166 }
167 }
168
169 foreach ($backupable_plus_db as $type => $entity_info) {
170 if (!isset($elements[$type]) || (isset($entity_info['restorable']) && !$entity_info['restorable'])) continue;
171 $whatwegot = $backups[$timestamp][$type];
172 if (is_string($whatwegot)) $whatwegot = array($whatwegot);
173 $expected_index = 0;
174 $missing = '';
175 ksort($whatwegot);
176 $outof = false;
177 foreach ($whatwegot as $index => $file) {
178 if (preg_match('/\d+of(\d+)\.zip/', $file, $omatch)) {
179 $outof = max($matches[1], 1);
180 }
181 while ($expected_index < $index) {
182 $missing .= ('' == $missing) ? (1+$expected_index) : ",".(1+$expected_index);
183 $expected_index++;
184 }
185 if (!file_exists($updraft_dir.'/'.$file)) {
186 $err[] = sprintf(__('File not found (you need to upload it): %s', 'updraftplus'), $updraft_dir.'/'.$file);
187 } elseif (filesize($updraft_dir.'/'.$file) == 0) {
188 $err[] = sprintf(__('File was found, but is zero-sized (you need to re-upload it): %s', 'updraftplus'), $file);
189 } else {
190 $itext = (0 == $index) ? '' : $index;
191 if (!empty($backups[$timestamp][$type.$itext.'-size']) && filesize($updraft_dir.'/'.$file) != $backups[$timestamp][$type.$itext.'-size']) {
192 if (empty($warn['doublecompressfixed'])) {
193 $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']);
194 }
195 }
196 do_action_ref_array("updraftplus_checkzip_$type", array($updraft_dir.'/'.$file, &$mess, &$warn, &$err));
197 }
198 $expected_index++;
199 }
200 do_action_ref_array("updraftplus_checkzip_end_$type", array(&$mess, &$warn, &$err));
201 // Detect missing archives where they are missing from the end of the set
202 if ($outof>0 && $expected_index < $outof) {
203 for ($j = $expected_index; $j<$outof; $j++) {
204 $missing .= ('' == $missing) ? (1+$j) : ",".(1+$j);
205 }
206 }
207 if ('' != $missing) {
208 $warn[] = sprintf(__("This multi-archive backup set appears to have the following archives missing: %s", 'updraftplus'), $missing.' ('.$entity_info['description'].')');
209 }
210 }
211
212 // Check this backup set has a incremental_sets array e.g may have been created before this array was introduced
213 if (isset($backups[$timestamp]['incremental_sets'])) {
214 $incremental_sets = array_keys($backups[$timestamp]['incremental_sets']);
215 // Check if there are more than one timestamp in the incremental set
216 if (1 < count($incremental_sets)) {
217 $incremental_select_html = '<label>'.__('Select your incremental restore point', 'updraftplus').': </label>';
218 $incremental_select_html .= '<select name="updraft_incremental_restore_point" id="updraft_incremental_restore_point">';
219 $first_timestamp = $incremental_sets[0];
220
221 foreach ($incremental_sets as $timestamp) {
222 $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', (int) $timestamp), 'M d, Y G:i');
223 $esc_pretty_date = esc_attr($pretty_date);
224 $incremental_select_html .= '<option value="'.$timestamp.'" '.selected($timestamp, $first_timestamp, false).'>'.$esc_pretty_date.'</option>';
225 }
226
227 $incremental_select_html .= '</select>';
228 $info['addui'] = empty($info['addui']) ? $incremental_select_html : $info['addui'].'<br>'.$incremental_select_html;
229 }
230 }
231
232 if (0 == count($err) && 0 == count($warn)) {
233 $mess_first = __('The backup archive files have been successfully processed. Now press Restore again to proceed.', 'updraftplus');
234 } elseif (0 == count($err)) {
235 $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');
236 } else {
237 $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');
238 }
239
240 if (count($this->_updraftplus_admin->logged) >0) {
241 foreach ($this->_updraftplus_admin->logged as $lwarn) $warn[] = $lwarn;
242 }
243 restore_error_handler();
244
245 // Get the info if it hasn't already come from the DB scan
246 if (!isset($info) || !is_array($info)) $info = array();
247
248 // Not all characters can be json-encoded, and we don't need this potentially-arbitrary user-supplied info.
249 unset($info['label']);
250
251 if (!isset($info['created_by_version']) && !empty($backups[$timestamp]['created_by_version'])) $info['created_by_version'] = $backups[$timestamp]['created_by_version'];
252
253 if (!isset($info['multisite']) && !empty($backups[$timestamp]['is_multisite'])) $info['multisite'] = $backups[$timestamp]['is_multisite'];
254
255 do_action_ref_array('updraftplus_restore_all_downloaded_postscan', array($backups, $timestamp, $elements, &$info, &$mess, &$warn, &$err));
256
257 $warn_result = '';
258 foreach ($warn as $warning) {
259 if (!$warn_result) $warn_result = '<ul id="updraft_restore_warnings">';
260 $warn_result .= '<li>'.$warning.'</li>';
261 }
262 if ($warn_result) $warn_result .= '</ul>';
263
264 return array('m' => '<p>'.$mess_first.'</p>'.implode('<br>', $mess), 'w' => $warn_result, 'e' => implode('<br>', $err), 'i' => json_encode($info));
265 }
266
267 }
268
269 /**
270 * 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
271 *
272 * @return string
273 */
274 public function ping() {
275 return 'pong';
276 }
277
278 public function dismissautobackup() {
279 UpdraftPlus_Options::update_updraft_option('updraftplus_dismissedautobackup', time() + 84*86400);
280 return array();
281 }
282
283 public function dismiss_notice() {
284 UpdraftPlus_Options::update_updraft_option('dismissed_general_notices_until', time() + 84*86400);
285 return array();
286 }
287
288 public function dismiss_season() {
289 UpdraftPlus_Options::update_updraft_option('dismissed_season_notices_until', time() + 366*86400);
290 return array();
291 }
292
293 public function set_autobackup_default($params) {
294 $default = empty($params['default']) ? 0 : 1;
295 UpdraftPlus_Options::update_updraft_option('updraft_autobackup_default', $default);
296 return array();
297 }
298
299 public function dismissexpiry() {
300 UpdraftPlus_Options::update_updraft_option('updraftplus_dismissedexpiry', time() + 14*86400);
301 return array();
302 }
303
304 public function dismissdashnotice() {
305 UpdraftPlus_Options::update_updraft_option('updraftplus_dismisseddashnotice', time() + 366*86400);
306 return array();
307 }
308
309 public function rawbackuphistory() {
310 // This is used for iframe source; hence, returns a string
311 $show_raw_data = $this->_updraftplus_admin->show_raw_backups();
312 return $show_raw_data['html'];
313 }
314
315 /**
316 * N.B. Not exactly the same as the phpinfo method in the UpdraftCentral core class
317 * Returns a string, as it is directly fetched as the source of an iframe
318 *
319 * @return String - returns the resulting HTML
320 */
321 public function phpinfo() {
322
323 ob_start();
324
325 phpinfo(INFO_ALL ^ (INFO_CREDITS | INFO_LICENSE));
326
327 echo '<h3 id="ud-debuginfo-constants">'.__('Constants', 'updraftplus').'</h3>';
328 $opts = @get_defined_constants();
329 ksort($opts);
330 echo '<table><thead></thead><tbody>';
331 foreach ($opts as $key => $opt) {
332 // Administrators can already read these in other ways, but we err on the side of caution
333 if (false !== stripos($opt, 'api_key')) $opt = '***';
334 echo '<tr><td>'.htmlspecialchars($key).'</td><td>'.htmlspecialchars(print_r($opt, true)).'</td>';
335 }
336 echo '</tbody></table>';
337
338 $ret = ob_get_contents();
339 ob_end_clean();
340
341 return $ret;
342
343 }
344
345 /**
346 * Return a message if there are more than 4 overdue cron jobs
347 *
348 * @return Array - the message, if there is one, is in the key 'm'
349 */
350 public function check_overdue_crons() {
351 $how_many_overdue = $this->_updraftplus_admin->howmany_overdue_crons();
352 return ($how_many_overdue >= 4) ? array('m' => $this->_updraftplus_admin->show_admin_warning_overdue_crons($how_many_overdue)) : array();
353 }
354
355 public function whichdownloadsneeded($params) {
356 // The purpose of this is to look at the list of indicated downloads, and indicate which are not already fully downloaded. i.e. Which need further action.
357 $send_back = array();
358
359 $backup = UpdraftPlus_Backup_History::get_history($params['timestamp']);
360 $updraft_dir = $this->_updraftplus->backups_dir_location();
361 $backupable_entities = $this->_updraftplus->get_backupable_file_entities();
362
363 if (empty($backup)) return array('result' => 'asyouwere');
364
365 foreach ($params['downloads'] as $i => $download) {
366 if (is_array($download) && 2 == count($download) && isset($download[0]) && isset($download[1])) {
367 $entity = $download[0];
368 if (('db' == $entity || isset($backupable_entities[$entity])) && isset($backup[$entity])) {
369 $indexes = explode(',', $download[1]);
370 $retain_string = '';
371 foreach ($indexes as $index) {
372 $retain = true; // default
373 $findex = (0 == $index) ? '' : (string) $index;
374 $files = $backup[$entity];
375 if (!is_array($files)) $files = array($files);
376 $size_key = $entity.$findex.'-size';
377 if (isset($files[$index]) && isset($backup[$size_key])) {
378 $file = $updraft_dir.'/'.$files[$index];
379 if (file_exists($file) && filesize($file) >= $backup[$size_key]) {
380 $retain = false;
381 }
382 }
383 if ($retain) {
384 $retain_string .= ('' === $retain_string) ? $index : ','.$index;
385 $send_back[$i][0] = $entity;
386 $send_back[$i][1] = $retain_string;
387 }
388 }
389 } else {
390 $send_back[$i][0] = $entity;
391 $send_back[$i][1] = $download[$i][1];
392 }
393 } else {
394 // Format not understood. Just send it back as-is.
395 $send_back[$i] = $download[$i];
396 }
397 }
398 // Finally, renumber the keys (to usual PHP style - 0, 1, ...). Otherwise, in order to preserve the indexes, json_encode() will create an object instead of an array in the case where $send_back only has one element (and is indexed with an index > 0)
399 $send_back = array_values($send_back);
400 return array('downloads' => $send_back);
401 }
402
403 /**
404 * This is an handler function that checks what entity has been specified in the $params and calls the required method
405 *
406 * @param [array] $params this is an array of parameters sent via ajax it can include various things depending on what has called this method, this method only cares about the entity parameter which is used to call the correct method and return tree nodes based on that
407 * @return [array] returns an array of jstree nodes
408 */
409 public function get_jstree_directory_nodes($params) {
410
411 if ('filebrowser' == $params['entity']) {
412 $node_array = $this->_updraft_jstree_directory($params);
413 } elseif ('zipbrowser' == $params['entity']) {
414 $node_array = $this->_updraft_jstree_zip($params);
415 }
416 return empty($node_array['error']) ? array('nodes' => $node_array) : $node_array;
417 }
418
419 /**
420 * This creates an array of nodes, built from either ABSPATH or the given directory ready to be returned to the jstree object.
421 *
422 * @param [array] $params this is an array of parameters sent via ajax it can include the following:
423 * node - this is a jstree node object containing information about the selected node
424 * path - this is a path if provided this will be used to build the tree otherwise ABSPATH is used
425 * drop_directory - this is a boolean that if set to true will drop one directory level off the path this is used so that you can move above the current root directory
426 * @return [array] returns an array of jstree nodes
427 */
428 private function _updraft_jstree_directory($params) {
429 $node_array = array();
430
431 // # is the root node if it's the root node then this is the first call so create a parent node otherwise it's a child node and we should get the path from the node id
432 if ('#' == $params['node']['id']) {
433 $path = ABSPATH;
434
435 if (!empty($params['path'])) $path = $params['path'];
436
437 if (!empty($params['drop_directory']) && true == $params['drop_directory']) $path = dirname($path);
438
439 $node_array[] = array(
440 'text' => basename($path),
441 'children' => true,
442 'id' => $path,
443 'icon' => 'jstree-folder',
444 'state' => array(
445 'opened' => true
446 )
447 );
448 } else {
449 $path = $params['node']['id'];
450 }
451
452 if ($dh = opendir($path)) {
453 $path = rtrim($path, DIRECTORY_SEPARATOR);
454
455 $skip_paths = array(".", "..");
456
457 while (($value = readdir($dh)) !== false) {
458 if (!in_array($value, $skip_paths)) {
459 if (is_dir($path . DIRECTORY_SEPARATOR . $value)) {
460 $node_array[] = array(
461 'text' => $value,
462 'children' => true,
463 'id' => $path . DIRECTORY_SEPARATOR . $value,
464 'icon' => 'jstree-folder'
465 );
466 } else {
467 $node_array[] = array(
468 'text' => $value,
469 'children' => false,
470 'id' => $path . DIRECTORY_SEPARATOR . $value,
471 'type' => 'file',
472 'icon' => 'jstree-file'
473 );
474 }
475 }
476 }
477 }
478
479 return $node_array;
480 }
481
482 /**
483 * This creates an array of nodes, built from a unzipped zip file structure.
484 *
485 * @param [array] $params this is an array of parameters sent via ajax it can include the following:
486 * node - this is a jstree node object containing information about the selected node
487 * timestamp - this is the backup timestamp and is used to get the backup archive
488 * type - this is the type of backup and is used to get the backup archive
489 * findex - this is the index used to get the correct backup archive if theres more than one of a single archive type
490 * @return [array] returns an array of jstree nodes
491 */
492 private function _updraft_jstree_zip($params) {
493
494 $updraftplus = $this->_updraftplus;
495
496 $node_array = array();
497
498 include_once(UPDRAFTPLUS_DIR.'/includes/class-zip.php');
499
500 $zip_object = 'UpdraftPlus_ZipArchive';
501
502 // In tests, PclZip was found to be 25% slower than ZipArchive
503 if (((defined('UPDRAFTPLUS_PREFERPCLZIP') && UPDRAFTPLUS_PREFERPCLZIP == true) || !class_exists('ZipArchive') || !class_exists('UpdraftPlus_ZipArchive') || (!extension_loaded('zip') && !method_exists('ZipArchive', 'AddFile')))) {
504 $zip_object = 'UpdraftPlus_PclZip';
505 }
506
507 // Retrieve the information from our backup history
508 $backup_history = UpdraftPlus_Backup_History::get_history();
509
510 if (!isset($backup_history[$params['timestamp']][$params['type']])) {
511 return array('error' => __('Backup set not found', 'updraftplus'));
512 }
513
514 // Base name
515 $file = $backup_history[$params['timestamp']][$params['type']];
516
517 // Get date in human readable form
518 $pretty_date = get_date_from_gmt(gmdate('Y-m-d H:i:s', (int) $params['timestamp']), 'M d, Y G:i');
519
520 $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
521
522 // Check the file type and set the name in a more friendly way
523 $archive_name = isset($backupable_entities[$params['type']]['description']) ? $backupable_entities[$params['type']]['description'] : $params['type'];
524
525 if (substr($params['type'], 0, 2) === 'db') $archive_name = __('Extra database', 'updraftplus') . ' ' . substr($params['type'], 3, 1);
526 if ('db' == $params['type']) $archive_name = __('Database', 'updraftplus');
527 if ('more' == $params['type']) $archive_name = $backupable_entities[$params['type']]['shortdescription'];
528 if ('wpcore' == $params['type']) $archive_name = __('WordPress Core', 'updraftplus');
529
530 $archive_set = ($params['findex'] + 1) . '/' . sizeof($file);
531
532 if ('1/1' == $archive_set) $archive_set = '';
533
534 $parent_name = $archive_name . ' ' . __('archive', 'updraftplus') . ' ' . $archive_set . ' ' . $pretty_date;
535
536 // Deal with multi-archive sets
537 if (is_array($file)) $file = $file[$params['findex']];
538
539 // Where it should end up being downloaded to
540 $fullpath = $updraftplus->backups_dir_location().'/'.$file;
541
542 if (file_exists($fullpath) && is_readable($fullpath) && filesize($fullpath)>0) {
543
544 $node_array[] = array(
545 'text' => $parent_name,
546 'parent' => '#',
547 'id' => $parent_name,
548 'icon' => 'jstree-folder',
549 'state' => array('opened' => true),
550 'li_attr' => array('path' => $parent_name)
551 );
552
553 $zip = new $zip_object;
554
555 $zip_opened = $zip->open($fullpath);
556
557 if (true !== $zip_opened) {
558 return array('error' => 'UpdraftPlus: opening zip (' . $fullpath . '): failed to open this zip file (object='.$zip_object.', code: '.$zip_opened.')');
559 } else {
560 if ('UpdraftPlus_PclZip' == $zip_object) {
561 $numfiles = $zip->numAll;
562 if (false === $numfiles) {
563 return array('error' => 'UpdraftPlus: reading zip: '.$zip->last_error);
564 }
565 } else {
566 $numfiles = $zip->numFiles;
567 }
568
569 for ($i=0; $i < $numfiles; $i++) {
570 $si = $zip->statIndex($i);
571
572 // Fix for windows being unable to build jstree due to different directory separators being used
573 $si['name'] = str_replace("/", DIRECTORY_SEPARATOR, $si['name']);
574
575 // if it's a dot then we don't want to append this as it will break the id's and the tree structure
576 if ('.' == dirname($si['name'])) {
577 $node_id = $parent_name;
578 } else {
579 $node_id = $parent_name . DIRECTORY_SEPARATOR . dirname($si['name']) . DIRECTORY_SEPARATOR;
580 }
581
582 $extension = substr(strrchr($si['name'], "."), 1);
583
584 if (0 == $si['size'] && empty($extension)) {
585 $node_array[] = array(
586 'text' => basename($si['name']),
587 'parent' => $node_id,
588 'id' => $parent_name . DIRECTORY_SEPARATOR . $si['name'],
589 'icon' => 'jstree-folder',
590 'li_attr' => array(
591 'path' => $parent_name . DIRECTORY_SEPARATOR . $si['name']
592 )
593 );
594 } else {
595 $node_array[] = array(
596 'text' => basename($si['name']),
597 'parent' => $node_id,
598 'id' => $parent_name . DIRECTORY_SEPARATOR . $si['name'],
599 'type' => 'file',
600 'icon' => 'jstree-file',
601 'li_attr' => array(
602 'path' => $parent_name . DIRECTORY_SEPARATOR . $si['name'],
603 'size' => UpdraftPlus_Manipulation_Functions::convert_numeric_size_to_text($si['size'])
604 )
605 );
606 }
607 }
608
609 // check if this is an upload archive if it is add a 'uploads' folder so that the children can attach to it
610 if ('uploads' == $params['type']) $node_array[] = array(
611 'text' => 'uploads',
612 'parent' => $parent_name,
613 'id' => $parent_name . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR,
614 'icon' => 'jstree-folder',
615 'li_attr' => array(
616 'path' => $parent_name . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR
617 )
618 );
619
620 @$zip->close();
621 }
622 }
623
624 return $node_array;
625 }
626
627 /**
628 * Return information on the zipfile download
629 *
630 * @param Array $params - details on the download; keys: type, findex, path, timestamp
631 *
632 * @return Array
633 */
634 public function get_zipfile_download($params) {
635 return apply_filters('updraftplus_command_get_zipfile_download', array('error' => 'UpdraftPlus: command (get_zipfile_download) not installed (are you missing an add-on?)'), $params);
636 }
637
638 /**
639 * Dismiss the notice which will if .htaccess have any old migrated site reference.
640 *
641 * @return Boolean Return true if migration notice is dismissed
642 */
643 public function dismiss_migration_notice_for_old_site_reference() {
644 delete_site_option('updraftplus_migrated_site_domain');
645 return true;
646 }
647
648 /**
649 * When character set and collate both are unsupported at restoration time and if user change anyone substitution dropdown from both, Other substitution select box value should be change respectively. To achieve this functionality, Ajax calls comes here.
650 *
651 * @param Array $params this is an array of parameters sent via ajax it can include the following:
652 * collate_change_on_charset_selection_data - It is data in serialize form which is need for choose other dropdown option value. It contains below elemts data:
653 * db_supported_collations - All collations supported by current database. This is result of 'SHOW COLLATION' query
654 * db_unsupported_collate_unique - Unsupported collates unique array
655 * db_collates_found - All collates found in database backup file
656 * event_source_elem - Dropdown elemtn id which trigger the ajax request
657 * updraft_restorer_charset - Charset dropdown selected value option
658 * updraft_restorer_collate - Collate dropdown selected value option
659 *
660 * @return array - $action_data which contains following data:
661 * is_action_required - 1 or 0 Whether or not change other dropdown value
662 * elem_id - Dropdown element id which value need to change. The other dropdown element id
663 * elem_val - Dropdown element value which should be selected for other drodown
664 */
665 public function collate_change_on_charset_selection($params) {
666 global $updraftplus;
667 $collate_change_on_charset_selection_data = json_decode(UpdraftPlus_Manipulation_Functions::wp_unslash($params['collate_change_on_charset_selection_data']), true);
668 $updraft_restorer_collate = $params['updraft_restorer_collate'];
669 $updraft_restorer_charset = $params['updraft_restorer_charset'];
670
671 $db_supported_collations = $collate_change_on_charset_selection_data['db_supported_collations'];
672 $db_unsupported_collate_unique = $collate_change_on_charset_selection_data['db_unsupported_collate_unique'];
673 $db_collates_found = $collate_change_on_charset_selection_data['db_collates_found'];
674
675 $action_data = array(
676 'is_action_required' => 0,
677 );
678 // No need to change other dropdown value
679 if (isset($db_supported_collations[$updraft_restorer_collate]->Charset) && $updraft_restorer_charset == $db_supported_collations[$updraft_restorer_collate]->Charset) {
680 return $action_data;
681 }
682 $similar_type_collate = $this->_updraftplus->get_similar_collate_related_to_charset($db_supported_collations, $db_unsupported_collate_unique, $updraft_restorer_charset);
683 if (empty($similar_type_collate)) {
684 $similar_type_collate = $this->_updraftplus->get_similar_collate_based_on_ocuurence_count($db_collates_found, $db_supported_collations, $db_supported_charsets_related_to_unsupported_collations = array($updraft_restorer_collate));
685 }
686 // Default collation for changed charcter set
687 if (empty($similar_type_collate)) {
688 $charset_row = $GLOBALS['wpdb']->get_row($GLOBALS['wpdb']->prepare("SHOW CHARACTER SET LIKE '%s'", $updraft_restorer_charset));
689 if (null !== $charset_row && !empty($charset_row->{'Default collation'})) {
690 $similar_type_collate = $charset_row->{'Default collation'};
691 }
692 }
693 if (empty($similar_type_collate)) {
694 foreach ($db_supported_collations as $db_supported_collation => $db_supported_collation_info) {
695 if (isset($db_supported_collation_info->Charset) && $updraft_restorer_charset == $db_supported_collation_info->Charset) {
696 $similar_type_collate = $db_supported_collation;
697 break;
698 }
699 }
700 }
701 if (!empty($similar_type_collate)) {
702 $action_data['is_action_required'] = 1;
703 $action_data['similar_type_collate'] = $similar_type_collate;
704 }
705 return $action_data;
706 }
707
708 /**
709 * Set the Tour status
710 *
711 * @param array $params - the $_REQUEST. We're looking for 'current_step'
712 * @return bool
713 */
714 public function set_tour_status($params) {
715 return UpdraftPlus_Tour::get_instance()->set_tour_status($params);
716 }
717
718 /**
719 * Resets the tour status
720 *
721 * @return bool
722 */
723 public function reset_tour_status() {
724 return UpdraftPlus_Tour::get_instance()->reset_tour_status();
725 }
726 }
727