Version Description
2014/09/17 =
FEATURE: Copy (https://copy.com) cloud storage support (Premium - http://updraftplus.com/shop/updraftplus-premium/)
FEATURE: The search/replace expert tool can now work on selected tables only
PERFORMANCE: Use PageVisibility API to be more intelligent about when we need to poll for progress in the dashboard
FIX: The Migrator add-on would fetch more database rows than it should, increasing the (low) risk of hitting memory limits, and increasing the time needed on enormous sites
FIX: Some Google Drive backups could get uploaded twice, if you were using multiple storage backends
FIX: If user set the option to not verify SSL certificates, then this option was not honoured for all methods
FIX: If user had never saved their settings (and hence using no cloud backup), then old backup sets were not pruned
TWEAK: Inform the user of possible plugin compatibility issues if they are about to restore a site onto a webserver running a PHP major version older than the original backup.
TWEAK: Detect database disconnection when search/replacing, and reconnect if possible; and to try less rows in case it was a memory limit
TWEAK: Allow wildcards at either end in exclusion items (e.g. backups)
TWEAK: Add option to control how many rows are search/replaced at once
TWEAK: Prevent PHP notice being generated on first Google Drive authentication
TWEAK: Update Bitcasa console link to new location
TRANSLATIONS: New Portuguese (Portugal) translation (pt_PT) - thanks to Pedro Mendona
TRANSLATIONS: Updated translations for Dutch, Italian, Swedish, Russian, Czech, Greek, Portuguese (Brazilian)
Release Info
Developer | DavidAnderson |
Plugin | UpdraftPlus WordPress Backup Plugin |
Version | 1.9.25 |
Comparing to | |
See all releases |
Code changes from version 1.9.17 to 1.9.25
- admin.php +135 -60
- backup.php +81 -63
- class-updraftplus.php +2494 -0
- class-zip.php +2 -2
- images/{copy.png → copycom.png} +0 -0
- includes/Google/IO/Abstract.php +23 -6
- includes/Google/IO/Curl.php +8 -7
- includes/Google/IO/Stream.php +5 -4
- includes/S3.php +44 -30
- includes/cacert.pem +1 -1
- includes/updraft-admin-ui.js +41 -5
- languages/updraftplus-cs_CZ.mo +0 -0
- languages/updraftplus-cs_CZ.po +995 -920
- languages/updraftplus-de_DE.mo +0 -0
- languages/updraftplus-de_DE.po +759 -737
- languages/updraftplus-el.mo +0 -0
- languages/updraftplus-el.po +995 -920
- languages/updraftplus-es_ES.mo +0 -0
- languages/updraftplus-es_ES.po +759 -737
- languages/updraftplus-fr_FR.mo +0 -0
- languages/updraftplus-fr_FR.po +631 -385
@@ -2,9 +2,7 @@
|
|
2 |
|
3 |
if (!defined ('ABSPATH')) die('No direct access allowed');
|
4 |
|
5 |
-
//
|
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();
|
@@ -45,25 +43,29 @@ class UpdraftPlus_Admin {
|
|
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()
|
54 |
-
$
|
55 |
-
|
56 |
-
|
|
|
|
|
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 |
|
@@ -172,7 +174,7 @@ class UpdraftPlus_Admin {
|
|
172 |
|
173 |
public function core_upgrade_preamble() {
|
174 |
if (!class_exists('UpdraftPlus_Addon_Autobackup')) {
|
175 |
-
if (defined('
|
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);
|
@@ -378,7 +380,7 @@ class UpdraftPlus_Admin {
|
|
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('
|
382 |
|
383 |
# TODO: Remove legacy/erroneous use of transient any time after 1 Jun 2014
|
384 |
$dismissed = get_transient('updraftplus_dismissedautobackup');
|
@@ -421,7 +423,7 @@ class UpdraftPlus_Admin {
|
|
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 "Backup Now") 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() {
|
@@ -455,6 +457,10 @@ class UpdraftPlus_Admin {
|
|
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 |
}
|
@@ -570,6 +576,7 @@ class UpdraftPlus_Admin {
|
|
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);
|
@@ -583,6 +590,7 @@ class UpdraftPlus_Admin {
|
|
583 |
$updraftplus->log('Remote fetch failed');
|
584 |
}
|
585 |
}
|
|
|
586 |
}
|
587 |
|
588 |
// Now, spool the thing to the browser
|
@@ -922,6 +930,7 @@ class UpdraftPlus_Admin {
|
|
922 |
|
923 |
$local_deleted = 0;
|
924 |
$remote_deleted = 0;
|
|
|
925 |
foreach ($files_to_delete as $key => $files) {
|
926 |
# Local deletion
|
927 |
if (is_string($files)) $files=array($files);
|
@@ -951,6 +960,7 @@ class UpdraftPlus_Admin {
|
|
951 |
}
|
952 |
}
|
953 |
}
|
|
|
954 |
$message .= __('The backup set has been removed.', 'updraftplus')."\n";
|
955 |
$message .= sprintf(__('Local archives deleted: %d', 'updraftplus'),$local_deleted)."\n";
|
956 |
$message .= sprintf(__('Remote archives deleted: %d', 'updraftplus'),$remote_deleted)."\n";
|
@@ -1034,11 +1044,11 @@ class UpdraftPlus_Admin {
|
|
1034 |
} elseif ('doaction' == $_REQUEST['subaction'] && !empty($_REQUEST['subsubaction']) && 'updraft_' == substr($_REQUEST['subsubaction'], 0, 8)) {
|
1035 |
do_action($_REQUEST['subsubaction']);
|
1036 |
} elseif ('backupnow' == $_REQUEST['subaction']) {
|
|
|
1037 |
$backupnow_nocloud = (empty($_REQUEST['backupnow_nocloud'])) ? false : true;
|
1038 |
$event = (!empty($_REQUEST['backupnow_nofiles'])) ? 'updraft_backupnow_backup_database' : ((!empty($_REQUEST['backupnow_nodb'])) ? 'updraft_backupnow_backup' : 'updraft_backupnow_backup_all');
|
1039 |
|
1040 |
-
$msg = '<strong>'.__('
|
1041 |
-
$updraftplus->log("A backup run has been started");
|
1042 |
$this->close_browser_connection($msg);
|
1043 |
do_action($event, $backupnow_nocloud);
|
1044 |
|
@@ -1123,6 +1133,7 @@ class UpdraftPlus_Admin {
|
|
1123 |
$objname = "UpdraftPlus_BackupModule_$method";
|
1124 |
|
1125 |
$this->logged = array();
|
|
|
1126 |
set_error_handler(array($this, 'get_php_errors'), E_ALL & ~E_STRICT);
|
1127 |
if (method_exists($objname, "credentials_test")) {
|
1128 |
$obj = new $objname;
|
@@ -1165,7 +1176,7 @@ class UpdraftPlus_Admin {
|
|
1165 |
return true;
|
1166 |
}
|
1167 |
|
1168 |
-
function download_status($timestamp, $type, $findex) {
|
1169 |
|
1170 |
global $updraftplus;
|
1171 |
|
@@ -1282,6 +1293,7 @@ class UpdraftPlus_Admin {
|
|
1282 |
$old_siteinfo = array();
|
1283 |
$gathering_siteinfo = true;
|
1284 |
$old_wp_version = '';
|
|
|
1285 |
|
1286 |
$tables_found = array();
|
1287 |
|
@@ -1317,13 +1329,21 @@ class UpdraftPlus_Admin {
|
|
1317 |
$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);
|
1318 |
if (!empty($powarn)) $warn[] = $powarn;
|
1319 |
}
|
1320 |
-
} elseif ('' == $old_wp_version && preg_match('/^\# WordPress Version: ([0-9]+(\.[0-9]+)+)(-[-a-z0-9]+,)
|
1321 |
$old_wp_version = $matches[1];
|
1322 |
if (!empty($matches[3])) $old_wp_version .= substr($matches[3], 0, strlen($matches[3])-1);
|
1323 |
if (version_compare($old_wp_version, $wp_version, '>')) {
|
1324 |
//$mess[] = sprintf(__('%s version: %s', 'updraftplus'), 'WordPress', $old_wp_version);
|
1325 |
$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);
|
1326 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1327 |
} elseif ('' == $old_table_prefix && (preg_match('/^\# Table prefix: (\S+)$/', $buffer, $matches) || preg_match('/^-- Table prefix: (\S+)$/i', $buffer, $matches))) {
|
1328 |
$old_table_prefix = $matches[1];
|
1329 |
// echo '<strong>'.__('Old table prefix:', 'updraftplus').'</strong> '.htmlspecialchars($old_table_prefix).'<br>';
|
@@ -1500,6 +1520,7 @@ CREATE TABLE $wpdb->signups (
|
|
1500 |
global $updraftplus;
|
1501 |
@set_time_limit(900);
|
1502 |
|
|
|
1503 |
check_ajax_referer('updraft-uploader');
|
1504 |
|
1505 |
$updraft_dir = $updraftplus->backups_dir_location();
|
@@ -1518,9 +1539,7 @@ CREATE TABLE $wpdb->signups (
|
|
1518 |
$farray['ext'] = 'x-gzip';
|
1519 |
$farray['type'] = 'application/octet-stream';
|
1520 |
|
1521 |
-
if (isset($_POST['chunks'])) {
|
1522 |
-
|
1523 |
-
} else {
|
1524 |
$farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
|
1525 |
}
|
1526 |
|
@@ -1539,7 +1558,11 @@ CREATE TABLE $wpdb->signups (
|
|
1539 |
// If this was the chunk, then we should instead be concatenating onto the final file
|
1540 |
if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
|
1541 |
$final_file = basename($_POST['name']);
|
1542 |
-
rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp')
|
|
|
|
|
|
|
|
|
1543 |
$status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
|
1544 |
|
1545 |
// Final chunk? If so, then stich it all back together
|
@@ -1611,7 +1634,7 @@ CREATE TABLE $wpdb->signups (
|
|
1611 |
@set_time_limit(900);
|
1612 |
global $updraftplus;
|
1613 |
|
1614 |
-
|
1615 |
check_ajax_referer('updraft-uploader');
|
1616 |
|
1617 |
$updraft_dir = $updraftplus->backups_dir_location();
|
@@ -1782,7 +1805,8 @@ CREATE TABLE $wpdb->signups (
|
|
1782 |
<div class="wrap" id="updraft-wrap">
|
1783 |
<h1><?php echo $updraftplus->plugin_title; ?></h1>
|
1784 |
|
1785 |
-
<a href="http://updraftplus.com">UpdraftPlus.Com</a> | <a href="
|
|
|
1786 |
<br>
|
1787 |
|
1788 |
<div id="updraft-hidethis">
|
@@ -1802,7 +1826,7 @@ CREATE TABLE $wpdb->signups (
|
|
1802 |
<?php
|
1803 |
}
|
1804 |
|
1805 |
-
if($this->scan_old_dirs()) $this->print_delete_old_dirs_form();
|
1806 |
|
1807 |
if(!empty($updraftplus->errors)) {
|
1808 |
echo '<div class="error fade" style="padding:8px;">';
|
@@ -1933,7 +1957,7 @@ CREATE TABLE $wpdb->signups (
|
|
1933 |
|
1934 |
<?php
|
1935 |
# Currently disabled - not sure who we want to show this to
|
1936 |
-
if (1==0 && !defined('
|
1937 |
$feed = $updraftplus->get_updraftplus_rssfeed();
|
1938 |
if (is_a($feed, 'SimplePie')) {
|
1939 |
echo '<tr><th style="vertical-align:top;">'.__('Latest UpdraftPlus.com news:', 'updraftplus').'</th><td style="vertical-align:top;">';
|
@@ -2032,7 +2056,7 @@ CREATE TABLE $wpdb->signups (
|
|
2032 |
<li>
|
2033 |
<strong><?php _e('More tasks:','updraftplus');?></strong>
|
2034 |
<a href="#" onclick="jQuery('#updraft-plupload-modal').slideToggle(); return false;"><?php _e('Upload backup files','updraftplus');?></a>
|
2035 |
-
| <a href="#" onclick="updraft_updatehistory(1, 0); return false;" title="<?php
|
2036 |
| <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>
|
2037 |
</li>
|
2038 |
<?php
|
@@ -2045,7 +2069,7 @@ CREATE TABLE $wpdb->signups (
|
|
2045 |
?><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>
|
2046 |
<?php } ?>
|
2047 |
|
2048 |
-
<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
|
2049 |
</p>
|
2050 |
|
2051 |
<div id="updraft-plupload-modal" title="<?php _e('UpdraftPlus - Upload backup files','updraftplus'); ?>" style="width: 75%; margin: 16px; display:none; margin-left: 100px;">
|
@@ -2140,7 +2164,8 @@ CREATE TABLE $wpdb->signups (
|
|
2140 |
echo '</div>';
|
2141 |
} else {
|
2142 |
$sdescrip = isset($info['shortdescription']) ? $info['shortdescription'] : $info['description'];
|
2143 |
-
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.'"
|
|
|
2144 |
}
|
2145 |
}
|
2146 |
?>
|
@@ -2222,7 +2247,7 @@ CREATE TABLE $wpdb->signups (
|
|
2222 |
$this->settings_debugrow(__('Free disk space in account:', 'updraftplus'), sprintf(__('%s (%s used)', 'updraftplus'), round($hosting_bytes_free[3]/1048576, 1)." Mb", "$perc %"));
|
2223 |
}
|
2224 |
|
2225 |
-
$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>');
|
2226 |
|
2227 |
$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>');
|
2228 |
|
@@ -2255,12 +2280,12 @@ CREATE TABLE $wpdb->signups (
|
|
2255 |
<tbody>
|
2256 |
<tr>
|
2257 |
<td>
|
2258 |
-
<form method="post">
|
2259 |
<input type="hidden" name="action" value="updraft_backup_debug_all" />
|
2260 |
<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>
|
2261 |
</form>
|
2262 |
</td><td>
|
2263 |
-
<form method="post">
|
2264 |
<input type="hidden" name="action" value="updraft_backup_debug_db" />
|
2265 |
<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>
|
2266 |
</form>
|
@@ -2270,7 +2295,7 @@ CREATE TABLE $wpdb->signups (
|
|
2270 |
</table>
|
2271 |
<h3><?php _e('Wipe Settings','updraftplus');?></h3>
|
2272 |
<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>
|
2273 |
-
<form method="post">
|
2274 |
<input type="hidden" name="action" value="updraft_wipesettings" />
|
2275 |
<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>
|
2276 |
</form>
|
@@ -2278,7 +2303,7 @@ CREATE TABLE $wpdb->signups (
|
|
2278 |
<?php
|
2279 |
}
|
2280 |
|
2281 |
-
function print_delete_old_dirs_form($include_blurb = true) {
|
2282 |
?>
|
2283 |
<?php if ($include_blurb) {
|
2284 |
?>
|
@@ -2622,7 +2647,8 @@ CREATE TABLE $wpdb->signups (
|
|
2622 |
return true;
|
2623 |
} else {
|
2624 |
@$wp_filesystem->chmod($default_backup_dir, 0775);
|
2625 |
-
|
|
|
2626 |
}
|
2627 |
}
|
2628 |
|
@@ -2630,15 +2656,23 @@ CREATE TABLE $wpdb->signups (
|
|
2630 |
}
|
2631 |
|
2632 |
//scans the content dir to see if any -old dirs are present
|
2633 |
-
private function scan_old_dirs() {
|
2634 |
global $updraftplus;
|
2635 |
$dirs = scandir(untrailingslashit(WP_CONTENT_DIR));
|
2636 |
if (!is_array($dirs)) $dirs = array();
|
2637 |
$dirs_u = @scandir($updraftplus->backups_dir_location());
|
2638 |
if (!is_array($dirs_u)) $dirs_u = array();
|
2639 |
-
foreach (array_merge($dirs, $dirs_u) as $dir) {
|
|
|
|
|
|
|
|
|
|
|
2640 |
# No need to scan ABSPATH - we don't backup there
|
2641 |
-
if (is_dir(untrailingslashit(WP_PLUGIN_DIR).'-old'))
|
|
|
|
|
|
|
2642 |
return false;
|
2643 |
}
|
2644 |
|
@@ -2738,6 +2772,7 @@ CREATE TABLE $wpdb->signups (
|
|
2738 |
?> <input type="number" min="1" step="1" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:48px;" />
|
2739 |
</td>
|
2740 |
</tr>
|
|
|
2741 |
<!--
|
2742 |
<tr id="updraft_incremental_row">
|
2743 |
<th><?php _e('Incremental file backup intervals', 'updraftplus'); ?>:</th>
|
@@ -2747,7 +2782,6 @@ CREATE TABLE $wpdb->signups (
|
|
2747 |
</td>
|
2748 |
</tr>
|
2749 |
-->
|
2750 |
-
|
2751 |
<?php apply_filters('updraftplus_after_file_intervals', false, $selected_interval); ?>
|
2752 |
<tr>
|
2753 |
<th><?php _e('Database backup intervals','updraftplus'); ?>:</th>
|
@@ -2768,7 +2802,7 @@ CREATE TABLE $wpdb->signups (
|
|
2768 |
</td>
|
2769 |
</tr>
|
2770 |
<tr class="backup-interval-description">
|
2771 |
-
<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.
|
2772 |
<?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>'); ?>
|
2773 |
</div></td>
|
2774 |
</tr>
|
@@ -2806,7 +2840,7 @@ CREATE TABLE $wpdb->signups (
|
|
2806 |
}
|
2807 |
?>
|
2808 |
<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>
|
2809 |
-
<?php if (1==0 && !defined('
|
2810 |
</td>
|
2811 |
</tr>
|
2812 |
|
@@ -3010,8 +3044,8 @@ CREATE TABLE $wpdb->signups (
|
|
3010 |
</tr>
|
3011 |
<?php
|
3012 |
$delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
|
3013 |
-
$split_every_mb = UpdraftPlus_Options::get_updraft_option('updraft_split_every',
|
3014 |
-
if (!is_numeric($split_every_mb)) $split_every_mb =
|
3015 |
if ($split_every_mb < UPDRAFTPLUS_SPLIT_MIN) $split_every_mb = UPDRAFTPLUS_SPLIT_MIN;
|
3016 |
?>
|
3017 |
|
@@ -3022,7 +3056,7 @@ CREATE TABLE $wpdb->signups (
|
|
3022 |
|
3023 |
<tr class="expertmode" style="display:none;">
|
3024 |
<th><?php _e('Split archives every:','updraftplus');?></th>
|
3025 |
-
<td><input type="text" name="updraft_split_every" id="updraft_split_every" value="<?php echo $split_every_mb ?>" size="5" /> Mb<br><?php
|
3026 |
</tr>
|
3027 |
|
3028 |
<tr class="deletelocal expertmode" style="display:none;">
|
@@ -3141,7 +3175,7 @@ CREATE TABLE $wpdb->signups (
|
|
3141 |
}
|
3142 |
|
3143 |
# If $basedirs is passed as an array, then $directorieses must be too
|
3144 |
-
function recursive_directory_size($directorieses, $exclude = array(), $basedirs = '') {
|
3145 |
|
3146 |
$size = 0;
|
3147 |
|
@@ -3152,11 +3186,11 @@ CREATE TABLE $wpdb->signups (
|
|
3152 |
|
3153 |
if (is_string($basedirs)) $basedirs = array($basedirs);
|
3154 |
|
3155 |
-
foreach ($
|
3156 |
-
|
3157 |
-
$directories = $directorieses[$ind];
|
3158 |
if (!is_array($directories)) $directories=array($directories);
|
3159 |
|
|
|
|
|
3160 |
foreach ($directories as $dir) {
|
3161 |
if (is_file($dir)) {
|
3162 |
$size += @filesize($dir);
|
@@ -3168,6 +3202,23 @@ CREATE TABLE $wpdb->signups (
|
|
3168 |
|
3169 |
}
|
3170 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3171 |
if ($size > 1073741824) {
|
3172 |
return round($size / 1073741824, 1).' Gb';
|
3173 |
} elseif ($size > 1048576) {
|
@@ -3180,7 +3231,7 @@ CREATE TABLE $wpdb->signups (
|
|
3180 |
|
3181 |
}
|
3182 |
|
3183 |
-
function recursive_directory_size_raw($prefix_directory, &$exclude = array(), $suffix_directory = '') {
|
3184 |
|
3185 |
$directory = $prefix_directory.('' == $suffix_directory ? '' : '/'.$suffix_directory);
|
3186 |
$size = 0;
|
@@ -3267,6 +3318,7 @@ CREATE TABLE $wpdb->signups (
|
|
3267 |
<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 class="updraft_existingbackup_date" data-rawbackup="$rawbackup"><b>$datespan</b>
|
3268 |
ENDHERE;
|
3269 |
|
|
|
3270 |
if (is_array($jobdata) && !empty($jobdata['resume_interval']) && (empty($jobdata['jobstatus']) || 'finished' != $jobdata['jobstatus'])) {
|
3271 |
$ret .= apply_filters('updraftplus_msg_unfinishedbackup', "<br><span title=\"".esc_attr(__('If you are seeing more backups than you expect, then it is probably because the deletion of old backup sets does not happen until a fresh backup completes.', 'updraftplus'))."\">".__('(Not finished)', 'updraftplus').'</span>', $jobdata, $non);
|
3272 |
}
|
@@ -3439,7 +3491,7 @@ ENDHERE;
|
|
3439 |
# jQuery('#updraft_restore_label_wpcore').html('".esc_js($wpcore_restore_descrip)."');
|
3440 |
$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');
|
3441 |
jQuery('#updraft_restore_timestamp').val('$key'); jQuery('.updraft_restore_date').html('$show_data'); ";
|
3442 |
-
$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>';
|
3443 |
}
|
3444 |
$ret .= <<<ENDHERE
|
3445 |
</form>
|
@@ -3461,7 +3513,9 @@ ENDHERE;
|
|
3461 |
$messages = array();
|
3462 |
$gmt_offset = get_option('gmt_offset');
|
3463 |
|
|
|
3464 |
$known_files = array();
|
|
|
3465 |
$known_nonces = array();
|
3466 |
$changes = false;
|
3467 |
|
@@ -3474,7 +3528,7 @@ ENDHERE;
|
|
3474 |
|
3475 |
$accept = apply_filters('updraftplus_accept_archivename', array());
|
3476 |
if (!is_array($accept)) $accept = array();
|
3477 |
-
//
|
3478 |
foreach ($backup_history as $btime => $bdata) {
|
3479 |
$found_file = false;
|
3480 |
foreach ($bdata as $key => $values) {
|
@@ -3490,7 +3544,7 @@ ENDHERE;
|
|
3490 |
} else {
|
3491 |
$found_file = true;
|
3492 |
$known_files[$val] = $nonce;
|
3493 |
-
$known_nonces[$nonce] = $btime;
|
3494 |
}
|
3495 |
} else {
|
3496 |
$accepted = false;
|
@@ -3499,9 +3553,10 @@ ENDHERE;
|
|
3499 |
}
|
3500 |
if (!empty($accepted) && (false != ($btime = apply_filters('updraftplus_foreign_gettime', false, $fkey, $val))) && $btime > 0) {
|
3501 |
$found_file = true;
|
|
|
3502 |
$nonce = substr(md5($val), 0, 12);
|
3503 |
$known_files[$val] = $nonce;
|
3504 |
-
$known_nonces[$nonce] = $btime;
|
3505 |
}
|
3506 |
}
|
3507 |
}
|
@@ -3516,7 +3571,9 @@ ENDHERE;
|
|
3516 |
$remotefiles = array();
|
3517 |
$remotesizes = array();
|
3518 |
# Scan remote storage and get back lists of files and their sizes
|
|
|
3519 |
if ($remotescan) {
|
|
|
3520 |
foreach ($updraftplus->backup_methods as $method => $desc) {
|
3521 |
require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
|
3522 |
$objname = 'UpdraftPlus_BackupModule_'.$method;
|
@@ -3548,6 +3605,7 @@ ENDHERE;
|
|
3548 |
}
|
3549 |
}
|
3550 |
}
|
|
|
3551 |
}
|
3552 |
|
3553 |
if (!$handle = opendir($updraft_dir)) return;
|
@@ -3557,6 +3615,7 @@ ENDHERE;
|
|
3557 |
$accepted_foreign = false;
|
3558 |
$potmessage = false;
|
3559 |
if ('.' == $entry || '..' == $entry) continue;
|
|
|
3560 |
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)) {
|
3561 |
|
3562 |
// Interpret the time as one from the blog's local timezone, rather than as UTC
|
@@ -3597,7 +3656,19 @@ ENDHERE;
|
|
3597 |
continue;
|
3598 |
}
|
3599 |
// The time from the filename does not include seconds. Need to identify the seconds to get the right time
|
3600 |
-
if (isset($known_nonces[$nonce]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3601 |
if ($btime <= 100) continue;
|
3602 |
$fs = @filesize($updraft_dir.'/'.$entry);
|
3603 |
|
@@ -3606,6 +3677,7 @@ ENDHERE;
|
|
3606 |
if (is_array($potmessage)) $messages[$potmessage['code']] = $potmessage;
|
3607 |
}
|
3608 |
|
|
|
3609 |
# Make sure we have the right list of services
|
3610 |
$current_services = (!empty($backup_history[$btime]) && !empty($backup_history[$btime]['service'])) ? $backup_history[$btime]['service'] : array();
|
3611 |
if (is_string($current_services)) $current_services = array($current_services);
|
@@ -3730,8 +3802,9 @@ ENDHERE;
|
|
3730 |
$credentials = request_filesystem_credentials(UpdraftPlus_Options::admin_page()."?page=updraftplus&action=updraft_restore&backup_timestamp=$timestamp", '', false, false, $extra_fields);
|
3731 |
WP_Filesystem($credentials);
|
3732 |
if ( $wp_filesystem->errors->get_error_code() ) {
|
|
|
3733 |
foreach ( $wp_filesystem->errors->get_error_messages() as $message ) show_message($message);
|
3734 |
-
exit;
|
3735 |
}
|
3736 |
|
3737 |
# Set up logging
|
@@ -3860,6 +3933,7 @@ ENDHERE;
|
|
3860 |
$fullpath = $updraft_dir.$file;
|
3861 |
echo sprintf(__("Looking for %s archive: file name: %s", 'updraftplus'), $type, htmlspecialchars($file))."<br>";
|
3862 |
|
|
|
3863 |
foreach ($service as $serv) {
|
3864 |
if(!is_readable($fullpath)) {
|
3865 |
$sd = (empty($updraftplus->backup_methods[$serv])) ? $serv : $updraftplus->backup_methods[$serv];
|
@@ -3874,6 +3948,7 @@ ENDHERE;
|
|
3874 |
echo '<br>';
|
3875 |
}
|
3876 |
}
|
|
|
3877 |
|
3878 |
$index = ($ind == 0) ? '' : $ind;
|
3879 |
// If a file size is stored in the backup data, then verify correctness of the local file
|
@@ -4053,7 +4128,7 @@ ENDHERE;
|
|
4053 |
private function get_settings_keys() {
|
4054 |
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',
|
4055 |
'updraft_lastmessage', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder',
|
4056 |
-
'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');
|
4057 |
}
|
4058 |
|
4059 |
}
|
2 |
|
3 |
if (!defined ('ABSPATH')) die('No direct access allowed');
|
4 |
|
5 |
+
// Admin-area code lives here. This gets called in admin_menu, earlier than admin_init
|
|
|
|
|
6 |
|
7 |
global $updraftplus_admin;
|
8 |
if (!is_a($updraftplus_admin, 'UpdraftPlus_Admin')) $updraftplus_admin = new UpdraftPlus_Admin();
|
43 |
$token = UpdraftPlus_Options::get_updraft_option('updraft_googledrive_token', '');
|
44 |
} else {
|
45 |
$clientid = $opts['clientid'];
|
46 |
+
$token = (empty($opts['token'])) ? '' : $opts['token'];
|
47 |
}
|
48 |
if (!empty($clientid) && empty($token)) add_action('all_admin_notices', array($this,'show_admin_warning_googledrive'));
|
49 |
}
|
50 |
|
51 |
+
if (UpdraftPlus_Options::user_can_manage()) {
|
52 |
+
if ('dropbox' === $service || is_array($service) && in_array('dropbox', $service)) {
|
53 |
+
$opts = UpdraftPlus_Options::get_updraft_option('updraft_dropbox');
|
54 |
+
if (empty($opts['tk_request_token'])) {
|
55 |
+
add_action('all_admin_notices', array($this,'show_admin_warning_dropbox') );
|
56 |
+
}
|
57 |
}
|
58 |
+
if ('bitcasa' === $service || is_array($service) && in_array('bitcasa', $service)) {
|
59 |
+
$opts = UpdraftPlus_Options::get_updraft_option('updraft_bitcasa');
|
60 |
+
if (!empty($opts['clientid']) && !empty($opts['secret']) && empty($opts['token'])) add_action('all_admin_notices', array($this,'show_admin_warning_bitcasa') );
|
61 |
+
}
|
62 |
+
if ('copycom' === $service || is_array($service) && in_array('copycom', $service)) {
|
63 |
+
$opts = UpdraftPlus_Options::get_updraft_option('updraft_copycom');
|
64 |
+
if (!empty($opts['clientid']) && !empty($opts['secret']) && empty($opts['token'])) add_action('all_admin_notices', array($this,'show_admin_warning_copycom') );
|
65 |
+
}
|
66 |
+
if ($this->disk_space_check(1048576*35) === false) add_action('all_admin_notices', array($this, 'show_admin_warning_diskspace'));
|
67 |
}
|
68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
// Next, the actions that only come on the UpdraftPlus page
|
70 |
if ($pagenow != UpdraftPlus_Options::admin_page() || empty($_REQUEST['page']) || 'updraftplus' != $_REQUEST['page']) return;
|
71 |
|
174 |
|
175 |
public function core_upgrade_preamble() {
|
176 |
if (!class_exists('UpdraftPlus_Addon_Autobackup')) {
|
177 |
+
if (defined('UPDRAFTPLUS_NOADS_B')) return;
|
178 |
# TODO: Remove legacy/wrong use of transient any time from 1 Jun 2014
|
179 |
if (true == get_transient('updraftplus_dismissedautobackup')) return;
|
180 |
$dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismissedautobackup', 0);
|
380 |
|
381 |
public function admin_action_upgrade_pluginortheme() {
|
382 |
|
383 |
+
if (isset($_GET['action']) && ($_GET['action'] == 'upgrade-plugin' || $_GET['action'] == 'upgrade-theme') && !class_exists('UpdraftPlus_Addon_Autobackup') && !defined('UPDRAFTPLUS_NOADS_B')) {
|
384 |
|
385 |
# TODO: Remove legacy/erroneous use of transient any time after 1 Jun 2014
|
386 |
$dismissed = get_transient('updraftplus_dismissedautobackup');
|
423 |
}
|
424 |
|
425 |
public function show_admin_warning_disabledcron() {
|
426 |
+
$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 "Backup Now") 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>', 'updated updraftplus-disable-wp-cron-warning');
|
427 |
}
|
428 |
|
429 |
public function show_admin_warning_diskspace() {
|
457 |
$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>');
|
458 |
}
|
459 |
|
460 |
+
public function show_admin_warning_copycom() {
|
461 |
+
$this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraftmethod-copycom-auth&updraftplus_copycomauth=doit">'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'),'Copy.Com','Copy').'</a>');
|
462 |
+
}
|
463 |
+
|
464 |
public function show_admin_warning_googledrive() {
|
465 |
$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>');
|
466 |
}
|
576 |
if ($needs_downloading) {
|
577 |
$this->close_browser_connection();
|
578 |
$is_downloaded = false;
|
579 |
+
add_action('http_request_args', array($updraftplus, 'modify_http_options'));
|
580 |
foreach ($services as $service) {
|
581 |
if ($is_downloaded) continue;
|
582 |
$download = $this->download_file($file, $service);
|
590 |
$updraftplus->log('Remote fetch failed');
|
591 |
}
|
592 |
}
|
593 |
+
remove_action('http_request_args', array($updraftplus, 'modify_http_options'));
|
594 |
}
|
595 |
|
596 |
// Now, spool the thing to the browser
|
930 |
|
931 |
$local_deleted = 0;
|
932 |
$remote_deleted = 0;
|
933 |
+
add_action('http_request_args', array($updraftplus, 'modify_http_options'));
|
934 |
foreach ($files_to_delete as $key => $files) {
|
935 |
# Local deletion
|
936 |
if (is_string($files)) $files=array($files);
|
960 |
}
|
961 |
}
|
962 |
}
|
963 |
+
remove_action('http_request_args', array($updraftplus, 'modify_http_options'));
|
964 |
$message .= __('The backup set has been removed.', 'updraftplus')."\n";
|
965 |
$message .= sprintf(__('Local archives deleted: %d', 'updraftplus'),$local_deleted)."\n";
|
966 |
$message .= sprintf(__('Remote archives deleted: %d', 'updraftplus'),$remote_deleted)."\n";
|
1044 |
} elseif ('doaction' == $_REQUEST['subaction'] && !empty($_REQUEST['subsubaction']) && 'updraft_' == substr($_REQUEST['subsubaction'], 0, 8)) {
|
1045 |
do_action($_REQUEST['subsubaction']);
|
1046 |
} elseif ('backupnow' == $_REQUEST['subaction']) {
|
1047 |
+
|
1048 |
$backupnow_nocloud = (empty($_REQUEST['backupnow_nocloud'])) ? false : true;
|
1049 |
$event = (!empty($_REQUEST['backupnow_nofiles'])) ? 'updraft_backupnow_backup_database' : ((!empty($_REQUEST['backupnow_nodb'])) ? 'updraft_backupnow_backup' : 'updraft_backupnow_backup_all');
|
1050 |
|
1051 |
+
$msg = '<strong>'.__('Start backup','updraftplus').':</strong> '.htmlspecialchars(__('OK. You should soon see activity in the "Last log message" field below.','updraftplus'));
|
|
|
1052 |
$this->close_browser_connection($msg);
|
1053 |
do_action($event, $backupnow_nocloud);
|
1054 |
|
1133 |
$objname = "UpdraftPlus_BackupModule_$method";
|
1134 |
|
1135 |
$this->logged = array();
|
1136 |
+
# TODO: Add action for WP HTTP SSL stuff
|
1137 |
set_error_handler(array($this, 'get_php_errors'), E_ALL & ~E_STRICT);
|
1138 |
if (method_exists($objname, "credentials_test")) {
|
1139 |
$obj = new $objname;
|
1176 |
return true;
|
1177 |
}
|
1178 |
|
1179 |
+
private function download_status($timestamp, $type, $findex) {
|
1180 |
|
1181 |
global $updraftplus;
|
1182 |
|
1293 |
$old_siteinfo = array();
|
1294 |
$gathering_siteinfo = true;
|
1295 |
$old_wp_version = '';
|
1296 |
+
$old_php_version = '';
|
1297 |
|
1298 |
$tables_found = array();
|
1299 |
|
1329 |
$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);
|
1330 |
if (!empty($powarn)) $warn[] = $powarn;
|
1331 |
}
|
1332 |
+
} elseif ('' == $old_wp_version && preg_match('/^\# WordPress Version: ([0-9]+(\.[0-9]+)+)(-[-a-z0-9]+,)?(.*)$/', $buffer, $matches)) {
|
1333 |
$old_wp_version = $matches[1];
|
1334 |
if (!empty($matches[3])) $old_wp_version .= substr($matches[3], 0, strlen($matches[3])-1);
|
1335 |
if (version_compare($old_wp_version, $wp_version, '>')) {
|
1336 |
//$mess[] = sprintf(__('%s version: %s', 'updraftplus'), 'WordPress', $old_wp_version);
|
1337 |
$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);
|
1338 |
}
|
1339 |
+
if (preg_match('/running on PHP ([0-9]+\.[0-9]+)(\s|\.)/', $matches[4], $nmatches) && preg_match('/^([0-9]+\.[0-9]+)(\s|\.)/', PHP_VERSION, $cmatches)) {
|
1340 |
+
$old_php_version = $nmatches[1];
|
1341 |
+
$current_php_version = $cmatches[1];
|
1342 |
+
if (version_compare($old_php_version, $current_php_version, '>')) {
|
1343 |
+
//$mess[] = sprintf(__('%s version: %s', 'updraftplus'), 'WordPress', $old_wp_version);
|
1344 |
+
$warn[] = sprintf(__('The site in this backup was running on a webserver with version %s of %s. ', 'updraftplus'), $old_php_version, 'PHP').' '.sprintf(__('This is significantly newer than the server which you are now restoring onto (version %s).', 'updraftplus'), PHP_VERSION).' '.sprintf(__('You should only proceed if you cannot update the current server and are confident (or willing to risk) that your plugins/themes/etc. are compatible with the older %s version.', 'updraftplus'), 'PHP').' '.sprintf(__('Any support requests to do with %s should be raised with your web hosting company.', 'updraftplus'), 'PHP');
|
1345 |
+
}
|
1346 |
+
}
|
1347 |
} elseif ('' == $old_table_prefix && (preg_match('/^\# Table prefix: (\S+)$/', $buffer, $matches) || preg_match('/^-- Table prefix: (\S+)$/i', $buffer, $matches))) {
|
1348 |
$old_table_prefix = $matches[1];
|
1349 |
// echo '<strong>'.__('Old table prefix:', 'updraftplus').'</strong> '.htmlspecialchars($old_table_prefix).'<br>';
|
1520 |
global $updraftplus;
|
1521 |
@set_time_limit(900);
|
1522 |
|
1523 |
+
if (!UpdraftPlus_Options::user_can_manage()) exit;
|
1524 |
check_ajax_referer('updraft-uploader');
|
1525 |
|
1526 |
$updraft_dir = $updraftplus->backups_dir_location();
|
1539 |
$farray['ext'] = 'x-gzip';
|
1540 |
$farray['type'] = 'application/octet-stream';
|
1541 |
|
1542 |
+
if (!isset($_POST['chunks'])) {
|
|
|
|
|
1543 |
$farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
|
1544 |
}
|
1545 |
|
1558 |
// If this was the chunk, then we should instead be concatenating onto the final file
|
1559 |
if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
|
1560 |
$final_file = basename($_POST['name']);
|
1561 |
+
if (!rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp')) {
|
1562 |
+
@unlink($status['file']);
|
1563 |
+
echo json_encode(array('e' => sprintf(__('Error: %s', 'updraftplus'), __('This file could not be uploaded', 'updraftplus'))));
|
1564 |
+
exit;
|
1565 |
+
}
|
1566 |
$status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
|
1567 |
|
1568 |
// Final chunk? If so, then stich it all back together
|
1634 |
@set_time_limit(900);
|
1635 |
global $updraftplus;
|
1636 |
|
1637 |
+
if (!UpdraftPlus_Options::user_can_manage()) exit;
|
1638 |
check_ajax_referer('updraft-uploader');
|
1639 |
|
1640 |
$updraft_dir = $updraftplus->backups_dir_location();
|
1805 |
<div class="wrap" id="updraft-wrap">
|
1806 |
<h1><?php echo $updraftplus->plugin_title; ?></h1>
|
1807 |
|
1808 |
+
<a href="http://updraftplus.com">UpdraftPlus.Com</a> | <a href="https://updraftplus.com/news/"><?php _e('News','updraftplus');?></a> | <a href="https://twitter.com/updraftplus"><?php _e('Twitter', 'updraftplus');?></a> | <?php if (!defined('UPDRAFTPLUS_NOADS_B')) { ?><a href="http://updraftplus.com/shop/updraftplus-premium/"><?php _e("Premium",'updraftplus');?></a>
|
1809 |
+
| <?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_B')) { ?><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; ?>
|
1810 |
<br>
|
1811 |
|
1812 |
<div id="updraft-hidethis">
|
1826 |
<?php
|
1827 |
}
|
1828 |
|
1829 |
+
if($this->scan_old_dirs(true)) $this->print_delete_old_dirs_form();
|
1830 |
|
1831 |
if(!empty($updraftplus->errors)) {
|
1832 |
echo '<div class="error fade" style="padding:8px;">';
|
1957 |
|
1958 |
<?php
|
1959 |
# Currently disabled - not sure who we want to show this to
|
1960 |
+
if (1==0 && !defined('UPDRAFTPLUS_NOADS_B')) {
|
1961 |
$feed = $updraftplus->get_updraftplus_rssfeed();
|
1962 |
if (is_a($feed, 'SimplePie')) {
|
1963 |
echo '<tr><th style="vertical-align:top;">'.__('Latest UpdraftPlus.com news:', 'updraftplus').'</th><td style="vertical-align:top;">';
|
2056 |
<li>
|
2057 |
<strong><?php _e('More tasks:','updraftplus');?></strong>
|
2058 |
<a href="#" onclick="jQuery('#updraft-plupload-modal').slideToggle(); return false;"><?php _e('Upload backup files','updraftplus');?></a>
|
2059 |
+
| <a href="#" onclick="updraft_updatehistory(1, 0); return false;" title="<?php echo __('Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded.', 'updraftplus').' '.__('The location of this directory is set in the expert settings, in the Settings tab.','updraftplus'); ?>"><?php _e('Rescan local folder for new backup sets','updraftplus');?></a>
|
2060 |
| <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>
|
2061 |
</li>
|
2062 |
<?php
|
2069 |
?><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>
|
2070 |
<?php } ?>
|
2071 |
|
2072 |
+
<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><?php _e('calculating...', 'updraftplus'); ?></em></span> <a href="#" onclick="updraftplus_diskspace(); return false;"><?php _e('refresh','updraftplus');?></a></li></ul>
|
2073 |
</p>
|
2074 |
|
2075 |
<div id="updraft-plupload-modal" title="<?php _e('UpdraftPlus - Upload backup files','updraftplus'); ?>" style="width: 75%; margin: 16px; display:none; margin-left: 100px;">
|
2164 |
echo '</div>';
|
2165 |
} else {
|
2166 |
$sdescrip = isset($info['shortdescription']) ? $info['shortdescription'] : $info['description'];
|
2167 |
+
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.'">';
|
2168 |
+
echo '</div>';
|
2169 |
}
|
2170 |
}
|
2171 |
?>
|
2247 |
$this->settings_debugrow(__('Free disk space in account:', 'updraftplus'), sprintf(__('%s (%s used)', 'updraftplus'), round($hosting_bytes_free[3]/1048576, 1)." Mb", "$perc %"));
|
2248 |
}
|
2249 |
|
2250 |
+
$this->settings_debugrow(__('Plugins for debugging:', 'updraftplus'),'<a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=wp-crontrol'), 'install-plugin_wp-crontrol').'">WP Crontrol</a> | <a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=sql-executioner'), 'install-plugin_sql-executioner').'">SQL Executioner</a> | <a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=advanced-code-editor'), 'install-plugin_advanced-code-editor').'">Advanced Code Editor</a> '.(current_user_can('edit_plugins') ? '<a href="'.self_admin_url('plugin-editor.php?file=updraftplus/updraftplus.php').'">(edit UpdraftPlus)</a>' : '').' | <a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=wp-filemanager'), 'install-plugin_wp-filemanager').'">WP Filemanager</a>');
|
2251 |
|
2252 |
$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>');
|
2253 |
|
2280 |
<tbody>
|
2281 |
<tr>
|
2282 |
<td>
|
2283 |
+
<form method="post" action="<?php echo add_query_arg(array('updraft_restore_success' => false, 'action' => false, 'page' => 'updraftplus')); ?>">
|
2284 |
<input type="hidden" name="action" value="updraft_backup_debug_all" />
|
2285 |
<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>
|
2286 |
</form>
|
2287 |
</td><td>
|
2288 |
+
<form method="post" action="<?php echo add_query_arg(array('updraft_restore_success' => false, 'action' => false, 'page' => 'updraftplus')); ?>">
|
2289 |
<input type="hidden" name="action" value="updraft_backup_debug_db" />
|
2290 |
<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>
|
2291 |
</form>
|
2295 |
</table>
|
2296 |
<h3><?php _e('Wipe Settings','updraftplus');?></h3>
|
2297 |
<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>
|
2298 |
+
<form method="post" action="<?php echo add_query_arg(array('updraft_restore_success' => false, 'action' => false, 'page' => 'updraftplus')); ?>">
|
2299 |
<input type="hidden" name="action" value="updraft_wipesettings" />
|
2300 |
<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>
|
2301 |
</form>
|
2303 |
<?php
|
2304 |
}
|
2305 |
|
2306 |
+
private function print_delete_old_dirs_form($include_blurb = true) {
|
2307 |
?>
|
2308 |
<?php if ($include_blurb) {
|
2309 |
?>
|
2647 |
return true;
|
2648 |
} else {
|
2649 |
@$wp_filesystem->chmod($default_backup_dir, 0775);
|
2650 |
+
$show_dir = (0 === strpos($default_backup_dir, ABSPATH)) ? substr($default_backup_dir, strlen(ABSPATH)) : $default_backup_dir;
|
2651 |
+
return new WP_Error('writable_error', __('The folder exists, but your webserver does not have permission to write to it.', 'updraftplus').' '.__('You will need to consult with your web hosting provider to find out how to set permissions for a WordPress plugin to write to the directory.', 'updraftplus').' ('.$show_dir.')');
|
2652 |
}
|
2653 |
}
|
2654 |
|
2656 |
}
|
2657 |
|
2658 |
//scans the content dir to see if any -old dirs are present
|
2659 |
+
private function scan_old_dirs($print_as_comment = false) {
|
2660 |
global $updraftplus;
|
2661 |
$dirs = scandir(untrailingslashit(WP_CONTENT_DIR));
|
2662 |
if (!is_array($dirs)) $dirs = array();
|
2663 |
$dirs_u = @scandir($updraftplus->backups_dir_location());
|
2664 |
if (!is_array($dirs_u)) $dirs_u = array();
|
2665 |
+
foreach (array_merge($dirs, $dirs_u) as $dir) {
|
2666 |
+
if (preg_match('/-old$/', $dir)) {
|
2667 |
+
if ($print_as_comment) echo '<!--'.htmlspecialchars($dir).'-->';
|
2668 |
+
return true;
|
2669 |
+
}
|
2670 |
+
}
|
2671 |
# No need to scan ABSPATH - we don't backup there
|
2672 |
+
if (is_dir(untrailingslashit(WP_PLUGIN_DIR).'-old')) {
|
2673 |
+
if ($print_as_comment) echo '<!--'.htmlspecialchars(untrailingslashit(WP_PLUGIN_DIR).'-old').'-->';
|
2674 |
+
return true;
|
2675 |
+
}
|
2676 |
return false;
|
2677 |
}
|
2678 |
|
2772 |
?> <input type="number" min="1" step="1" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:48px;" />
|
2773 |
</td>
|
2774 |
</tr>
|
2775 |
+
|
2776 |
<!--
|
2777 |
<tr id="updraft_incremental_row">
|
2778 |
<th><?php _e('Incremental file backup intervals', 'updraftplus'); ?>:</th>
|
2782 |
</td>
|
2783 |
</tr>
|
2784 |
-->
|
|
|
2785 |
<?php apply_filters('updraftplus_after_file_intervals', false, $selected_interval); ?>
|
2786 |
<tr>
|
2787 |
<th><?php _e('Database backup intervals','updraftplus'); ?>:</th>
|
2802 |
</td>
|
2803 |
</tr>
|
2804 |
<tr class="backup-interval-description">
|
2805 |
+
<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.', 'updraftplus').' '.__('If the two schedules are the same, then the two backups will take place together.', 'updraftplus')); ?></p>
|
2806 |
<?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>'); ?>
|
2807 |
</div></td>
|
2808 |
</tr>
|
2840 |
}
|
2841 |
?>
|
2842 |
<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>
|
2843 |
+
<?php if (1==0 && !defined('UPDRAFTPLUS_NOADS_B')) echo '<p><a href="http://wordshell.net">('.__('Use WordShell for automatic backup, version control and patching', 'updraftplus').').</a></p>';?>
|
2844 |
</td>
|
2845 |
</tr>
|
2846 |
|
3044 |
</tr>
|
3045 |
<?php
|
3046 |
$delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
|
3047 |
+
$split_every_mb = UpdraftPlus_Options::get_updraft_option('updraft_split_every', 500);
|
3048 |
+
if (!is_numeric($split_every_mb)) $split_every_mb = 500;
|
3049 |
if ($split_every_mb < UPDRAFTPLUS_SPLIT_MIN) $split_every_mb = UPDRAFTPLUS_SPLIT_MIN;
|
3050 |
?>
|
3051 |
|
3056 |
|
3057 |
<tr class="expertmode" style="display:none;">
|
3058 |
<th><?php _e('Split archives every:','updraftplus');?></th>
|
3059 |
+
<td><input type="text" name="updraft_split_every" id="updraft_split_every" value="<?php echo $split_every_mb ?>" size="5" /> Mb<br><?php echo sprintf(__('UpdraftPlus will split up backup archives when they exceed this file size. The default value is %s megabytes. Be careful to leave some margin if your web-server has a hard size limit (e.g. the 2 Gb / 2048 Mb limit on some 32-bit servers/file systems).','updraftplus'), 500); ?></td>
|
3060 |
</tr>
|
3061 |
|
3062 |
<tr class="deletelocal expertmode" style="display:none;">
|
3175 |
}
|
3176 |
|
3177 |
# If $basedirs is passed as an array, then $directorieses must be too
|
3178 |
+
private function recursive_directory_size($directorieses, $exclude = array(), $basedirs = '') {
|
3179 |
|
3180 |
$size = 0;
|
3181 |
|
3186 |
|
3187 |
if (is_string($basedirs)) $basedirs = array($basedirs);
|
3188 |
|
3189 |
+
foreach ($directorieses as $ind => $directories) {
|
|
|
|
|
3190 |
if (!is_array($directories)) $directories=array($directories);
|
3191 |
|
3192 |
+
$basedir = empty($basedirs[$ind]) ? $basedirs[0] : $basedirs[$ind];
|
3193 |
+
|
3194 |
foreach ($directories as $dir) {
|
3195 |
if (is_file($dir)) {
|
3196 |
$size += @filesize($dir);
|
3202 |
|
3203 |
}
|
3204 |
|
3205 |
+
// foreach ($basedirs as $ind => $basedir) {
|
3206 |
+
//
|
3207 |
+
// $directories = $directorieses[$ind];
|
3208 |
+
// if (!is_array($directories)) $directories=array($directories);
|
3209 |
+
//
|
3210 |
+
// foreach ($directories as $dir) {
|
3211 |
+
// error_log($dir);
|
3212 |
+
// if (is_file($dir)) {
|
3213 |
+
// $size += @filesize($dir);
|
3214 |
+
// } else {
|
3215 |
+
// $suffix = ('' != $basedir) ? ((0 === strpos($dir, $basedir.'/')) ? substr($dir, 1+strlen($basedir)) : '') : '';
|
3216 |
+
// $size += $this->recursive_directory_size_raw($basedir, $exclude, $suffix);
|
3217 |
+
// }
|
3218 |
+
// }
|
3219 |
+
//
|
3220 |
+
// }
|
3221 |
+
|
3222 |
if ($size > 1073741824) {
|
3223 |
return round($size / 1073741824, 1).' Gb';
|
3224 |
} elseif ($size > 1048576) {
|
3231 |
|
3232 |
}
|
3233 |
|
3234 |
+
private function recursive_directory_size_raw($prefix_directory, &$exclude = array(), $suffix_directory = '') {
|
3235 |
|
3236 |
$directory = $prefix_directory.('' == $suffix_directory ? '' : '/'.$suffix_directory);
|
3237 |
$size = 0;
|
3318 |
<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 class="updraft_existingbackup_date" data-rawbackup="$rawbackup"><b>$datespan</b>
|
3319 |
ENDHERE;
|
3320 |
|
3321 |
+
# TODO: This probably isn't showing the right thing when an incremental backup finishes
|
3322 |
if (is_array($jobdata) && !empty($jobdata['resume_interval']) && (empty($jobdata['jobstatus']) || 'finished' != $jobdata['jobstatus'])) {
|
3323 |
$ret .= apply_filters('updraftplus_msg_unfinishedbackup', "<br><span title=\"".esc_attr(__('If you are seeing more backups than you expect, then it is probably because the deletion of old backup sets does not happen until a fresh backup completes.', 'updraftplus'))."\">".__('(Not finished)', 'updraftplus').'</span>', $jobdata, $non);
|
3324 |
}
|
3491 |
# jQuery('#updraft_restore_label_wpcore').html('".esc_js($wpcore_restore_descrip)."');
|
3492 |
$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');
|
3493 |
jQuery('#updraft_restore_timestamp').val('$key'); jQuery('.updraft_restore_date').html('$show_data'); ";
|
3494 |
+
$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(''); updraft_activejobs_update(true);\">".__('Restore', 'updraftplus').'</button>';
|
3495 |
}
|
3496 |
$ret .= <<<ENDHERE
|
3497 |
</form>
|
3513 |
$messages = array();
|
3514 |
$gmt_offset = get_option('gmt_offset');
|
3515 |
|
3516 |
+
# Array of nonces keyed by filename
|
3517 |
$known_files = array();
|
3518 |
+
# Array of backup times keyed by nonce
|
3519 |
$known_nonces = array();
|
3520 |
$changes = false;
|
3521 |
|
3528 |
|
3529 |
$accept = apply_filters('updraftplus_accept_archivename', array());
|
3530 |
if (!is_array($accept)) $accept = array();
|
3531 |
+
// Process what is known from the database backup history; this means populating $known_files and $known_nonces
|
3532 |
foreach ($backup_history as $btime => $bdata) {
|
3533 |
$found_file = false;
|
3534 |
foreach ($bdata as $key => $values) {
|
3544 |
} else {
|
3545 |
$found_file = true;
|
3546 |
$known_files[$val] = $nonce;
|
3547 |
+
$known_nonces[$nonce] = (empty($known_nonces[$nonce]) || $known_nonces[$nonce]<100) ? $btime : min($btime, $known_nonces[$nonce]);
|
3548 |
}
|
3549 |
} else {
|
3550 |
$accepted = false;
|
3553 |
}
|
3554 |
if (!empty($accepted) && (false != ($btime = apply_filters('updraftplus_foreign_gettime', false, $fkey, $val))) && $btime > 0) {
|
3555 |
$found_file = true;
|
3556 |
+
# Generate a nonce; this needs to be deterministic and based on the filename only
|
3557 |
$nonce = substr(md5($val), 0, 12);
|
3558 |
$known_files[$val] = $nonce;
|
3559 |
+
$known_nonces[$nonce] = (empty($known_nonces[$nonce]) || $known_nonces[$nonce]<100) ? $btime : min($btime, $known_nonces[$nonce]);
|
3560 |
}
|
3561 |
}
|
3562 |
}
|
3571 |
$remotefiles = array();
|
3572 |
$remotesizes = array();
|
3573 |
# Scan remote storage and get back lists of files and their sizes
|
3574 |
+
# TODO: Make compatible with incremental naming
|
3575 |
if ($remotescan) {
|
3576 |
+
add_action('http_request_args', array($updraftplus, 'modify_http_options'));
|
3577 |
foreach ($updraftplus->backup_methods as $method => $desc) {
|
3578 |
require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
|
3579 |
$objname = 'UpdraftPlus_BackupModule_'.$method;
|
3605 |
}
|
3606 |
}
|
3607 |
}
|
3608 |
+
remove_action('http_request_args', array($updraftplus, 'modify_http_options'));
|
3609 |
}
|
3610 |
|
3611 |
if (!$handle = opendir($updraft_dir)) return;
|
3615 |
$accepted_foreign = false;
|
3616 |
$potmessage = false;
|
3617 |
if ('.' == $entry || '..' == $entry) continue;
|
3618 |
+
# TODO: Make compatible with Incremental naming
|
3619 |
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)) {
|
3620 |
|
3621 |
// Interpret the time as one from the blog's local timezone, rather than as UTC
|
3656 |
continue;
|
3657 |
}
|
3658 |
// The time from the filename does not include seconds. Need to identify the seconds to get the right time
|
3659 |
+
if (isset($known_nonces[$nonce])) {
|
3660 |
+
$btime_exact = $known_nonces[$nonce];
|
3661 |
+
# TODO: If the btime we had was more than 60 seconds earlier, then this must be an increment - we then need to change the $backup_history array accordingly. We can pad the '60 second' test, as there's no option to run an increment more frequently than every 4 hours (though someone could run one manually from the CLI)
|
3662 |
+
if ($btime > 100 && $btime_exact - $btime > 60 && !empty($backup_history[$btime_exact])) {
|
3663 |
+
# TODO: This needs testing
|
3664 |
+
# The code below assumes that $backup_history[$btime] is presently empty
|
3665 |
+
# Re-key array, indicating the newly-found time to be the start of the backup set
|
3666 |
+
$backup_history[$btime] = $backup_history[$btime_exact];
|
3667 |
+
unset($backup_history[$btime_exact]);
|
3668 |
+
$btime_exact = $btime;
|
3669 |
+
}
|
3670 |
+
$btime = $btime_exact;
|
3671 |
+
}
|
3672 |
if ($btime <= 100) continue;
|
3673 |
$fs = @filesize($updraft_dir.'/'.$entry);
|
3674 |
|
3677 |
if (is_array($potmessage)) $messages[$potmessage['code']] = $potmessage;
|
3678 |
}
|
3679 |
|
3680 |
+
# TODO: Code below here has not been reviewed or adjusted for compatibility with incremental backups
|
3681 |
# Make sure we have the right list of services
|
3682 |
$current_services = (!empty($backup_history[$btime]) && !empty($backup_history[$btime]['service'])) ? $backup_history[$btime]['service'] : array();
|
3683 |
if (is_string($current_services)) $current_services = array($current_services);
|
3802 |
$credentials = request_filesystem_credentials(UpdraftPlus_Options::admin_page()."?page=updraftplus&action=updraft_restore&backup_timestamp=$timestamp", '', false, false, $extra_fields);
|
3803 |
WP_Filesystem($credentials);
|
3804 |
if ( $wp_filesystem->errors->get_error_code() ) {
|
3805 |
+
echo '<p><em><a href="http://updraftplus.com/faqs/asked-ftp-details-upon-restorationmigration-updates/">'.__('Why am I seeing this?', 'updraftplus').'</a></em></p>';
|
3806 |
foreach ( $wp_filesystem->errors->get_error_messages() as $message ) show_message($message);
|
3807 |
+
exit;
|
3808 |
}
|
3809 |
|
3810 |
# Set up logging
|
3933 |
$fullpath = $updraft_dir.$file;
|
3934 |
echo sprintf(__("Looking for %s archive: file name: %s", 'updraftplus'), $type, htmlspecialchars($file))."<br>";
|
3935 |
|
3936 |
+
add_action('http_request_args', array($updraftplus, 'modify_http_options'));
|
3937 |
foreach ($service as $serv) {
|
3938 |
if(!is_readable($fullpath)) {
|
3939 |
$sd = (empty($updraftplus->backup_methods[$serv])) ? $serv : $updraftplus->backup_methods[$serv];
|
3948 |
echo '<br>';
|
3949 |
}
|
3950 |
}
|
3951 |
+
remove_action('http_request_args', array($updraftplus, 'modify_http_options'));
|
3952 |
|
3953 |
$index = ($ind == 0) ? '' : $ind;
|
3954 |
// If a file size is stored in the backup data, then verify correctness of the local file
|
4128 |
private function get_settings_keys() {
|
4129 |
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',
|
4130 |
'updraft_lastmessage', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder',
|
4131 |
+
'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_copycom', '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');
|
4132 |
}
|
4133 |
|
4134 |
}
|
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
|
3 |
if (!defined('UPDRAFTPLUS_DIR')) die('No direct access allowed');
|
4 |
-
if (!class_exists('UpdraftPlus_PclZip'))
|
5 |
|
6 |
// This file contains functions that are only needed/loaded when a backup is running (reduces memory usage on other site pages)
|
7 |
|
@@ -250,7 +250,7 @@ class UpdraftPlus_Backup {
|
|
250 |
|
251 |
$updraftplus->jobdata_set('jobstatus', 'clouduploading');
|
252 |
|
253 |
-
add_action('
|
254 |
|
255 |
$upload_status = $updraftplus->jobdata_get('uploading_substatus');
|
256 |
if (!is_array($upload_status) || !isset($upload_status['t'])) {
|
@@ -311,7 +311,7 @@ class UpdraftPlus_Backup {
|
|
311 |
|
312 |
if (!empty($do_prune)) $this->prune_retained_backups($do_prune);
|
313 |
|
314 |
-
remove_action('
|
315 |
|
316 |
}
|
317 |
|
@@ -549,7 +549,7 @@ class UpdraftPlus_Backup {
|
|
549 |
|
550 |
# The class_exists() check here is a micro-optimization to prevent a possible HTTP call whose results may be disregarded by the filter
|
551 |
$feed = '';
|
552 |
-
if (!class_exists('UpdraftPlus_Addon_Reporting') && !defined('
|
553 |
$updraftplus->log('Fetching RSS news feed');
|
554 |
$rss = $updraftplus->get_updraftplus_rssfeed();
|
555 |
$updraftplus->log('Fetched RSS news feed; result is a: '.get_class($rss));
|
@@ -645,7 +645,7 @@ class UpdraftPlus_Backup {
|
|
645 |
|
646 |
global $updraftplus;
|
647 |
if ($a == $b) return 0;
|
648 |
-
$our_table_prefix = $this->
|
649 |
if ($a == $our_table_prefix.'options') return -1;
|
650 |
if ($b == $our_table_prefix.'options') return 1;
|
651 |
if ($a == $our_table_prefix.'users') return -1;
|
@@ -1037,13 +1037,15 @@ class UpdraftPlus_Backup {
|
|
1037 |
}
|
1038 |
|
1039 |
# If no check-in last time, then we could in future try the other method (but - any point in retrying slow method on large tables??)
|
1040 |
-
|
|
|
|
|
|
|
|
|
1041 |
if (true !== $bindump) $this->backup_table($table, $where);
|
1042 |
|
1043 |
if (!empty($manyrows_warning)) $updraftplus->log_removewarning('manyrows_'.$this->whichdb_suffix.$table);
|
1044 |
|
1045 |
-
// Close file
|
1046 |
-
|
1047 |
$this->close();
|
1048 |
|
1049 |
$updraftplus->log("Table $table: finishing file (${table_file_prefix}.gz - ".round(filesize($this->updraft_dir.'/'.$table_file_prefix.'.tmp.gz')/1024,1)." Kb)");
|
@@ -1275,7 +1277,8 @@ class UpdraftPlus_Backup {
|
|
1275 |
|
1276 |
$increment = 1000;
|
1277 |
if (!$updraftplus->something_useful_happened && !empty($updraftplus->current_resumption) && ($updraftplus->current_resumption - $updraftplus->last_successful_resumption > 1)) {
|
1278 |
-
|
|
|
1279 |
}
|
1280 |
|
1281 |
if($segment == 'none') {
|
@@ -1463,7 +1466,7 @@ class UpdraftPlus_Backup {
|
|
1463 |
|
1464 |
// Is the place we've ended up above the original base? That leads to infinite recursion
|
1465 |
if (($fullpath !== $original_fullpath && strpos($original_fullpath, $fullpath) === 0) || ($original_fullpath == $fullpath && ((1== $startlevels && strpos($use_path_when_storing, '/') !== false) || (2 == $startlevels && substr_count($use_path_when_storing, '/') >1)))) {
|
1466 |
-
$updraftplus->log("Infinite recursion: symlink
|
1467 |
$updraftplus->log(__("Infinite recursion: consult your log for more information",'updraftplus'), 'error');
|
1468 |
return false;
|
1469 |
}
|
@@ -1481,7 +1484,7 @@ class UpdraftPlus_Backup {
|
|
1481 |
if (is_file($fullpath)) {
|
1482 |
if (is_readable($fullpath)) {
|
1483 |
$mtime = filemtime($fullpath);
|
1484 |
-
$key = ($fullpath == $original_fullpath) ? ((2 == $startlevels) ? $use_path_when_storing : basename($fullpath)) : $use_path_when_storing.'/'
|
1485 |
if ($mtime > 0 && $mtime > $if_altered_since) {
|
1486 |
$this->zipfiles_batched[$fullpath] = $key;
|
1487 |
$this->makezip_recursive_batchedbytes += @filesize($fullpath);
|
@@ -1681,9 +1684,10 @@ class UpdraftPlus_Backup {
|
|
1681 |
#makezip_recursive_add($fullpath, $use_path_when_storing, $original_fullpath, $startlevels = 1, $exclude_array)
|
1682 |
if ('uploads' == $whichone) {
|
1683 |
$dirname = dirname($element);
|
1684 |
-
$
|
|
|
1685 |
} else {
|
1686 |
-
$add_them = $this->makezip_recursive_add($element, basename($element), $element, 1, $exclude);
|
1687 |
}
|
1688 |
if (is_wp_error($add_them) || false === $add_them) $error_occurred = true;
|
1689 |
}
|
@@ -1736,6 +1740,23 @@ class UpdraftPlus_Backup {
|
|
1736 |
|
1737 |
}
|
1738 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1739 |
// Q. Why don't we only open and close the zip file just once?
|
1740 |
// A. Because apparently PHP doesn't write out until the final close, and it will return an error if anything file has vanished in the meantime. So going directory-by-directory reduces our chances of hitting an error if the filesystem is changing underneath us (which is very possible if dealing with e.g. 1Gb of files)
|
1741 |
|
@@ -1759,44 +1780,43 @@ class UpdraftPlus_Backup {
|
|
1759 |
# If on PclZip, then if possible short-circuit to a quicker method (makes a huge time difference - on a folder of 1500 small files, 2.6s instead of 76.6)
|
1760 |
# This assumes that makezip_addfiles() is only called once so that we know about all needed files (the new style)
|
1761 |
# This is rather conservative - because it assumes zero compression. But we can't know that in advance.
|
1762 |
-
|
1763 |
-
|
1764 |
-
|
1765 |
-
|
1766 |
-
|
1767 |
-
|
1768 |
-
$
|
1769 |
-
|
1770 |
-
|
1771 |
-
|
1772 |
-
|
1773 |
-
|
1774 |
-
|
1775 |
-
|
1776 |
-
|
1777 |
-
|
1778 |
-
|
1779 |
-
|
1780 |
-
|
1781 |
-
|
1782 |
-
|
1783 |
-
|
1784 |
-
|
1785 |
-
|
1786 |
-
|
1787 |
-
|
1788 |
-
|
1789 |
-
|
1790 |
-
|
1791 |
-
|
1792 |
-
|
1793 |
-
|
1794 |
-
|
1795 |
-
|
1796 |
-
|
1797 |
-
|
1798 |
-
|
1799 |
-
return true;
|
1800 |
}
|
1801 |
}
|
1802 |
|
@@ -1818,15 +1838,13 @@ class UpdraftPlus_Backup {
|
|
1818 |
}
|
1819 |
|
1820 |
if ($opencode !== true) return new WP_Error('no_open', sprintf(__('Failed to open the zip file (%s) - %s', 'updraftplus'),$zipfile, $zip->last_error));
|
1821 |
-
|
1822 |
-
|
1823 |
-
$zip->addEmptyDir($dir);
|
1824 |
-
}
|
1825 |
|
|
|
|
|
1826 |
$zipfiles_added_thisbatch = 0;
|
1827 |
|
1828 |
-
do_action("updraftplus_makezip_addfiles_prepack", $this, $this->whichone);
|
1829 |
-
|
1830 |
// Go through all those batched files
|
1831 |
foreach ($this->zipfiles_batched as $file => $add_as) {
|
1832 |
|
@@ -1848,7 +1866,7 @@ class UpdraftPlus_Backup {
|
|
1848 |
$data_added_since_reopen += $fsize;
|
1849 |
/* Conditions for forcing a write-out and re-open:
|
1850 |
- more than $maxzipbatch bytes have been batched
|
1851 |
-
- more than
|
1852 |
- that adding this batch of data is likely already enough to take us over the split limit (and if that happens, then do actually split - to prevent a scenario of progressively tinier writes as we approach but don't actually reach the limit)
|
1853 |
- more than 500 files batched (should perhaps intelligently lower this as the zip file gets bigger - not yet needed)
|
1854 |
*/
|
@@ -1857,7 +1875,7 @@ class UpdraftPlus_Backup {
|
|
1857 |
# Since we don't test before the file has been created (so that zip_last_ratio has meaningful data), we rely on max_zip_batch being less than zip_split_every - which should always be the case
|
1858 |
$reaching_split_limit = ( $this->zip_last_ratio > 0 && $original_size>0 && ($original_size + 1.1*$data_added_since_reopen*$this->zip_last_ratio) > $this->zip_split_every) ? true : false;
|
1859 |
|
1860 |
-
if ($zipfiles_added_thisbatch > UPDRAFTPLUS_MAXBATCHFILES || $reaching_split_limit || $data_added_since_reopen > $maxzipbatch || (time() - $this->zipfiles_lastwritetime) >
|
1861 |
|
1862 |
@set_time_limit(900);
|
1863 |
$something_useful_sizetest = false;
|
@@ -1868,7 +1886,7 @@ class UpdraftPlus_Backup {
|
|
1868 |
} elseif ($zipfiles_added_thisbatch > UPDRAFTPLUS_MAXBATCHFILES) {
|
1869 |
$updraftplus->log("Adding batch to zip file (".$this->use_zip_object."): over ".UPDRAFTPLUS_MAXBATCHFILES." files added on this batch (".round($data_added_since_reopen/1048576,1)." Mb, ".count($this->zipfiles_batched)." files batched, $zipfiles_added_thisbatch (".$this->zipfiles_added_thisrun.") added so far); re-opening (prior size: ".round($original_size/1024,1).' Kb)');
|
1870 |
} elseif (!$reaching_split_limit) {
|
1871 |
-
$updraftplus->log("Adding batch to zip file (".$this->use_zip_object."): over
|
1872 |
} else {
|
1873 |
$updraftplus->log("Adding batch to zip file (".$this->use_zip_object."): possibly approaching split limit (".round($data_added_since_reopen/1048576,1)." Mb, $zipfiles_added_thisbatch (".$this->zipfiles_added_thisrun.") files added so far); last ratio: ".round($this->zip_last_ratio,4)."; re-opening (prior size: ".round($original_size/1024,1).' Kb)');
|
1874 |
}
|
@@ -1887,7 +1905,7 @@ class UpdraftPlus_Backup {
|
|
1887 |
// Call here, in case we've got so many big files that we don't complete the whole routine
|
1888 |
if (filesize($zipfile) > $original_size) {
|
1889 |
|
1890 |
-
# It is essential that this does not go above 1, even though in reality (and this can happen at the start, if just 1 file is added (e.g. due to >
|
1891 |
$this->zip_last_ratio = ($data_added_since_reopen > 0) ? min((filesize($zipfile) - $original_size)/$data_added_since_reopen, 1) : 1;
|
1892 |
|
1893 |
# We need a rolling update of this
|
@@ -2029,7 +2047,7 @@ class UpdraftPlus_Backup {
|
|
2029 |
$this->zipfiles_lastwritetime = time();
|
2030 |
}
|
2031 |
} elseif (0 == $this->zipfiles_added_thisrun) {
|
2032 |
-
// Update lastwritetime, because otherwise the
|
2033 |
// Testing shows that calling time() 1000 times takes negligible time
|
2034 |
$this->zipfiles_lastwritetime=time();
|
2035 |
}
|
@@ -2058,7 +2076,7 @@ class UpdraftPlus_Backup {
|
|
2058 |
$original_size = 0;
|
2059 |
}
|
2060 |
|
2061 |
-
if ($opencode !== true) return new WP_Error('no_open', sprintf(__('Failed to open the zip file (%s) - %s', 'updraftplus')
|
2062 |
}
|
2063 |
|
2064 |
}
|
1 |
<?php
|
2 |
|
3 |
if (!defined('UPDRAFTPLUS_DIR')) die('No direct access allowed');
|
4 |
+
if (!class_exists('UpdraftPlus_PclZip')) require_once(UPDRAFTPLUS_DIR.'/class-zip.php');
|
5 |
|
6 |
// This file contains functions that are only needed/loaded when a backup is running (reduces memory usage on other site pages)
|
7 |
|
250 |
|
251 |
$updraftplus->jobdata_set('jobstatus', 'clouduploading');
|
252 |
|
253 |
+
add_action('http_request_args', array($updraftplus, 'modify_http_options'));
|
254 |
|
255 |
$upload_status = $updraftplus->jobdata_get('uploading_substatus');
|
256 |
if (!is_array($upload_status) || !isset($upload_status['t'])) {
|
311 |
|
312 |
if (!empty($do_prune)) $this->prune_retained_backups($do_prune);
|
313 |
|
314 |
+
remove_action('http_request_args', array($updraftplus, 'modify_http_options'));
|
315 |
|
316 |
}
|
317 |
|
549 |
|
550 |
# The class_exists() check here is a micro-optimization to prevent a possible HTTP call whose results may be disregarded by the filter
|
551 |
$feed = '';
|
552 |
+
if (!class_exists('UpdraftPlus_Addon_Reporting') && !defined('UPDRAFTPLUS_NOADS_B') && !defined('UPDRAFTPLUS_NONEWSFEED')) {
|
553 |
$updraftplus->log('Fetching RSS news feed');
|
554 |
$rss = $updraftplus->get_updraftplus_rssfeed();
|
555 |
$updraftplus->log('Fetched RSS news feed; result is a: '.get_class($rss));
|
645 |
|
646 |
global $updraftplus;
|
647 |
if ($a == $b) return 0;
|
648 |
+
$our_table_prefix = $this->table_prefix_raw;
|
649 |
if ($a == $our_table_prefix.'options') return -1;
|
650 |
if ($b == $our_table_prefix.'options') return 1;
|
651 |
if ($a == $our_table_prefix.'users') return -1;
|
1037 |
}
|
1038 |
|
1039 |
# If no check-in last time, then we could in future try the other method (but - any point in retrying slow method on large tables??)
|
1040 |
+
|
1041 |
+
# New Jul 2014: This attempt to use bindump instead at a lower threshold is quite conservative - only if the last successful run was exactly two resumptions ago - may be useful to expand
|
1042 |
+
$bindump_threshold = (!$updraftplus->something_useful_happened && !empty($updraftplus->current_resumption) && ($updraftplus->current_resumption - $updraftplus->last_successful_resumption == 2 )) ? 1000 : 8000;
|
1043 |
+
|
1044 |
+
$bindump = (isset($rows) && ($rows>$bindump_threshold || (defined('UPDRAFTPLUS_ALWAYS_TRY_MYSQLDUMP') && UPDRAFTPLUS_ALWAYS_TRY_MYSQLDUMP)) && is_string($binsqldump)) ? $this->backup_table_bindump($binsqldump, $table, $where) : false;
|
1045 |
if (true !== $bindump) $this->backup_table($table, $where);
|
1046 |
|
1047 |
if (!empty($manyrows_warning)) $updraftplus->log_removewarning('manyrows_'.$this->whichdb_suffix.$table);
|
1048 |
|
|
|
|
|
1049 |
$this->close();
|
1050 |
|
1051 |
$updraftplus->log("Table $table: finishing file (${table_file_prefix}.gz - ".round(filesize($this->updraft_dir.'/'.$table_file_prefix.'.tmp.gz')/1024,1)." Kb)");
|
1277 |
|
1278 |
$increment = 1000;
|
1279 |
if (!$updraftplus->something_useful_happened && !empty($updraftplus->current_resumption) && ($updraftplus->current_resumption - $updraftplus->last_successful_resumption > 1)) {
|
1280 |
+
# This used to be fixed at 500; but we (after a long time) saw a case that looked like an out-of-memory even at this level. We must be careful about going too low, though - otherwise we increase the risks of timeouts.
|
1281 |
+
$increment = ( $updraftplus->current_resumption - $updraftplus->last_successful_resumption > 2 ) ? 350 : 500;
|
1282 |
}
|
1283 |
|
1284 |
if($segment == 'none') {
|
1466 |
|
1467 |
// Is the place we've ended up above the original base? That leads to infinite recursion
|
1468 |
if (($fullpath !== $original_fullpath && strpos($original_fullpath, $fullpath) === 0) || ($original_fullpath == $fullpath && ((1== $startlevels && strpos($use_path_when_storing, '/') !== false) || (2 == $startlevels && substr_count($use_path_when_storing, '/') >1)))) {
|
1469 |
+
$updraftplus->log("Infinite recursion: symlink led us to $fullpath, which is within $original_fullpath");
|
1470 |
$updraftplus->log(__("Infinite recursion: consult your log for more information",'updraftplus'), 'error');
|
1471 |
return false;
|
1472 |
}
|
1484 |
if (is_file($fullpath)) {
|
1485 |
if (is_readable($fullpath)) {
|
1486 |
$mtime = filemtime($fullpath);
|
1487 |
+
$key = ($fullpath == $original_fullpath) ? ((2 == $startlevels) ? $use_path_when_storing : $this->basename($fullpath)) : $use_path_when_storing.'/'.$this->basename($fullpath);
|
1488 |
if ($mtime > 0 && $mtime > $if_altered_since) {
|
1489 |
$this->zipfiles_batched[$fullpath] = $key;
|
1490 |
$this->makezip_recursive_batchedbytes += @filesize($fullpath);
|
1684 |
#makezip_recursive_add($fullpath, $use_path_when_storing, $original_fullpath, $startlevels = 1, $exclude_array)
|
1685 |
if ('uploads' == $whichone) {
|
1686 |
$dirname = dirname($element);
|
1687 |
+
$basename = $this->basename($element);
|
1688 |
+
$add_them = $this->makezip_recursive_add($element, basename($dirname).'/'.$basename, $element, 2, $exclude);
|
1689 |
} else {
|
1690 |
+
$add_them = $this->makezip_recursive_add($element, $this->basename($element), $element, 1, $exclude);
|
1691 |
}
|
1692 |
if (is_wp_error($add_them) || false === $add_them) $error_occurred = true;
|
1693 |
}
|
1740 |
|
1741 |
}
|
1742 |
|
1743 |
+
private function basename($element) {
|
1744 |
+
# This function is an ugly, conservative workaround for https://bugs.php.net/bug.php?id=62119. It does not aim to always work-around, but to ensure that nothing is made worse.
|
1745 |
+
$dirname = dirname($element);
|
1746 |
+
$basename_manual = preg_replace('#^[\\/]+#', '', substr($element, strlen($dirname)));
|
1747 |
+
$basename = basename($element);
|
1748 |
+
if ($basename_manual != $basename) {
|
1749 |
+
$locale = setlocale(LC_CTYPE, "0");
|
1750 |
+
if ('C' == $locale) {
|
1751 |
+
setlocale(LC_CTYPE, 'en_US.UTF8');
|
1752 |
+
$basename_new = basename($element);
|
1753 |
+
if ($basename_new == $basename_manual) $basename = $basename_new;
|
1754 |
+
setlocale(LC_CTYPE, $locale);
|
1755 |
+
}
|
1756 |
+
}
|
1757 |
+
return $basename;
|
1758 |
+
}
|
1759 |
+
|
1760 |
// Q. Why don't we only open and close the zip file just once?
|
1761 |
// A. Because apparently PHP doesn't write out until the final close, and it will return an error if anything file has vanished in the meantime. So going directory-by-directory reduces our chances of hitting an error if the filesystem is changing underneath us (which is very possible if dealing with e.g. 1Gb of files)
|
1762 |
|
1780 |
# If on PclZip, then if possible short-circuit to a quicker method (makes a huge time difference - on a folder of 1500 small files, 2.6s instead of 76.6)
|
1781 |
# This assumes that makezip_addfiles() is only called once so that we know about all needed files (the new style)
|
1782 |
# This is rather conservative - because it assumes zero compression. But we can't know that in advance.
|
1783 |
+
$force_allinone = false;
|
1784 |
+
if (0 == $this->index && $this->makezip_recursive_batchedbytes < $this->zip_split_every) {
|
1785 |
+
# So far, we only have a processor for this for PclZip; but that check can be removed - need to address the below items
|
1786 |
+
# TODO: Is this really what we want? Always go all-in-one for < 500Mb???? Should be more conservative? Or, is it always faster to go all-in-one? What about situations where we might want to auto-split because of slowness - check that that is still working.
|
1787 |
+
# TODO: Test this new method for PclZip - are we still getting the performance gains? Test for ZipArchive too.
|
1788 |
+
# TODO: Test that we get a manifest for PclZip on increments when on all-in-one
|
1789 |
+
if ('UpdraftPlus_PclZip' == $this->use_zip_object && ($this->makezip_recursive_batchedbytes < 512*1048576 || (defined('UPDRAFTPLUS_PCLZIP_FORCEALLINONE') && UPDRAFTPLUS_PCLZIP_FORCEALLINONE == true && 'UpdraftPlus_PclZip' == $this->use_zip_object))) {
|
1790 |
+
$updraftplus->log("Only one archive required (".$this->use_zip_object.") - will attempt to do in single operation (data: ".round($this->makezip_recursive_batchedbytes/1024,1)." Kb, split: ".round($this->zip_split_every/1024, 1)." Kb)");
|
1791 |
+
// $updraftplus->log("PclZip, and only one archive required - will attempt to do in single operation (data: ".round($this->makezip_recursive_batchedbytes/1024,1)." Kb, split: ".round($this->zip_split_every/1024, 1)." Kb)");
|
1792 |
+
$force_allinone = true;
|
1793 |
+
// if(!class_exists('PclZip')) require_once(ABSPATH.'/wp-admin/includes/class-pclzip.php');
|
1794 |
+
// $zip = new PclZip($zipfile);
|
1795 |
+
// $remove_path = ($this->whichone == 'wpcore') ? untrailingslashit(ABSPATH) : WP_CONTENT_DIR;
|
1796 |
+
// $add_path = false;
|
1797 |
+
// // Remove prefixes
|
1798 |
+
// $backupable_entities = $updraftplus->get_backupable_file_entities(true);
|
1799 |
+
// if (isset($backupable_entities[$this->whichone])) {
|
1800 |
+
// if ('plugins' == $this->whichone || 'themes' == $this->whichone || 'uploads' == $this->whichone) {
|
1801 |
+
// $remove_path = dirname($backupable_entities[$this->whichone]);
|
1802 |
+
// # To normalise instead of removing (which binzip doesn't support, so we don't do it), you'd remove the dirname() in the above line, and uncomment the below one.
|
1803 |
+
// #$add_path = $this->whichone;
|
1804 |
+
// } else {
|
1805 |
+
// $remove_path = $backupable_entities[$this->whichone];
|
1806 |
+
// }
|
1807 |
+
// }
|
1808 |
+
// if ($add_path) {
|
1809 |
+
// $zipcode = $zip->create($this->source, PCLZIP_OPT_REMOVE_PATH, $remove_path, PCLZIP_OPT_ADD_PATH, $add_path);
|
1810 |
+
// } else {
|
1811 |
+
// $zipcode = $zip->create($this->source, PCLZIP_OPT_REMOVE_PATH, $remove_path);
|
1812 |
+
// }
|
1813 |
+
// if ($zipcode == 0) {
|
1814 |
+
// $updraftplus->log("PclZip Error: ".$zip->errorInfo(true), 'warning');
|
1815 |
+
// return $zip->errorCode();
|
1816 |
+
// } else {
|
1817 |
+
// $updraftplus->something_useful_happened();
|
1818 |
+
// return true;
|
1819 |
+
// }
|
|
|
1820 |
}
|
1821 |
}
|
1822 |
|
1838 |
}
|
1839 |
|
1840 |
if ($opencode !== true) return new WP_Error('no_open', sprintf(__('Failed to open the zip file (%s) - %s', 'updraftplus'),$zipfile, $zip->last_error));
|
1841 |
+
# TODO: This action isn't being called for the all-in-one case - should be, I think
|
1842 |
+
do_action("updraftplus_makezip_addfiles_prepack", $this, $this->whichone);
|
|
|
|
|
1843 |
|
1844 |
+
// Make sure all directories are created before we start creating files
|
1845 |
+
while ($dir = array_pop($this->zipfiles_dirbatched)) $zip->addEmptyDir($dir);
|
1846 |
$zipfiles_added_thisbatch = 0;
|
1847 |
|
|
|
|
|
1848 |
// Go through all those batched files
|
1849 |
foreach ($this->zipfiles_batched as $file => $add_as) {
|
1850 |
|
1866 |
$data_added_since_reopen += $fsize;
|
1867 |
/* Conditions for forcing a write-out and re-open:
|
1868 |
- more than $maxzipbatch bytes have been batched
|
1869 |
+
- more than 2.0 seconds have passed since the last time we wrote
|
1870 |
- that adding this batch of data is likely already enough to take us over the split limit (and if that happens, then do actually split - to prevent a scenario of progressively tinier writes as we approach but don't actually reach the limit)
|
1871 |
- more than 500 files batched (should perhaps intelligently lower this as the zip file gets bigger - not yet needed)
|
1872 |
*/
|
1875 |
# Since we don't test before the file has been created (so that zip_last_ratio has meaningful data), we rely on max_zip_batch being less than zip_split_every - which should always be the case
|
1876 |
$reaching_split_limit = ( $this->zip_last_ratio > 0 && $original_size>0 && ($original_size + 1.1*$data_added_since_reopen*$this->zip_last_ratio) > $this->zip_split_every) ? true : false;
|
1877 |
|
1878 |
+
if (!$force_allinone && ($zipfiles_added_thisbatch > UPDRAFTPLUS_MAXBATCHFILES || $reaching_split_limit || $data_added_since_reopen > $maxzipbatch || (time() - $this->zipfiles_lastwritetime) > 2)) {
|
1879 |
|
1880 |
@set_time_limit(900);
|
1881 |
$something_useful_sizetest = false;
|
1886 |
} elseif ($zipfiles_added_thisbatch > UPDRAFTPLUS_MAXBATCHFILES) {
|
1887 |
$updraftplus->log("Adding batch to zip file (".$this->use_zip_object."): over ".UPDRAFTPLUS_MAXBATCHFILES." files added on this batch (".round($data_added_since_reopen/1048576,1)." Mb, ".count($this->zipfiles_batched)." files batched, $zipfiles_added_thisbatch (".$this->zipfiles_added_thisrun.") added so far); re-opening (prior size: ".round($original_size/1024,1).' Kb)');
|
1888 |
} elseif (!$reaching_split_limit) {
|
1889 |
+
$updraftplus->log("Adding batch to zip file (".$this->use_zip_object."): over 2.0 seconds have passed since the last write (".round($data_added_since_reopen/1048576,1)." Mb, $zipfiles_added_thisbatch (".$this->zipfiles_added_thisrun.") files added so far); re-opening (prior size: ".round($original_size/1024,1).' Kb)');
|
1890 |
} else {
|
1891 |
$updraftplus->log("Adding batch to zip file (".$this->use_zip_object."): possibly approaching split limit (".round($data_added_since_reopen/1048576,1)." Mb, $zipfiles_added_thisbatch (".$this->zipfiles_added_thisrun.") files added so far); last ratio: ".round($this->zip_last_ratio,4)."; re-opening (prior size: ".round($original_size/1024,1).' Kb)');
|
1892 |
}
|
1905 |
// Call here, in case we've got so many big files that we don't complete the whole routine
|
1906 |
if (filesize($zipfile) > $original_size) {
|
1907 |
|
1908 |
+
# It is essential that this does not go above 1, even though in reality (and this can happen at the start, if just 1 file is added (e.g. due to >2.0s detection) the 'compressed' zip file may be *bigger* than the files stored in it. When that happens, if the ratio is big enough, it can then fire the "approaching split limit" detection (very) prematurely
|
1909 |
$this->zip_last_ratio = ($data_added_since_reopen > 0) ? min((filesize($zipfile) - $original_size)/$data_added_since_reopen, 1) : 1;
|
1910 |
|
1911 |
# We need a rolling update of this
|
2047 |
$this->zipfiles_lastwritetime = time();
|
2048 |
}
|
2049 |
} elseif (0 == $this->zipfiles_added_thisrun) {
|
2050 |
+
// Update lastwritetime, because otherwise the 2.0-second-activity detection can fire prematurely (e.g. if it takes >2.0 seconds to process the previously-written files, then the detector fires after 1 file. This then can have the knock-on effect of having something_useful_happened() called, but then a subsequent attempt to write out a lot of meaningful data fails, and the maximum batch is not then reduced.
|
2051 |
// Testing shows that calling time() 1000 times takes negligible time
|
2052 |
$this->zipfiles_lastwritetime=time();
|
2053 |
}
|
2076 |
$original_size = 0;
|
2077 |
}
|
2078 |
|
2079 |
+
if ($opencode !== true) return new WP_Error('no_open', sprintf(__('Failed to open the zip file (%s) - %s', 'updraftplus'), $zipfile, $zip->last_error));
|
2080 |
}
|
2081 |
|
2082 |
}
|
@@ -0,0 +1,2494 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|