UpdraftPlus WordPress Backup Plugin - Version 1.9.25

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)

Download this release

Release Info

Developer DavidAnderson
Plugin Icon 128x128 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 CHANGED
@@ -2,9 +2,7 @@
2
 
3
  if (!defined ('ABSPATH')) die('No direct access allowed');
4
 
5
- // For the purposes of improving site performance (don't load in 10s of Kilobytes of un-needed code on every page load), admin-area code lives here
6
-
7
- // This gets called in admin_menu, earlier than admin_init
8
 
9
  global $updraftplus_admin;
10
  if (!is_a($updraftplus_admin, 'UpdraftPlus_Admin')) $updraftplus_admin = new UpdraftPlus_Admin();
@@ -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() && ('dropbox' === $service || is_array($service) && in_array('dropbox', $service))) {
54
- $opts = UpdraftPlus_Options::get_updraft_option('updraft_dropbox');
55
- if (empty($opts['tk_request_token'])) {
56
- add_action('all_admin_notices', array($this,'show_admin_warning_dropbox') );
 
 
57
  }
 
 
 
 
 
 
 
 
 
58
  }
59
 
60
- if (UpdraftPlus_Options::user_can_manage() && ('bitcasa' === $service || is_array($service) && in_array('bitcasa', $service))) {
61
- $opts = UpdraftPlus_Options::get_updraft_option('updraft_bitcasa');
62
- if (!empty($opts['clientid']) && !empty($opts['secret']) && empty($opts['token'])) add_action('all_admin_notices', array($this,'show_admin_warning_bitcasa') );
63
- }
64
-
65
- if (UpdraftPlus_Options::user_can_manage() && $this->disk_space_check(1048576*35) === false) add_action('all_admin_notices', array($this, 'show_admin_warning_diskspace'));
66
-
67
  // Next, the actions that only come on the UpdraftPlus page
68
  if ($pagenow != UpdraftPlus_Options::admin_page() || empty($_REQUEST['page']) || 'updraftplus' != $_REQUEST['page']) return;
69
 
@@ -172,7 +174,7 @@ class UpdraftPlus_Admin {
172
 
173
  public function core_upgrade_preamble() {
174
  if (!class_exists('UpdraftPlus_Addon_Autobackup')) {
175
- if (defined('UPDRAFTPLUS_NOADS_A')) return;
176
  # TODO: Remove legacy/wrong use of transient any time from 1 Jun 2014
177
  if (true == get_transient('updraftplus_dismissedautobackup')) return;
178
  $dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismissedautobackup', 0);
@@ -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('UPDRAFTPLUS_NOADS_A')) {
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 &quot;Backup Now&quot;) unless either you have set up a facility to call the scheduler manually, or until it is enabled.','updraftplus').' <a href="http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/#disablewpcron">'.__('Go here for more information.','updraftplus').'</a>');
425
  }
426
 
427
  public function show_admin_warning_diskspace() {
@@ -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>'.__('Schedule backup','updraftplus').':</strong> '.htmlspecialchars(__('OK. You should soon see activity in the "Last log message" field below.','updraftplus'));
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]+,)?/', $buffer, $matches)) {
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
- // check ajax nonce
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="http://updraftplus.com/news/"><?php _e('News','updraftplus');?></a> | <?php if (!defined('UPDRAFTPLUS_NOADS_A')) { ?><a href="http://updraftplus.com/shop/updraftplus-premium/"><?php _e("Premium",'updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/"><?php _e("Support",'updraftplus');?></a> | <a href="http://david.dw-perspective.org.uk"><?php _e("Lead developer's homepage",'updraftplus');?></a> | <?php if (1==0 && !defined('UPDRAFTPLUS_NOADS_A')) { ?><a href="http://wordshell.net">WordShell - WordPress command line</a> | <a href="http://david.dw-perspective.org.uk/donate"><?php _e('Donate', 'updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/frequently-asked-questions/">FAQs</a> | <a href="https://www.simbahosting.co.uk/s3/shop/"><?php _e('More plugins', 'updraftplus');?></a> - <?php _e('Version','updraftplus');?>: <?php echo $updraftplus->version; ?>
 
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('UPDRAFTPLUS_NOADS_A')) {
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 _e('Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below.','updraftplus'); ?>"><?php _e('Rescan local folder for new backup sets','updraftplus');?></a>
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>(calculating...)</em></span> <a href="#" onclick="updraftplus_diskspace(); return false;"><?php _e('refresh','updraftplus');?></a></li></ul>
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.'"></div>';
 
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
- return new WP_Error('writable_error', __('The folder exists, but your webserver does not have permission to write to it.', 'updraftplus').' '.__('You will need to consult with your web hosting provider to find out to set permissions for a WordPress plugin to write to the directory.', 'updraftplus'));
 
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) { if (preg_match('/-old$/', $dir)) return true; }
 
 
 
 
 
2640
  # No need to scan ABSPATH - we don't backup there
2641
- if (is_dir(untrailingslashit(WP_PLUGIN_DIR).'-old')) return true;
 
 
 
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. Backups will occur at the intervals specified. If the two schedules are the same, then the two backups will take place together. If you choose "manual" then you must click the "Backup Now" button whenever you wish a backup to occur.', 'updraftplus')); ?></p>
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('UPDRAFTPLUS_NOADS_A')) echo '<p><a href="http://wordshell.net">('.__('Use WordShell for automatic backup, version control and patching', 'updraftplus').').</a></p>';?>
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', 1*800);
3014
- if (!is_numeric($split_every_mb)) $split_every_mb = 1*800;
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 _e('UpdraftPlus will split up backup archives when they exceed this file size. The default value is 800 megabytes. Be careful to leave some margin if your web-server has a hard size limit (e.g. the 2 Gb / 2048 Mb limit on some 32-bit servers/file systems).','updraftplus'); ?></td>
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 ($basedirs as $ind => $basedir) {
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
- // Accumulate a list of known files in the database backup history
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])) $btime = $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 &quot;Backup Now&quot;) unless either you have set up a facility to call the scheduler manually, or until it is enabled.','updraftplus').' <a href="http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/#disablewpcron">'.__('Go here for more information.','updraftplus').'</a>', '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
  }
backup.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
 
3
  if (!defined('UPDRAFTPLUS_DIR')) die('No direct access allowed');
4
- if (!class_exists('UpdraftPlus_PclZip')) require(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,7 +250,7 @@ class UpdraftPlus_Backup {
250
 
251
  $updraftplus->jobdata_set('jobstatus', 'clouduploading');
252
 
253
- add_action('http_api_curl', array($updraftplus, 'add_curl_capath'));
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('http_api_curl', array($updraftplus, 'add_curl_capath'));
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('UPDRAFTPLUS_NOADS_A') && !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,7 +645,7 @@ class UpdraftPlus_Backup {
645
 
646
  global $updraftplus;
647
  if ($a == $b) return 0;
648
- $our_table_prefix = $this->table_prefix;
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
- $bindump = (isset($rows) && $rows>8000 && is_string($binsqldump)) ? $this->backup_table_bindump($binsqldump, $table, $where) : false;
 
 
 
 
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
- $increment = 500;
 
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 lead us to $fullpath, which is within $original_fullpath");
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.'/'.basename($fullpath);
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
- $add_them = $this->makezip_recursive_add($element, basename($dirname).'/'.basename($element), $element, 2, $exclude);
 
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
- if (0 == $this->index && 'UpdraftPlus_PclZip' == $this->use_zip_object && $this->makezip_recursive_batchedbytes < $this->zip_split_every && ($this->makezip_recursive_batchedbytes < 512*1024*1024 || (defined('UPDRAFTPLUS_PCLZIP_FORCEALLINONE') && UPDRAFTPLUS_PCLZIP_FORCEALLINONE == true))) {
1765
- $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)");
1766
- if(!class_exists('PclZip')) require_once(ABSPATH.'/wp-admin/includes/class-pclzip.php');
1767
- $zip = new PclZip($zipfile);
1768
- $remove_path = ($this->whichone == 'wpcore') ? untrailingslashit(ABSPATH) : (($this->whichone == 'more' && is_string($this->source)) ? dirname($this->source) : WP_CONTENT_DIR);
1769
- $add_path = false;
1770
- // Remove prefixes
1771
- $backupable_entities = $updraftplus->get_backupable_file_entities(true);
1772
- if (isset($backupable_entities[$this->whichone])) {
1773
- if ('plugins' == $this->whichone || 'themes' == $this->whichone || 'uploads' == $this->whichone) {
1774
- $remove_path = dirname($backupable_entities[$this->whichone]);
1775
- # 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.
1776
- #$add_path = $this->whichone;
1777
- } elseif ('more' == $this->whichone) {
1778
- if (is_string($this->source)) {
1779
- $remove_path = dirname($this->source);
1780
- } elseif (is_array($this->source) && count($this->source) === 1) {
1781
- $remove_path = dirname($this->source[0]);
1782
- } else {
1783
- $remove_path = '';
1784
- }
1785
- } else {
1786
- $remove_path = $backupable_entities[$this->whichone];
1787
- }
1788
- }
1789
- if ($add_path) {
1790
- $zipcode = $zip->create($this->source, PCLZIP_OPT_REMOVE_PATH, $remove_path, PCLZIP_OPT_ADD_PATH, $add_path);
1791
- } else {
1792
- $zipcode = $zip->create($this->source, PCLZIP_OPT_REMOVE_PATH, $remove_path);
1793
- }
1794
- if ($zipcode == 0 ) {
1795
- $updraftplus->log("PclZip Error: ".$zip->errorInfo(true), 'warning');
1796
- return $zip->errorCode();
1797
- } else {
1798
- $updraftplus->something_useful_happened();
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
- // Make sure all directories are created before we start creating files
1822
- while ($dir = array_pop($this->zipfiles_dirbatched)) {
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 1.5 seconds have passed since the last time we wrote
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) > 1.5) {
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 1.5 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)');
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 >1.5s 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
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 1.5-second-activity detection can fire prematurely (e.g. if it takes >1.5 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.
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'),$zipfile, $zip->last_error));
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
  }
class-updraftplus.php ADDED
@@ -0,0 +1,2494 @@