UpdraftPlus WordPress Backup Plugin - Version 1.9.19

Version Description

  • 2014/08/19 =

  • FEATURE: Omit any directory from the backup (recursively) by creating a file called .donotbackup within it

  • PERFORMANCE: Lazy-load more code

  • PERFORMANCE: Prevent no-op search/replacements when restoring

  • FIX: Fix a corner-case where a backup might be able to continue but no attempt was made after using PclZip

  • FIX: Fix a corner-case (race condition) where UD might try to upload the same archive twice

  • FIX: Detection of pre-WP 3.5 hard-coded uploads paths upon site clone had stopped working

  • FIX: Fix bug in Importer add-on which could halt restorations of 3rd-party backups from the BackupWordPress plugin

  • FIX: Fix bug in the informational disk space consumption calculation in the expert tools section

  • TWEAK: Catch + log errors thrown by phpMailer

  • TWEAK: Merge Google SDK tweak from https://github.com/google/google-api-php-client/pull/189 to deal with buggy curl/proxy combinations with Google Drive

  • TWEAK: Prevent PHP log notice being generated on "Backup Now"

  • TWEAK: Change default zip split size to 500Mb on new installs

  • TWEAK: Scheduling algorithm tweak for more efficiency with very large backups when PHP is allowed to run long

  • TWEAK: Do not rely on PHP's disk_free_space() when it returns (int)0

  • TWEAK: Check database connection after auto-backup

  • TWEAK: More helpful message if uploading a backup when local storage is not writable

  • TWEAK: Extra logic to survive out-of-memory MySQL conditions in extreme cases; plus introduce UPDRAFTPLUS_ALWAYS_TRY_MYSQLDUMP constant

  • TWEAK: Tweak Amazon S3 logic so that it can cope with a situation where there is no permission to request its location (but there is permission for all other operations)

  • TWEAK: Workaround for PHP bug #62119 which could cause some files beginning with a non-ASCII character to be dropped

  • TWEAK: Warn the user if they are running on Apache without mod_rewrite and restore a site with permalinks requiring mod_rewrite

  • TWEAK: If Premium user was backing up non-WP tables, then optimize the backup table order

  • TWEAK: Deal with case when uploading very large backups to Google Drive on overloaded servers with unreliable network where activity check might misfire

  • TRANSLATIONS: Updated translations: Hungarian, Swedish, Russian, Brazilian (Portuguese), Spanish, Czeck, Dutch, Turkish, German

Download this release

Release Info

Developer DavidAnderson
Plugin Icon 128x128 UpdraftPlus WordPress Backup Plugin
Version 1.9.19
Comparing to
See all releases

Code changes from version 1.9.15 to 1.9.19

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,7 +43,7 @@ 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
  }
@@ -62,6 +60,11 @@ class UpdraftPlus_Admin {
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
@@ -151,7 +154,7 @@ class UpdraftPlus_Admin {
151
  'delete_old_dirs' => __('Delete Old Directories', 'updraftplus'),
152
  'raw' => __('Raw backup history', 'updraftplus'),
153
  'notarchive' => __('This file does not appear to be an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)).', 'updraftplus').' '.__('However, UpdraftPlus archives are standard zip/SQL files - so if you are sure that your file has the right format, then you can rename it to match that pattern.','updraftplus'),
154
- 'notarchive2' => '<p>'.__('This file does not appear to be an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)).', 'updraftplus').'</p> <p><a href="http://updraftplus.com/shop/updraftplus-premium/">'.__('If this is a backup created by a different backup plugin, then UpdraftPlus Premium may be able to help you.', 'updraftplus').'</a></p>',
155
  'makesure' => __('(make sure that you were trying to upload a zip file previously created by UpdraftPlus)','updraftplus'),
156
  'uploaderror' => __('Upload error:','updraftplus'),
157
  'notdba' => __('This file does not appear to be an UpdraftPlus encrypted database archive (such files are .gz.crypt files which have a name like: backup_(time)_(site name)_(code)_db.crypt.gz).','updraftplus'),
@@ -172,7 +175,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);
@@ -227,13 +230,13 @@ class UpdraftPlus_Admin {
227
  // 'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'),
228
 
229
  # WP 3.9 updated to plupload 2.0 - https://core.trac.wordpress.org/ticket/25663
230
- if (is_file(ABSPATH.'wp-includes/js/plupload/Moxie.swf')) {
231
  $plupload_init['flash_swf_url'] = includes_url('js/plupload/Moxie.swf');
232
  } else {
233
  $plupload_init['flash_swf_url'] = includes_url('js/plupload/plupload.flash.swf');
234
  }
235
 
236
- if (is_file(ABSPATH.'wp-includes/js/plupload/Moxie.xap')) {
237
  $plupload_init['silverlight_xap_url'] = includes_url('js/plupload/Moxie.xap');
238
  } else {
239
  $plupload_init['silverlight_xap_url'] = includes_url('js/plupload/plupload.silverlight.swf');
@@ -365,7 +368,7 @@ class UpdraftPlus_Admin {
365
 
366
  # Adds the settings link under the plugin on the plugin screen.
367
  public function plugin_action_links($links, $file) {
368
- if ($file == 'updraftplus/updraftplus.php'){
369
  $settings_link = '<a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__("Settings", "updraftplus").'</a>';
370
  array_unshift($links, $settings_link);
371
  // $settings_link = '<a href="http://david.dw-perspective.org.uk/donate">'.__("Donate","UpdraftPlus").'</a>';
@@ -378,7 +381,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 +424,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 +458,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
  }
@@ -802,7 +809,8 @@ class UpdraftPlus_Admin {
802
  if (!is_array($foreign_known) || empty($foreign_known[$backups[$timestamp]['meta_foreign']])) {
803
  $err[] = sprintf(__('Backup created by unknown source (%s) - cannot be restored.', 'updraftplus'), $backups[$timestamp]['meta_foreign']);
804
  } else {
805
- $backupable_plus_db = apply_filters_ref_array("updraftplus_importforeign_backupable_plus_db", array($backupable_plus_db, $foreign_known[$backups[$timestamp]['meta_foreign']], &$mess, &$warn, &$err));
 
806
  }
807
  }
808
 
@@ -1007,7 +1015,8 @@ class UpdraftPlus_Admin {
1007
  } elseif ('countbackups' == $_REQUEST['subaction']) {
1008
  $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1009
  $backup_history = (is_array($backup_history))?$backup_history:array();
1010
- echo sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history));
 
1011
  } elseif ('ping' == $_REQUEST['subaction']) {
1012
  // The purpose of this is to detect brokenness caused by extra line feeds in plugins/themes - before it breaks other AJAX operations and leads to support requests
1013
  echo 'pong';
@@ -1032,12 +1041,11 @@ class UpdraftPlus_Admin {
1032
  } elseif ('doaction' == $_REQUEST['subaction'] && !empty($_REQUEST['subsubaction']) && 'updraft_' == substr($_REQUEST['subsubaction'], 0, 8)) {
1033
  do_action($_REQUEST['subsubaction']);
1034
  } elseif ('backupnow' == $_REQUEST['subaction']) {
1035
- echo '<strong>',__('Schedule backup','updraftplus').':</strong> ';
1036
  $backupnow_nocloud = (empty($_REQUEST['backupnow_nocloud'])) ? false : true;
1037
  $event = (!empty($_REQUEST['backupnow_nofiles'])) ? 'updraft_backupnow_backup_database' : ((!empty($_REQUEST['backupnow_nodb'])) ? 'updraft_backupnow_backup' : 'updraft_backupnow_backup_all');
1038
 
1039
- $msg = htmlspecialchars(__('OK. You should soon see activity in the "Last log message" field below.','updraftplus'));
1040
- $updraftplus->log("A backup run has been started");
1041
  $this->close_browser_connection($msg);
1042
  do_action($event, $backupnow_nocloud);
1043
 
@@ -1095,7 +1103,7 @@ class UpdraftPlus_Admin {
1095
  $backup_history = (is_array($backup_history)) ? $backup_history : array();
1096
  $output = $this->existing_backup_table($backup_history);
1097
 
1098
- if (!empty($messages) && is_array($messages)) {
1099
  $noutput = '<div style="margin-left: 100px; margin-top: 10px;"><ul style="list-style: disc inside;">';
1100
  foreach ($messages as $msg) {
1101
  $noutput .= '<li>'.(($msg['desc']) ? $msg['desc'].': ' : '').'<em>'.$msg['message'].'</em></li>';
@@ -1104,7 +1112,8 @@ class UpdraftPlus_Admin {
1104
  $output = $noutput.$output;
1105
  }
1106
 
1107
- echo json_encode(array('n' => sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history)), 't' => $output));
 
1108
  } elseif (isset($_GET['subaction']) && 'downloadstatus' == $_GET['subaction'] && isset($_GET['timestamp']) && isset($_GET['type'])) {
1109
 
1110
  $findex = (isset($_GET['findex'])) ? $_GET['findex'] : '0';
@@ -1140,7 +1149,7 @@ class UpdraftPlus_Admin {
1140
 
1141
  public function howmany_overdue_crons() {
1142
  $how_many_overdue = 0;
1143
- if (function_exists('_get_cron_array') || (is_file(ABSPATH.'wp-includes/cron.php') && include_once(ABSPATH.'wp-includes/cron.php') && function_exists('_get_cron_array'))) {
1144
  $crons = _get_cron_array();
1145
  if (is_array($crons)) {
1146
  $timenow = time();
@@ -1163,7 +1172,7 @@ class UpdraftPlus_Admin {
1163
  return true;
1164
  }
1165
 
1166
- function download_status($timestamp, $type, $findex) {
1167
 
1168
  global $updraftplus;
1169
 
@@ -1214,7 +1223,7 @@ class UpdraftPlus_Admin {
1214
  $mess = array(); $warn = array(); $err = array();
1215
 
1216
  global $updraftplus, $wp_version;
1217
- include(ABSPATH.'wp-includes/version.php');
1218
 
1219
  # This attempts to raise the maximum packet size. This can't be done within the session, only globally. Therefore, it has to be done before the session starts; in our case, during the pre-analysis.
1220
  $updraftplus->get_max_packet_size();
@@ -1280,6 +1289,7 @@ class UpdraftPlus_Admin {
1280
  $old_siteinfo = array();
1281
  $gathering_siteinfo = true;
1282
  $old_wp_version = '';
 
1283
 
1284
  $tables_found = array();
1285
 
@@ -1315,13 +1325,21 @@ class UpdraftPlus_Admin {
1315
  $powarn = apply_filters('updraftplus_dbscan_urlchange', sprintf(__('Warning: %s', 'updraftplus'), '<a href="http://updraftplus.com/shop/migrator/">'.__('This backup set is from a different site - this is not a restoration, but a migration. You need the Migrator add-on in order to make this work.', 'updraftplus').'</a>'), $old_home, $res);
1316
  if (!empty($powarn)) $warn[] = $powarn;
1317
  }
1318
- } elseif ('' == $old_wp_version && preg_match('/^\# WordPress Version: ([0-9]+(\.[0-9]+)+)(-[-a-z0-9]+,)?/', $buffer, $matches)) {
1319
  $old_wp_version = $matches[1];
1320
  if (!empty($matches[3])) $old_wp_version .= substr($matches[3], 0, strlen($matches[3])-1);
1321
  if (version_compare($old_wp_version, $wp_version, '>')) {
1322
  //$mess[] = sprintf(__('%s version: %s', 'updraftplus'), 'WordPress', $old_wp_version);
1323
  $warn[] = sprintf(__('You are importing from a newer version of WordPress (%s) into an older one (%s). There are no guarantees that WordPress can handle this.', 'updraftplus'), $old_wp_version, $wp_version);
1324
  }
 
 
 
 
 
 
 
 
1325
  } elseif ('' == $old_table_prefix && (preg_match('/^\# Table prefix: (\S+)$/', $buffer, $matches) || preg_match('/^-- Table prefix: (\S+)$/i', $buffer, $matches))) {
1326
  $old_table_prefix = $matches[1];
1327
  // echo '<strong>'.__('Old table prefix:', 'updraftplus').'</strong> '.htmlspecialchars($old_table_prefix).'<br>';
@@ -1498,10 +1516,14 @@ CREATE TABLE $wpdb->signups (
1498
  global $updraftplus;
1499
  @set_time_limit(900);
1500
 
 
1501
  check_ajax_referer('updraft-uploader');
1502
 
1503
  $updraft_dir = $updraftplus->backups_dir_location();
1504
- if (!is_writable($updraft_dir)) exit;
 
 
 
1505
 
1506
  add_filter('upload_dir', array($this, 'upload_dir'));
1507
  add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
@@ -1513,9 +1535,7 @@ CREATE TABLE $wpdb->signups (
1513
  $farray['ext'] = 'x-gzip';
1514
  $farray['type'] = 'application/octet-stream';
1515
 
1516
- if (isset($_POST['chunks'])) {
1517
-
1518
- } else {
1519
  $farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
1520
  }
1521
 
@@ -1533,8 +1553,12 @@ CREATE TABLE $wpdb->signups (
1533
 
1534
  // If this was the chunk, then we should instead be concatenating onto the final file
1535
  if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
1536
- $final_file = $_POST['name'];
1537
- rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
 
 
 
 
1538
  $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
1539
 
1540
  // Final chunk? If so, then stich it all back together
@@ -1568,6 +1592,7 @@ CREATE TABLE $wpdb->signups (
1568
  $response = array();
1569
  if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
1570
  $file = basename($status['file']);
 
1571
  if (!preg_match('/^log\.[a-f0-9]{12}\.txt/', $file) && !preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)([0-9]+(of[0-9]+)?)?\.(zip|gz|gz\.crypt)$/i', $file, $matches)) {
1572
  $accept = apply_filters('updraftplus_accept_archivename', array());
1573
  if (is_array($accept)) {
@@ -1605,7 +1630,7 @@ CREATE TABLE $wpdb->signups (
1605
  @set_time_limit(900);
1606
  global $updraftplus;
1607
 
1608
- // check ajax nonce
1609
  check_ajax_referer('updraft-uploader');
1610
 
1611
  $updraft_dir = $updraftplus->backups_dir_location();
@@ -1642,7 +1667,7 @@ CREATE TABLE $wpdb->signups (
1642
 
1643
  // If this was the chunk, then we should instead be concatenating onto the final file
1644
  if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
1645
- $final_file = $_POST['name'];
1646
  rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
1647
  $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
1648
 
@@ -1776,12 +1801,12 @@ CREATE TABLE $wpdb->signups (
1776
  <div class="wrap" id="updraft-wrap">
1777
  <h1><?php echo $updraftplus->plugin_title; ?></h1>
1778
 
1779
- <?php _e('By UpdraftPlus.Com','updraftplus')?> ( <a href="http://updraftplus.com">UpdraftPlus.Com</a> | <a href="http://updraftplus.com/news/"><?php _e('News','updraftplus');?></a> | <?php if (!defined('UPDRAFTPLUS_NOADS_A')) { ?><a href="http://updraftplus.com/shop/updraftplus-premium/"><?php _e("Premium",'updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/"><?php _e("Support",'updraftplus');?></a> | <a href="http://david.dw-perspective.org.uk"><?php _e("Lead developer's homepage",'updraftplus');?></a> | <?php if (1==0 && !defined('UPDRAFTPLUS_NOADS_A')) { ?><a href="http://wordshell.net">WordShell - WordPress command line</a> | <a href="http://david.dw-perspective.org.uk/donate"><?php _e('Donate', 'updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/frequently-asked-questions/">FAQs</a> | <a href="https://www.simbahosting.co.uk/s3/shop/"><?php _e('More plugins', 'updraftplus');?></a> ) <?php _e('Version','updraftplus');?>: <?php echo $updraftplus->version; ?>
 
1780
  <br>
1781
 
1782
  <div id="updraft-hidethis">
1783
  <p><strong><?php _e('Warning:', 'updraftplus'); ?> <?php _e("If you can still read these words after the page finishes loading, then there is a JavaScript or jQuery problem in the site.", 'updraftplus'); ?> <a href="http://updraftplus.com/do-you-have-a-javascript-or-jquery-error/"><?php _e('Go here for more information.', 'updraftplus'); ?></a></strong></p>
1784
- </p>
1785
  </div>
1786
 
1787
  <?php
@@ -1796,17 +1821,26 @@ CREATE TABLE $wpdb->signups (
1796
  <div class="updated" style="padding:8px;"><?php _e("Your PHP memory limit (set by your web hosting company) is very low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may struggle with a memory limit of less than 64 Mb - especially if you have very large files uploaded (though on the other hand, many sites will be successful with a 32Mb limit - your experience may vary).",'updraftplus');?> <?php _e('Current limit is:','updraftplus');?> <?php echo $updraftplus->memory_check_current(); ?> Mb</div>
1797
  <?php
1798
  }
1799
- if($this->scan_old_dirs()) $this->print_delete_old_dirs_form();
 
 
1800
  if(!empty($updraftplus->errors)) {
1801
  echo '<div class="error fade" style="padding:8px;">';
1802
  $updraftplus->list_errors();
1803
  echo '</div>';
1804
  }
 
 
 
 
 
 
 
1805
  ?>
1806
 
1807
  <h2 class="nav-tab-wrapper" style="margin: 14px 0px;">
1808
  <a class="nav-tab nav-tab-active" href="#updraft-navtab-status-content" id="updraft-navtab-status"><?php _e('Current Status', 'updraftplus');?></a>
1809
- <a class="nav-tab" href="#updraft-navtab-backups-contents" id="updraft-navtab-backups"><?php _e('Existing Backups', 'updraftplus');?></a>
1810
  <a class="nav-tab" id="updraft-navtab-settings" href="#updraft-navtab-settings-content"><?php _e('Settings', 'updraftplus');?></a>
1811
  <a class="nav-tab" id="updraft-navtab-expert" href="#updraft-navtab-expert-content"><?php _e('Debugging / Expert Tools', 'updraftplus');?></a>
1812
  </h2>
@@ -1865,7 +1899,7 @@ CREATE TABLE $wpdb->signups (
1865
  // Convert to blog time zone
1866
  $next_scheduled_backup_database = get_date_from_gmt($next_scheduled_backup_database_gmt, 'D, F j, Y H:i');
1867
  } else {
1868
- $next_scheduled_backup_database = __('Nothing currently scheduled','updraftplus');
1869
  }
1870
  }
1871
  $current_time = get_date_from_gmt(gmdate('Y-m-d H:i:s'), 'D, F j, Y H:i');
@@ -1877,7 +1911,7 @@ CREATE TABLE $wpdb->signups (
1877
  <script>var lastbackup_laststatus = '<?php echo esc_js($last_backup_html);?>';</script>
1878
 
1879
  <tr>
1880
- <th><span title="<?php _e('All the times shown in this section are using WordPress\'s configured time zone, which you can set in Settings -> General', 'updraftplus'); ?>"><?php _e('Next scheduled backups','updraftplus');?>:</span></th>
1881
  <td>
1882
  <table style="border: 0px; padding: 0px; margin: 0 10px 0 0;">
1883
  <tr>
@@ -1895,15 +1929,6 @@ CREATE TABLE $wpdb->signups (
1895
  </tr>
1896
  </table>
1897
 
1898
- <?php
1899
- $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1900
- if (empty($backup_history)) {
1901
- $this->rebuild_backup_history();
1902
- $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1903
- }
1904
- $backup_history = (is_array($backup_history))?$backup_history:array();
1905
- ?>
1906
-
1907
  <br style="clear:both" />
1908
  <table class="form-table">
1909
 
@@ -1921,13 +1946,14 @@ CREATE TABLE $wpdb->signups (
1921
  </td>
1922
  </tr>
1923
 
1924
- <tr>
1925
  <th><?php echo htmlspecialchars(__('Backups, logs & restoring','updraftplus')); ?>:</th>
1926
  <td><a id="updraft_showbackups" href="#" title="<?php _e('Press to see available backups','updraftplus');?>" onclick="updraft_openrestorepanel(0); return false;"><?php echo sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history)); ?></a></td>
1927
- </tr>
 
1928
  <?php
1929
  # Currently disabled - not sure who we want to show this to
1930
- if (1==0 && !defined('UPDRAFTPLUS_NOADS_A')) {
1931
  $feed = $updraftplus->get_updraftplus_rssfeed();
1932
  if (is_a($feed, 'SimplePie')) {
1933
  echo '<tr><th style="vertical-align:top;">'.__('Latest UpdraftPlus.com news:', 'updraftplus').'</th><td style="vertical-align:top;">';
@@ -2026,7 +2052,7 @@ CREATE TABLE $wpdb->signups (
2026
  <li>
2027
  <strong><?php _e('More tasks:','updraftplus');?></strong>
2028
  <a href="#" onclick="jQuery('#updraft-plupload-modal').slideToggle(); return false;"><?php _e('Upload backup files','updraftplus');?></a>
2029
- | <a href="#" onclick="updraft_updatehistory(1, 0); return false;" title="<?php _e('Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below.','updraftplus'); ?>"><?php _e('Rescan local folder for new backup sets','updraftplus');?></a>
2030
  | <a href="#" onclick="updraft_updatehistory(1, 1); return false;" title="<?php _e('Press here to look inside any remote storage methods for any existing backup sets.','updraftplus'); ?>"><?php _e('Rescan remote storage','updraftplus');?></a>
2031
  </li>
2032
  <?php
@@ -2039,7 +2065,7 @@ CREATE TABLE $wpdb->signups (
2039
  ?><li><strong><?php _e('Google Drive','updraftplus');?>:</strong> <?php _e('Google changed their permissions setup recently (April 2013). To download or restore from Google Drive, you <strong>must</strong> first re-authenticate (using the link in the Google Drive configuration section).','updraftplus');?></li>
2040
  <?php } ?>
2041
 
2042
- <li title="<?php _e('This is a count of the contents of your Updraft directory','updraftplus');?>"><strong><?php _e('Web-server disk space in use by UpdraftPlus','updraftplus');?>:</strong> <span id="updraft_diskspaceused"><em>(calculating...)</em></span> <a href="#" onclick="updraftplus_diskspace(); return false;"><?php _e('refresh','updraftplus');?></a></li></ul>
2043
  </p>
2044
 
2045
  <div id="updraft-plupload-modal" title="<?php _e('UpdraftPlus - Upload backup files','updraftplus'); ?>" style="width: 75%; margin: 16px; display:none; margin-left: 100px;">
@@ -2177,7 +2203,7 @@ CREATE TABLE $wpdb->signups (
2177
  $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2178
  ?>
2179
  <div class="expertmode">
2180
- <!-- <h2><?php _e('Debug Information And Expert Options','updraftplus');?></h2> -->
2181
  <table>
2182
  <?php
2183
 
@@ -2209,14 +2235,14 @@ CREATE TABLE $wpdb->signups (
2209
  }
2210
  $this->settings_debugrow('ZipArchive::addFile:', $ziparchive_exists);
2211
  $binzip = $updraftplus->find_working_bin_zip(false, false);
2212
- $this->settings_debugrow(__('zip executable found:', 'updraftplus'), __('zip executable found:', 'updraftplus').' '.((is_string($binzip)) ? __('Yes').': '.$binzip : __('No')));
2213
  $hosting_bytes_free = $updraftplus->get_hosting_disk_quota_free();
2214
  if (is_array($hosting_bytes_free)) {
2215
  $perc = round(100*$hosting_bytes_free[1]/(max($hosting_bytes_free[2], 1)), 1);
2216
  $this->settings_debugrow(__('Free disk space in account:', 'updraftplus'), sprintf(__('%s (%s used)', 'updraftplus'), round($hosting_bytes_free[3]/1048576, 1)." Mb", "$perc %"));
2217
  }
2218
 
2219
- $this->settings_debugrow(__('Plugins for debugging:', 'updraftplus'),'<a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=wp-crontrol'), 'install-plugin_wp-crontrol').'">WP Crontrol</a> | <a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=sql-executioner'), 'install-plugin_sql-executioner').'">SQL Executioner</a> | <a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=advanced-code-editor'), 'install-plugin_advanced-code-editor').'">Advanced Code Editor</a> | <a href="'.wp_nonce_url(self_admin_url('update.php?action=install-plugin&updraftplus_noautobackup=1&plugin=wp-filemanager'), 'install-plugin_wp-filemanager').'">WP Filemanager</a>');
2220
 
2221
  $this->settings_debugrow("HTTP Get: ", '<input id="updraftplus_httpget_uri" type="text" style="width: 300px; height: 22px;"> <a href="#" id="updraftplus_httpget_go">'.__('Fetch', 'updraftplus').'</a> <a href="#" id="updraftplus_httpget_gocurl">'.__('Fetch', 'updraftplus').' (Curl)</a><p id="updraftplus_httpget_results"></p>');
2222
 
@@ -2291,7 +2317,6 @@ CREATE TABLE $wpdb->signups (
2291
  $cron = get_option('cron');
2292
  if (!is_array($cron)) $cron = array();
2293
  // $found_jobs = 0;
2294
-
2295
  $ret = '';
2296
 
2297
  foreach ($cron as $time => $job) {
@@ -2306,9 +2331,7 @@ CREATE TABLE $wpdb->signups (
2306
  }
2307
  }
2308
 
2309
- // if (0 == $found_jobs) {
2310
- // $ret .= '<p><em>'.__('(None)', 'updraftplus').'</em></p>';
2311
- // }
2312
  return $ret;
2313
  }
2314
 
@@ -2317,13 +2340,15 @@ CREATE TABLE $wpdb->signups (
2317
  $ret = '';
2318
 
2319
  global $updraftplus;
2320
- $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2321
 
2322
  $jobdata = $updraftplus->jobdata_getarray($job_id);
 
2323
 
2324
  #if (!is_array($jobdata)) $jobdata = array();
2325
  if (!isset($jobdata['backup_time'])) return '';
2326
 
 
 
2327
  $began_at = (isset($jobdata['backup_time'])) ? get_date_from_gmt(gmdate('Y-m-d H:i:s', (int)$jobdata['backup_time']), 'D, F j, Y H:i') : '?';
2328
 
2329
  $jobstatus = empty($jobdata['jobstatus']) ? 'unknown' : $jobdata['jobstatus'];
@@ -2617,7 +2642,8 @@ CREATE TABLE $wpdb->signups (
2617
  return true;
2618
  } else {
2619
  @$wp_filesystem->chmod($default_backup_dir, 0775);
2620
- return new WP_Error('writable_error', __('The folder exists, but your webserver does not have permission to write to it.', 'updraftplus').' '.__('You will need to consult with your web hosting provider to find out to set permissions for a WordPress plugin to write to the directory.', 'updraftplus'));
 
2621
  }
2622
  }
2623
 
@@ -2625,15 +2651,23 @@ CREATE TABLE $wpdb->signups (
2625
  }
2626
 
2627
  //scans the content dir to see if any -old dirs are present
2628
- private function scan_old_dirs() {
2629
  global $updraftplus;
2630
  $dirs = scandir(untrailingslashit(WP_CONTENT_DIR));
2631
  if (!is_array($dirs)) $dirs = array();
2632
  $dirs_u = @scandir($updraftplus->backups_dir_location());
2633
  if (!is_array($dirs_u)) $dirs_u = array();
2634
- foreach (array_merge($dirs, $dirs_u) as $dir) { if (preg_match('/-old$/', $dir)) return true; }
 
 
 
 
 
2635
  # No need to scan ABSPATH - we don't backup there
2636
- if (is_dir(untrailingslashit(WP_PLUGIN_DIR).'-old')) return true;
 
 
 
2637
  return false;
2638
  }
2639
 
@@ -2733,6 +2767,16 @@ CREATE TABLE $wpdb->signups (
2733
  ?> <input type="number" min="1" step="1" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:48px;" />
2734
  </td>
2735
  </tr>
 
 
 
 
 
 
 
 
 
 
2736
  <?php apply_filters('updraftplus_after_file_intervals', false, $selected_interval); ?>
2737
  <tr>
2738
  <th><?php _e('Database backup intervals','updraftplus'); ?>:</th>
@@ -2753,12 +2797,12 @@ CREATE TABLE $wpdb->signups (
2753
  </td>
2754
  </tr>
2755
  <tr class="backup-interval-description">
2756
- <td></td><td><div style="max-width:670px;"><p><?php echo htmlspecialchars(__('If you would like to automatically schedule backups, choose schedules from the dropdowns above. Backups will occur at the intervals specified. If the two schedules are the same, then the two backups will take place together. If you choose "manual" then you must click the "Backup Now" button whenever you wish a backup to occur.', 'updraftplus')); ?></p>
2757
  <?php echo apply_filters('updraftplus_fixtime_ftinfo', '<p><strong>'.__('To fix the time at which a backup should take place,','updraftplus').' </strong> ('.__('e.g. if your server is busy at day and you want to run overnight','updraftplus').'), <a href="http://updraftplus.com/shop/updraftplus-premium/">'.htmlspecialchars(__('use UpdraftPlus Premium', 'updraftplus')).'</a></p>'); ?>
2758
  </div></td>
2759
  </tr>
2760
  <tr>
2761
- <th><?php _e('Include in files backup','updraftplus');?>:</th>
2762
  <td>
2763
 
2764
  <?php
@@ -2791,7 +2835,7 @@ CREATE TABLE $wpdb->signups (
2791
  }
2792
  ?>
2793
  <p><?php echo apply_filters('updraftplus_admin_directories_description', __('The above directories are everything, except for WordPress core itself which you can download afresh from WordPress.org.', 'updraftplus').' <a href="http://updraftplus.com/shop/">'.htmlspecialchars(__('See also the "More Files" add-on from our shop.', 'updraftplus'))); ?></a></p>
2794
- <?php if (1==0 && !defined('UPDRAFTPLUS_NOADS_A')) echo '<p><a href="http://wordshell.net">('.__('Use WordShell for automatic backup, version control and patching', 'updraftplus').').</a></p>';?>
2795
  </td>
2796
  </tr>
2797
 
@@ -2995,8 +3039,8 @@ CREATE TABLE $wpdb->signups (
2995
  </tr>
2996
  <?php
2997
  $delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
2998
- $split_every_mb = UpdraftPlus_Options::get_updraft_option('updraft_split_every', 1*800);
2999
- if (!is_numeric($split_every_mb)) $split_every_mb = 1*800;
3000
  if ($split_every_mb < UPDRAFTPLUS_SPLIT_MIN) $split_every_mb = UPDRAFTPLUS_SPLIT_MIN;
3001
  ?>
3002
 
@@ -3007,7 +3051,7 @@ CREATE TABLE $wpdb->signups (
3007
 
3008
  <tr class="expertmode" style="display:none;">
3009
  <th><?php _e('Split archives every:','updraftplus');?></th>
3010
- <td><input type="text" name="updraft_split_every" id="updraft_split_every" value="<?php echo $split_every_mb ?>" size="5" /> Mb<br><?php _e('UpdraftPlus will split up backup archives when they exceed this file size. The default value is 800 megabytes. Be careful to leave some margin if your web-server has a hard size limit (e.g. the 2 Gb / 2048 Mb limit on some 32-bit servers/file systems).','updraftplus'); ?></td>
3011
  </tr>
3012
 
3013
  <tr class="deletelocal expertmode" style="display:none;">
@@ -3126,7 +3170,7 @@ CREATE TABLE $wpdb->signups (
3126
  }
3127
 
3128
  # If $basedirs is passed as an array, then $directorieses must be too
3129
- function recursive_directory_size($directorieses, $exclude = array(), $basedirs = '') {
3130
 
3131
  $size = 0;
3132
 
@@ -3137,11 +3181,11 @@ CREATE TABLE $wpdb->signups (
3137
 
3138
  if (is_string($basedirs)) $basedirs = array($basedirs);
3139
 
3140
- foreach ($basedirs as $ind => $basedir) {
3141
-
3142
- $directories = $directorieses[$ind];
3143
  if (!is_array($directories)) $directories=array($directories);
3144
 
 
 
3145
  foreach ($directories as $dir) {
3146
  if (is_file($dir)) {
3147
  $size += @filesize($dir);
@@ -3153,6 +3197,23 @@ CREATE TABLE $wpdb->signups (
3153
 
3154
  }
3155
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3156
  if ($size > 1073741824) {
3157
  return round($size / 1073741824, 1).' Gb';
3158
  } elseif ($size > 1048576) {
@@ -3165,13 +3226,14 @@ CREATE TABLE $wpdb->signups (
3165
 
3166
  }
3167
 
3168
- function recursive_directory_size_raw($prefix_directory, &$exclude = array(), $suffix_directory = '') {
3169
 
3170
  $directory = $prefix_directory.('' == $suffix_directory ? '' : '/'.$suffix_directory);
3171
  $size = 0;
3172
  if(substr($directory, -1) == '/') $directory = substr($directory,0,-1);
3173
 
3174
  if(!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) return -1;
 
3175
 
3176
  if($handle = opendir($directory)) {
3177
  while (($file = readdir($handle)) !== false) {
@@ -3233,15 +3295,27 @@ CREATE TABLE $wpdb->signups (
3233
  $entities = '';
3234
  $sval = ((isset($backup['service']) && $backup['service'] != 'email' && $backup['service'] != 'none')) ? '1' : '0';
3235
  $title = __('Delete this backup set', 'updraftplus');
3236
- $non=$backup['nonce'];
 
 
 
 
 
 
 
 
 
 
 
 
3237
  $ret .= <<<ENDHERE
3238
  <tr id="updraft_existing_backups_row_$key">
3239
- <td><div class="updraftplus-remove" style="width: 19px; height: 19px; padding-top:0px; font-size: 18px; text-align:center;font-weight:bold; border-radius: 7px;"><a style="text-decoration:none;" href="javascript:updraft_delete('$key', '$non', $sval);" title="$title">×</a></div></td><td><b>$pretty_date</b>
3240
  ENDHERE;
3241
 
3242
- $jobdata = $updraftplus->jobdata_getarray($non);
3243
  if (is_array($jobdata) && !empty($jobdata['resume_interval']) && (empty($jobdata['jobstatus']) || 'finished' != $jobdata['jobstatus'])) {
3244
- $ret .= "<br><span title=\"".esc_attr(__('If you are seeing more backups than you expect, then it is probably because the deletion of old backup sets does not happen until a fresh backup completes.', 'updraftplus'))."\">".__('(Not finished)', 'updraftplus').'</span>';
3245
  }
3246
 
3247
  $ret .= "</td>\n";
@@ -3251,9 +3325,8 @@ ENDHERE;
3251
  if (isset($backup['db'])) {
3252
  $entities .= '/db=0/';
3253
  $sdescrip = preg_replace('/ \(.*\)$/', '', __('Database','updraftplus'));
3254
-
3255
 
3256
- if (isset($accept[$backup['meta_foreign']])) {
3257
  $desc_source = $accept[$backup['meta_foreign']]['desc'];
3258
  } else {
3259
  $desc_source = __('unknown source', 'updraftplus');
@@ -3293,7 +3366,7 @@ ENDHERE;
3293
  $entities = '/db=0/meta_foreign=1/';
3294
  }
3295
 
3296
- if (!empty($backup['meta_foreign']) && !empty($accept[$backup['meta_foreign']]['separatedb'])) {
3297
  $entities .= '/meta_foreign=2/';
3298
  }
3299
 
@@ -3429,11 +3502,15 @@ ENDHERE;
3429
  // If $remotescan is set, then remote storage is also scanned
3430
  public function rebuild_backup_history($remotescan = false) {
3431
 
 
 
3432
  global $updraftplus;
3433
  $messages = array();
3434
  $gmt_offset = get_option('gmt_offset');
3435
 
 
3436
  $known_files = array();
 
3437
  $known_nonces = array();
3438
  $changes = false;
3439
 
@@ -3446,7 +3523,7 @@ ENDHERE;
3446
 
3447
  $accept = apply_filters('updraftplus_accept_archivename', array());
3448
  if (!is_array($accept)) $accept = array();
3449
- // Accumulate a list of known files in the database backup history
3450
  foreach ($backup_history as $btime => $bdata) {
3451
  $found_file = false;
3452
  foreach ($bdata as $key => $values) {
@@ -3462,7 +3539,7 @@ ENDHERE;
3462
  } else {
3463
  $found_file = true;
3464
  $known_files[$val] = $nonce;
3465
- $known_nonces[$nonce] = $btime;
3466
  }
3467
  } else {
3468
  $accepted = false;
@@ -3471,9 +3548,10 @@ ENDHERE;
3471
  }
3472
  if (!empty($accepted) && (false != ($btime = apply_filters('updraftplus_foreign_gettime', false, $fkey, $val))) && $btime > 0) {
3473
  $found_file = true;
 
3474
  $nonce = substr(md5($val), 0, 12);
3475
  $known_files[$val] = $nonce;
3476
- $known_nonces[$nonce] = $btime;
3477
  }
3478
  }
3479
  }
@@ -3488,6 +3566,7 @@ ENDHERE;
3488
  $remotefiles = array();
3489
  $remotesizes = array();
3490
  # Scan remote storage and get back lists of files and their sizes
 
3491
  if ($remotescan) {
3492
  foreach ($updraftplus->backup_methods as $method => $desc) {
3493
  require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
@@ -3529,6 +3608,7 @@ ENDHERE;
3529
  $accepted_foreign = false;
3530
  $potmessage = false;
3531
  if ('.' == $entry || '..' == $entry) continue;
 
3532
  if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)([0-9]+(of[0-9]+)?)?\.(zip|gz|gz\.crypt)$/i', $entry, $matches)) {
3533
 
3534
  // Interpret the time as one from the blog's local timezone, rather than as UTC
@@ -3545,7 +3625,7 @@ ENDHERE;
3545
  $index = (empty($matches[4])) ? '0' : (max((int)$matches[4]-1,0));
3546
  }
3547
  $itext = ($index == 0) ? '' : $index;
3548
- } elseif (false != ($accepted_foreign = apply_filters('updraftplus_accept_foreign', false, $entry)) && false != ($btime = apply_filters('updraftplus_foreign_gettime', false, $accepted_foreign, $entry))) {
3549
  $nonce = substr(md5($entry), 0, 12);
3550
  $type = preg_match('/\.sql(\.(bz2|gz))?$/', $entry) ? 'db' : 'wpcore';
3551
  $index = '0';
@@ -3569,7 +3649,19 @@ ENDHERE;
3569
  continue;
3570
  }
3571
  // The time from the filename does not include seconds. Need to identify the seconds to get the right time
3572
- if (isset($known_nonces[$nonce])) $btime = $known_nonces[$nonce];
 
 
 
 
 
 
 
 
 
 
 
 
3573
  if ($btime <= 100) continue;
3574
  $fs = @filesize($updraft_dir.'/'.$entry);
3575
 
@@ -3578,6 +3670,7 @@ ENDHERE;
3578
  if (is_array($potmessage)) $messages[$potmessage['code']] = $potmessage;
3579
  }
3580
 
 
3581
  # Make sure we have the right list of services
3582
  $current_services = (!empty($backup_history[$btime]) && !empty($backup_history[$btime]['service'])) ? $backup_history[$btime]['service'] : array();
3583
  if (is_string($current_services)) $current_services = array($current_services);
@@ -3674,7 +3767,7 @@ ENDHERE;
3674
  }
3675
 
3676
  // Return values: false = 'not yet' (not necessarily terminal); WP_Error = terminal failure; true = success
3677
- function restore_backup($timestamp) {
3678
 
3679
  @set_time_limit(900);
3680
 
@@ -3702,8 +3795,9 @@ ENDHERE;
3702
  $credentials = request_filesystem_credentials(UpdraftPlus_Options::admin_page()."?page=updraftplus&action=updraft_restore&backup_timestamp=$timestamp", '', false, false, $extra_fields);
3703
  WP_Filesystem($credentials);
3704
  if ( $wp_filesystem->errors->get_error_code() ) {
 
3705
  foreach ( $wp_filesystem->errors->get_error_messages() as $message ) show_message($message);
3706
- exit;
3707
  }
3708
 
3709
  # Set up logging
@@ -3739,7 +3833,7 @@ ENDHERE;
3739
  if (empty($backup_set['meta_foreign'])) {
3740
  $entities_to_restore[$entity] = $entity;
3741
  } else {
3742
- if ('db' == $entity && !empty($foreign_known[$backup_set['meta_foreign']]['separatedb'])) {
3743
  $entities_to_restore[$entity] = 'db';
3744
  } else {
3745
  $entities_to_restore[$entity] = 'wpcore';
@@ -3941,13 +4035,13 @@ ENDHERE;
3941
  if (!empty($data)) {
3942
  $pdata = (is_string($data)) ? $data : serialize($data);
3943
  echo '<strong>'.__('Error data:', 'updraftplus').'</strong> '.htmlspecialchars($pdata).'<br>';
 
 
 
3944
  }
3945
  }
3946
  }
3947
  echo '</div>'; //close the updraft_restore_progress div even if we error
3948
- if (false !== strpos($val->get_error_data(), 'PCLZIP_ERR_BAD_FORMAT (-10)')) {
3949
- echo '<a href="http://updraftplus.com/faqs/error-message-pclzip_err_bad_format-10-invalid-archive-structure-mean/"><strong>'.__('Please consult this FAQ for help on what to do about it.', 'updraftplus').'</strong></a><br>';
3950
- }
3951
  restore_error_handler();
3952
  return $val;
3953
  } elseif (false === $val) {
@@ -3963,7 +4057,7 @@ ENDHERE;
3963
  foreach (array('template', 'stylesheet', 'template_root', 'stylesheet_root') as $opt) {
3964
  add_filter('pre_option_'.$opt, array($this, 'option_filter_'.$opt));
3965
  }
3966
- if (!function_exists('validate_current_theme')) require_once(ABSPATH.'wp-includes/themes');
3967
 
3968
  # Have seen a case where the current theme in the DB began with a capital, but not on disk - and this breaks migrating from Windows to a case-sensitive system
3969
  $template = get_option('template');
@@ -4025,7 +4119,7 @@ ENDHERE;
4025
  private function get_settings_keys() {
4026
  return array('updraft_autobackup_default', 'updraft_dropbox', 'updraft_googledrive', 'updraftplus_tmp_googledrive_access_token', 'updraftplus_dismissedautobackup', 'updraftplus_dismissedexpiry', 'updraft_interval', 'updraft_interval_increments', 'updraft_interval_database', 'updraft_retain', 'updraft_retain_db', 'updraft_encryptionphrase', 'updraft_service', 'updraft_dropbox_appkey', 'updraft_dropbox_secret', 'updraft_googledrive_clientid', 'updraft_googledrive_secret', 'updraft_googledrive_remotepath', 'updraft_ftp_login', 'updraft_ftp_pass', 'updraft_ftp_remote_path', 'updraft_server_address', 'updraft_dir', 'updraft_email', 'updraft_delete_local', 'updraft_debug_mode', 'updraft_include_plugins', 'updraft_include_themes', 'updraft_include_uploads', 'updraft_include_others', 'updraft_include_wpcore', 'updraft_include_wpcore_exclude', 'updraft_include_more', 'updraft_include_blogs', 'updraft_include_mu-plugins', 'updraft_include_others_exclude', 'updraft_include_uploads_exclude',
4027
  'updraft_lastmessage', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder',
4028
- 'updraft_last_backup', 'updraft_starttime_files', 'updraft_starttime_db', 'updraft_startday_db', 'updraft_startday_files', 'updraft_sftp_settings', 'updraft_s3', 'updraft_s3generic', 'updraft_dreamhost', 'updraft_s3generic_login', 'updraft_s3generic_pass', 'updraft_s3generic_remote_path', 'updraft_s3generic_endpoint', 'updraft_webdav_settings', 'updraft_disable_ping', 'updraft_openstack', 'updraft_bitcasa', 'updraft_cloudfiles', 'updraft_cloudfiles_user', 'updraft_cloudfiles_apikey', 'updraft_cloudfiles_path', 'updraft_cloudfiles_authurl', 'updraft_ssl_useservercerts', 'updraft_ssl_disableverify', 'updraft_s3_login', 'updraft_s3_pass', 'updraft_s3_remote_path', 'updraft_dreamobjects_login', 'updraft_dreamobjects_pass', 'updraft_dreamobjects_remote_path', 'updraft_report_warningsonly', 'updraft_report_wholebackup', 'updraft_log_syslog', 'updraft_extradatabases');
4029
  }
4030
 
4031
  }
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
  }
60
  if (!empty($opts['clientid']) && !empty($opts['secret']) && empty($opts['token'])) add_action('all_admin_notices', array($this,'show_admin_warning_bitcasa') );
61
  }
62
 
63
+ if (UpdraftPlus_Options::user_can_manage() && ('copycom' === $service || is_array($service) && in_array('copycom', $service))) {
64
+ $opts = UpdraftPlus_Options::get_updraft_option('updraft_copycom');
65
+ if (!empty($opts['clientid']) && !empty($opts['secret']) && empty($opts['token'])) add_action('all_admin_notices', array($this,'show_admin_warning_copycom') );
66
+ }
67
+
68
  if (UpdraftPlus_Options::user_can_manage() && $this->disk_space_check(1048576*35) === false) add_action('all_admin_notices', array($this, 'show_admin_warning_diskspace'));
69
 
70
  // Next, the actions that only come on the UpdraftPlus page
154
  'delete_old_dirs' => __('Delete Old Directories', 'updraftplus'),
155
  'raw' => __('Raw backup history', 'updraftplus'),
156
  'notarchive' => __('This file does not appear to be an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)).', 'updraftplus').' '.__('However, UpdraftPlus archives are standard zip/SQL files - so if you are sure that your file has the right format, then you can rename it to match that pattern.','updraftplus'),
157
+ 'notarchive2' => '<p>'.__('This file does not appear to be an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)).', 'updraftplus').'</p> '.apply_filters('updraftplus_if_foreign_then_premium_message', '<p><a href="http://updraftplus.com/shop/updraftplus-premium/">'.__('If this is a backup created by a different backup plugin, then UpdraftPlus Premium may be able to help you.', 'updraftplus').'</a></p>'),
158
  'makesure' => __('(make sure that you were trying to upload a zip file previously created by UpdraftPlus)','updraftplus'),
159
  'uploaderror' => __('Upload error:','updraftplus'),
160
  'notdba' => __('This file does not appear to be an UpdraftPlus encrypted database archive (such files are .gz.crypt files which have a name like: backup_(time)_(site name)_(code)_db.crypt.gz).','updraftplus'),
175
 
176
  public function core_upgrade_preamble() {
177
  if (!class_exists('UpdraftPlus_Addon_Autobackup')) {
178
+ if (defined('UPDRAFTPLUS_NOADS_B')) return;
179
  # TODO: Remove legacy/wrong use of transient any time from 1 Jun 2014
180
  if (true == get_transient('updraftplus_dismissedautobackup')) return;
181
  $dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismissedautobackup', 0);
230
  // 'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'),
231
 
232
  # WP 3.9 updated to plupload 2.0 - https://core.trac.wordpress.org/ticket/25663
233
+ if (is_file(ABSPATH.WPINC.'/js/plupload/Moxie.swf')) {
234
  $plupload_init['flash_swf_url'] = includes_url('js/plupload/Moxie.swf');
235
  } else {
236
  $plupload_init['flash_swf_url'] = includes_url('js/plupload/plupload.flash.swf');
237
  }
238
 
239
+ if (is_file(ABSPATH.WPINC.'/js/plupload/Moxie.xap')) {
240
  $plupload_init['silverlight_xap_url'] = includes_url('js/plupload/Moxie.xap');
241
  } else {
242
  $plupload_init['silverlight_xap_url'] = includes_url('js/plupload/plupload.silverlight.swf');
368
 
369
  # Adds the settings link under the plugin on the plugin screen.
370
  public function plugin_action_links($links, $file) {
371
+ if (is_array($links) && $file == 'updraftplus/updraftplus.php'){
372
  $settings_link = '<a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__("Settings", "updraftplus").'</a>';
373
  array_unshift($links, $settings_link);
374
  // $settings_link = '<a href="http://david.dw-perspective.org.uk/donate">'.__("Donate","UpdraftPlus").'</a>';
381
 
382
  public function admin_action_upgrade_pluginortheme() {
383
 
384
+ if (isset($_GET['action']) && ($_GET['action'] == 'upgrade-plugin' || $_GET['action'] == 'upgrade-theme') && !class_exists('UpdraftPlus_Addon_Autobackup') && !defined('UPDRAFTPLUS_NOADS_B')) {
385
 
386
  # TODO: Remove legacy/erroneous use of transient any time after 1 Jun 2014
387
  $dismissed = get_transient('updraftplus_dismissedautobackup');
424
  }
425
 
426
  public function show_admin_warning_disabledcron() {
427
+ $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');
428
  }
429
 
430
  public function show_admin_warning_diskspace() {
458
  $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>');
459
  }
460
 
461
+ public function show_admin_warning_copycom() {
462
+ $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>');
463
+ }
464
+
465
  public function show_admin_warning_googledrive() {
466
  $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>');
467
  }
809
  if (!is_array($foreign_known) || empty($foreign_known[$backups[$timestamp]['meta_foreign']])) {
810
  $err[] = sprintf(__('Backup created by unknown source (%s) - cannot be restored.', 'updraftplus'), $backups[$timestamp]['meta_foreign']);
811
  } else {
812
+ # For some reason, on PHP 5.5 passing by reference in a single array stopped working with apply_filters_ref_array (though not with do_action_ref_array).
813
+ $backupable_plus_db = apply_filters_ref_array("updraftplus_importforeign_backupable_plus_db", array($backupable_plus_db, array($foreign_known[$backups[$timestamp]['meta_foreign']], &$mess, &$warn, &$err)));
814
  }
815
  }
816
 
1015
  } elseif ('countbackups' == $_REQUEST['subaction']) {
1016
  $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1017
  $backup_history = (is_array($backup_history))?$backup_history:array();
1018
+ #echo sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history));
1019
+ echo __('Existing Backups', 'updraftplus').' ('.count($backup_history).')';
1020
  } elseif ('ping' == $_REQUEST['subaction']) {
1021
  // The purpose of this is to detect brokenness caused by extra line feeds in plugins/themes - before it breaks other AJAX operations and leads to support requests
1022
  echo 'pong';
1041
  } elseif ('doaction' == $_REQUEST['subaction'] && !empty($_REQUEST['subsubaction']) && 'updraft_' == substr($_REQUEST['subsubaction'], 0, 8)) {
1042
  do_action($_REQUEST['subsubaction']);
1043
  } elseif ('backupnow' == $_REQUEST['subaction']) {
1044
+
1045
  $backupnow_nocloud = (empty($_REQUEST['backupnow_nocloud'])) ? false : true;
1046
  $event = (!empty($_REQUEST['backupnow_nofiles'])) ? 'updraft_backupnow_backup_database' : ((!empty($_REQUEST['backupnow_nodb'])) ? 'updraft_backupnow_backup' : 'updraft_backupnow_backup_all');
1047
 
1048
+ $msg = '<strong>'.__('Start backup','updraftplus').':</strong> '.htmlspecialchars(__('OK. You should soon see activity in the "Last log message" field below.','updraftplus'));
 
1049
  $this->close_browser_connection($msg);
1050
  do_action($event, $backupnow_nocloud);
1051
 
1103
  $backup_history = (is_array($backup_history)) ? $backup_history : array();
1104
  $output = $this->existing_backup_table($backup_history);
1105
 
1106
+ if (is_array($messages) && !empty($messages)) {
1107
  $noutput = '<div style="margin-left: 100px; margin-top: 10px;"><ul style="list-style: disc inside;">';
1108
  foreach ($messages as $msg) {
1109
  $noutput .= '<li>'.(($msg['desc']) ? $msg['desc'].': ' : '').'<em>'.$msg['message'].'</em></li>';
1112
  $output = $noutput.$output;
1113
  }
1114
 
1115
+ // echo @json_encode(array('n' => sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history)), 't' => $output));
1116
+ echo @json_encode(array('n' => sprintf(__('Existing Backups', 'updraftplus').' (%d)', count($backup_history)), 't' => $output));
1117
  } elseif (isset($_GET['subaction']) && 'downloadstatus' == $_GET['subaction'] && isset($_GET['timestamp']) && isset($_GET['type'])) {
1118
 
1119
  $findex = (isset($_GET['findex'])) ? $_GET['findex'] : '0';
1149
 
1150
  public function howmany_overdue_crons() {
1151
  $how_many_overdue = 0;
1152
+ if (function_exists('_get_cron_array') || (is_file(ABSPATH.WPINC.'/cron.php') && include_once(ABSPATH.WPINC.'/cron.php') && function_exists('_get_cron_array'))) {
1153
  $crons = _get_cron_array();
1154
  if (is_array($crons)) {
1155
  $timenow = time();
1172
  return true;
1173
  }
1174
 
1175
+ private function download_status($timestamp, $type, $findex) {
1176
 
1177
  global $updraftplus;
1178
 
1223
  $mess = array(); $warn = array(); $err = array();
1224
 
1225
  global $updraftplus, $wp_version;
1226
+ include(ABSPATH.WPINC.'/version.php');
1227
 
1228
  # This attempts to raise the maximum packet size. This can't be done within the session, only globally. Therefore, it has to be done before the session starts; in our case, during the pre-analysis.
1229
  $updraftplus->get_max_packet_size();
1289
  $old_siteinfo = array();
1290
  $gathering_siteinfo = true;
1291
  $old_wp_version = '';
1292
+ $old_php_version = '';
1293
 
1294
  $tables_found = array();
1295
 
1325
  $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);
1326
  if (!empty($powarn)) $warn[] = $powarn;
1327
  }
1328
+ } elseif ('' == $old_wp_version && preg_match('/^\# WordPress Version: ([0-9]+(\.[0-9]+)+)(-[-a-z0-9]+,)?(.*)$/', $buffer, $matches)) {
1329
  $old_wp_version = $matches[1];
1330
  if (!empty($matches[3])) $old_wp_version .= substr($matches[3], 0, strlen($matches[3])-1);
1331
  if (version_compare($old_wp_version, $wp_version, '>')) {
1332
  //$mess[] = sprintf(__('%s version: %s', 'updraftplus'), 'WordPress', $old_wp_version);
1333
  $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);
1334
  }
1335
+ if (preg_match('/running on PHP ([0-9]+\.[0-9]+)(\s|\.)/', $matches[4], $nmatches) && preg_match('/^([0-9]+\.[0-9]+)(\s|\.)/', PHP_VERSION, $cmatches)) {
1336
+ $old_php_version = $nmatches[1];
1337
+ $current_php_version = $cmatches[1];
1338
+ if (version_compare($old_php_version, $current_php_version, '>')) {
1339
+ //$mess[] = sprintf(__('%s version: %s', 'updraftplus'), 'WordPress', $old_wp_version);
1340
+ $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');
1341
+ }
1342
+ }
1343
  } elseif ('' == $old_table_prefix && (preg_match('/^\# Table prefix: (\S+)$/', $buffer, $matches) || preg_match('/^-- Table prefix: (\S+)$/i', $buffer, $matches))) {
1344
  $old_table_prefix = $matches[1];
1345
  // echo '<strong>'.__('Old table prefix:', 'updraftplus').'</strong> '.htmlspecialchars($old_table_prefix).'<br>';
1516
  global $updraftplus;
1517
  @set_time_limit(900);
1518
 
1519
+ if (!UpdraftPlus_Options::user_can_manage()) exit;
1520
  check_ajax_referer('updraft-uploader');
1521
 
1522
  $updraft_dir = $updraftplus->backups_dir_location();
1523
+ if (!@$updraftplus->really_is_writable($updraft_dir)) {
1524
+ echo json_encode(array('e' => sprintf(__("Backup directory (%s) is not writable, or does not exist.", 'updraftplus'), $updraft_dir).' '.__('You will find more information about this in the Settings section.', 'updraftplus')));
1525
+ exit;
1526
+ }
1527
 
1528
  add_filter('upload_dir', array($this, 'upload_dir'));
1529
  add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
1535
  $farray['ext'] = 'x-gzip';
1536
  $farray['type'] = 'application/octet-stream';
1537
 
1538
+ if (!isset($_POST['chunks'])) {
 
 
1539
  $farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
1540
  }
1541
 
1553
 
1554
  // If this was the chunk, then we should instead be concatenating onto the final file
1555
  if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
1556
+ $final_file = basename($_POST['name']);
1557
+ if (!rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp')) {
1558
+ @unlink($status['file']);
1559
+ echo json_encode(array('e' => sprintf(__('Error: %s', 'updraftplus'), __('This file could not be uploaded', 'updraftplus'))));
1560
+ exit;
1561
+ }
1562
  $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
1563
 
1564
  // Final chunk? If so, then stich it all back together
1592
  $response = array();
1593
  if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
1594
  $file = basename($status['file']);
1595
+ # TODO: Make compatible with incremental naming scheme
1596
  if (!preg_match('/^log\.[a-f0-9]{12}\.txt/', $file) && !preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)([0-9]+(of[0-9]+)?)?\.(zip|gz|gz\.crypt)$/i', $file, $matches)) {
1597
  $accept = apply_filters('updraftplus_accept_archivename', array());
1598
  if (is_array($accept)) {
1630
  @set_time_limit(900);
1631
  global $updraftplus;
1632
 
1633
+ if (!UpdraftPlus_Options::user_can_manage()) exit;
1634
  check_ajax_referer('updraft-uploader');
1635
 
1636
  $updraft_dir = $updraftplus->backups_dir_location();
1667
 
1668
  // If this was the chunk, then we should instead be concatenating onto the final file
1669
  if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
1670
+ $final_file = basename($_POST['name']);
1671
  rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
1672
  $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
1673
 
1801
  <div class="wrap" id="updraft-wrap">
1802
  <h1><?php echo $updraftplus->plugin_title; ?></h1>
1803
 
1804
+ <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>
1805
+ | <?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; ?>
1806
  <br>
1807
 
1808
  <div id="updraft-hidethis">
1809
  <p><strong><?php _e('Warning:', 'updraftplus'); ?> <?php _e("If you can still read these words after the page finishes loading, then there is a JavaScript or jQuery problem in the site.", 'updraftplus'); ?> <a href="http://updraftplus.com/do-you-have-a-javascript-or-jquery-error/"><?php _e('Go here for more information.', 'updraftplus'); ?></a></strong></p>
 
1810
  </div>
1811
 
1812
  <?php
1821
  <div class="updated" style="padding:8px;"><?php _e("Your PHP memory limit (set by your web hosting company) is very low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may struggle with a memory limit of less than 64 Mb - especially if you have very large files uploaded (though on the other hand, many sites will be successful with a 32Mb limit - your experience may vary).",'updraftplus');?> <?php _e('Current limit is:','updraftplus');?> <?php echo $updraftplus->memory_check_current(); ?> Mb</div>
1822
  <?php
1823
  }
1824
+
1825
+ if($this->scan_old_dirs(true)) $this->print_delete_old_dirs_form();
1826
+
1827
  if(!empty($updraftplus->errors)) {
1828
  echo '<div class="error fade" style="padding:8px;">';
1829
  $updraftplus->list_errors();
1830
  echo '</div>';
1831
  }
1832
+
1833
+ $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1834
+ if (empty($backup_history)) {
1835
+ $this->rebuild_backup_history();
1836
+ $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1837
+ }
1838
+ $backup_history = (is_array($backup_history))?$backup_history:array();
1839
  ?>
1840
 
1841
  <h2 class="nav-tab-wrapper" style="margin: 14px 0px;">
1842
  <a class="nav-tab nav-tab-active" href="#updraft-navtab-status-content" id="updraft-navtab-status"><?php _e('Current Status', 'updraftplus');?></a>
1843
+ <a class="nav-tab" href="#updraft-navtab-backups-contents" id="updraft-navtab-backups"><?php echo __('Existing Backups', 'updraftplus').' ('.count($backup_history).')';?></a>
1844
  <a class="nav-tab" id="updraft-navtab-settings" href="#updraft-navtab-settings-content"><?php _e('Settings', 'updraftplus');?></a>
1845
  <a class="nav-tab" id="updraft-navtab-expert" href="#updraft-navtab-expert-content"><?php _e('Debugging / Expert Tools', 'updraftplus');?></a>
1846
  </h2>
1899
  // Convert to blog time zone
1900
  $next_scheduled_backup_database = get_date_from_gmt($next_scheduled_backup_database_gmt, 'D, F j, Y H:i');
1901
  } else {
1902
+ $next_scheduled_backup_database = __('Nothing currently scheduled', 'updraftplus');
1903
  }
1904
  }
1905
  $current_time = get_date_from_gmt(gmdate('Y-m-d H:i:s'), 'D, F j, Y H:i');
1911
  <script>var lastbackup_laststatus = '<?php echo esc_js($last_backup_html);?>';</script>
1912
 
1913
  <tr>
1914
+ <th><span title="<?php _e('All the times shown in this section are using WordPress\'s configured time zone, which you can set in Settings -> General', 'updraftplus'); ?>"><?php _e('Next scheduled backups', 'updraftplus');?>:</span></th>
1915
  <td>
1916
  <table style="border: 0px; padding: 0px; margin: 0 10px 0 0;">
1917
  <tr>
1929
  </tr>
1930
  </table>
1931
 
 
 
 
 
 
 
 
 
 
1932
  <br style="clear:both" />
1933
  <table class="form-table">
1934
 
1946
  </td>
1947
  </tr>
1948
 
1949
+ <!--<tr>
1950
  <th><?php echo htmlspecialchars(__('Backups, logs & restoring','updraftplus')); ?>:</th>
1951
  <td><a id="updraft_showbackups" href="#" title="<?php _e('Press to see available backups','updraftplus');?>" onclick="updraft_openrestorepanel(0); return false;"><?php echo sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history)); ?></a></td>
1952
+ </tr>-->
1953
+
1954
  <?php
1955
  # Currently disabled - not sure who we want to show this to
1956
+ if (1==0 && !defined('UPDRAFTPLUS_NOADS_B')) {
1957
  $feed = $updraftplus->get_updraftplus_rssfeed();
1958
  if (is_a($feed, 'SimplePie')) {
1959
  echo '<tr><th style="vertical-align:top;">'.__('Latest UpdraftPlus.com news:', 'updraftplus').'</th><td style="vertical-align:top;">';
2052
  <li>
2053
  <strong><?php _e('More tasks:','updraftplus');?></strong>
2054
  <a href="#" onclick="jQuery('#updraft-plupload-modal').slideToggle(); return false;"><?php _e('Upload backup files','updraftplus');?></a>
2055
+ | <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>
2056
  | <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>
2057
  </li>
2058
  <?php
2065
  ?><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>
2066
  <?php } ?>
2067
 
2068
+ <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>
2069
  </p>
2070
 
2071
  <div id="updraft-plupload-modal" title="<?php _e('UpdraftPlus - Upload backup files','updraftplus'); ?>" style="width: 75%; margin: 16px; display:none; margin-left: 100px;">
2203
  $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2204
  ?>
2205
  <div class="expertmode">
2206
+ <p><em><?php _e('Unless you have a problem, you can completely ignore everything here.', 'updraftplus');?></em></p>
2207
  <table>
2208
  <?php
2209
 
2235
  }
2236
  $this->settings_debugrow('ZipArchive::addFile:', $ziparchive_exists);
2237
  $binzip = $updraftplus->find_working_bin_zip(false, false);
2238
+ $this->settings_debugrow(__('zip executable found:', 'updraftplus'), ((is_string($binzip)) ? __('Yes').': '.$binzip : __('No')));
2239
  $hosting_bytes_free = $updraftplus->get_hosting_disk_quota_free();
2240
  if (is_array($hosting_bytes_free)) {
2241
  $perc = round(100*$hosting_bytes_free[1]/(max($hosting_bytes_free[2], 1)), 1);
2242
  $this->settings_debugrow(__('Free disk space in account:', 'updraftplus'), sprintf(__('%s (%s used)', 'updraftplus'), round($hosting_bytes_free[3]/1048576, 1)." Mb", "$perc %"));
2243
  }
2244
 
2245
+ $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>');
2246
 
2247
  $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>');
2248
 
2317
  $cron = get_option('cron');
2318
  if (!is_array($cron)) $cron = array();
2319
  // $found_jobs = 0;
 
2320
  $ret = '';
2321
 
2322
  foreach ($cron as $time => $job) {
2331
  }
2332
  }
2333
 
2334
+ // if (0 == $found_jobs) $ret .= '<p><em>'.__('(None)', 'updraftplus').'</em></p>';
 
 
2335
  return $ret;
2336
  }
2337
 
2340
  $ret = '';
2341
 
2342
  global $updraftplus;
 
2343
 
2344
  $jobdata = $updraftplus->jobdata_getarray($job_id);
2345
+ if (false == apply_filters('updraftplus_print_active_job_continue', true, $is_oneshot, $next_resumption, $jobdata)) return '';
2346
 
2347
  #if (!is_array($jobdata)) $jobdata = array();
2348
  if (!isset($jobdata['backup_time'])) return '';
2349
 
2350
+ $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
2351
+
2352
  $began_at = (isset($jobdata['backup_time'])) ? get_date_from_gmt(gmdate('Y-m-d H:i:s', (int)$jobdata['backup_time']), 'D, F j, Y H:i') : '?';
2353
 
2354
  $jobstatus = empty($jobdata['jobstatus']) ? 'unknown' : $jobdata['jobstatus'];
2642
  return true;
2643
  } else {
2644
  @$wp_filesystem->chmod($default_backup_dir, 0775);
2645
+ $show_dir = (0 === strpos($default_backup_dir, ABSPATH)) ? substr($default_backup_dir, strlen(ABSPATH)) : $default_backup_dir;
2646
+ 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.')');
2647
  }
2648
  }
2649
 
2651
  }
2652
 
2653
  //scans the content dir to see if any -old dirs are present
2654
+ private function scan_old_dirs($print_as_comment = false) {
2655
  global $updraftplus;
2656
  $dirs = scandir(untrailingslashit(WP_CONTENT_DIR));
2657
  if (!is_array($dirs)) $dirs = array();
2658
  $dirs_u = @scandir($updraftplus->backups_dir_location());
2659
  if (!is_array($dirs_u)) $dirs_u = array();
2660
+ foreach (array_merge($dirs, $dirs_u) as $dir) {
2661
+ if (preg_match('/-old$/', $dir)) {
2662
+ if ($print_as_comment) echo '<!--'.htmlspecialchars($dir).'-->';
2663
+ return true;
2664
+ }
2665
+ }
2666
  # No need to scan ABSPATH - we don't backup there
2667
+ if (is_dir(untrailingslashit(WP_PLUGIN_DIR).'-old')) {
2668
+ if ($print_as_comment) echo '<!--'.htmlspecialchars(untrailingslashit(WP_PLUGIN_DIR).'-old').'-->';
2669
+ return true;
2670
+ }
2671
  return false;
2672
  }
2673
 
2767
  ?> <input type="number" min="1" step="1" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:48px;" />
2768
  </td>
2769
  </tr>
2770
+
2771
+ <!--
2772
+ <tr id="updraft_incremental_row">
2773
+ <th><?php _e('Incremental file backup intervals', 'updraftplus'); ?>:</th>
2774
+ <td>
2775
+ <?php do_action('updraftplus_incremental_cell', $selected_interval); ?>
2776
+ <a href="http://updraftplus.com/support/tell-me-more-about-incremental-backups/"><em><?php _e('Tell me more about incremental backups', 'updraftplus'); ?><em></a>
2777
+ </td>
2778
+ </tr>
2779
+ -->
2780
  <?php apply_filters('updraftplus_after_file_intervals', false, $selected_interval); ?>
2781
  <tr>
2782
  <th><?php _e('Database backup intervals','updraftplus'); ?>:</th>
2797
  </td>
2798
  </tr>
2799
  <tr class="backup-interval-description">
2800
+ <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>
2801
  <?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>'); ?>
2802
  </div></td>
2803
  </tr>
2804
  <tr>
2805
+ <th><?php _e('Include in files backup', 'updraftplus');?>:</th>
2806
  <td>
2807
 
2808
  <?php
2835
  }
2836
  ?>
2837
  <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>
2838
+ <?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>';?>
2839
  </td>
2840
  </tr>
2841
 
3039
  </tr>
3040
  <?php
3041
  $delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
3042
+ $split_every_mb = UpdraftPlus_Options::get_updraft_option('updraft_split_every', 500);
3043
+ if (!is_numeric($split_every_mb)) $split_every_mb = 500;
3044
  if ($split_every_mb < UPDRAFTPLUS_SPLIT_MIN) $split_every_mb = UPDRAFTPLUS_SPLIT_MIN;
3045
  ?>
3046
 
3051
 
3052
  <tr class="expertmode" style="display:none;">
3053
  <th><?php _e('Split archives every:','updraftplus');?></th>
3054
+ <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>
3055
  </tr>
3056
 
3057
  <tr class="deletelocal expertmode" style="display:none;">
3170
  }
3171
 
3172
  # If $basedirs is passed as an array, then $directorieses must be too
3173
+ private function recursive_directory_size($directorieses, $exclude = array(), $basedirs = '') {
3174
 
3175
  $size = 0;
3176
 
3181
 
3182
  if (is_string($basedirs)) $basedirs = array($basedirs);
3183
 
3184
+ foreach ($directorieses as $ind => $directories) {
 
 
3185
  if (!is_array($directories)) $directories=array($directories);
3186
 
3187
+ $basedir = empty($basedirs[$ind]) ? $basedirs[0] : $basedirs[$ind];
3188
+
3189
  foreach ($directories as $dir) {
3190
  if (is_file($dir)) {
3191
  $size += @filesize($dir);
3197
 
3198
  }
3199
 
3200
+ // foreach ($basedirs as $ind => $basedir) {
3201
+ //
3202
+ // $directories = $directorieses[$ind];
3203
+ // if (!is_array($directories)) $directories=array($directories);
3204
+ //
3205
+ // foreach ($directories as $dir) {
3206
+ // error_log($dir);
3207
+ // if (is_file($dir)) {
3208
+ // $size += @filesize($dir);
3209
+ // } else {
3210
+ // $suffix = ('' != $basedir) ? ((0 === strpos($dir, $basedir.'/')) ? substr($dir, 1+strlen($basedir)) : '') : '';
3211
+ // $size += $this->recursive_directory_size_raw($basedir, $exclude, $suffix);
3212
+ // }
3213
+ // }
3214
+ //
3215
+ // }
3216
+
3217
  if ($size > 1073741824) {
3218
  return round($size / 1073741824, 1).' Gb';
3219
  } elseif ($size > 1048576) {
3226
 
3227
  }
3228
 
3229
+ private function recursive_directory_size_raw($prefix_directory, &$exclude = array(), $suffix_directory = '') {
3230
 
3231
  $directory = $prefix_directory.('' == $suffix_directory ? '' : '/'.$suffix_directory);
3232
  $size = 0;
3233
  if(substr($directory, -1) == '/') $directory = substr($directory,0,-1);
3234
 
3235
  if(!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) return -1;
3236
+ if (file_exists($directory.'/.donotbackup')) return 0;
3237
 
3238
  if($handle = opendir($directory)) {
3239
  while (($file = readdir($handle)) !== false) {
3295
  $entities = '';
3296
  $sval = ((isset($backup['service']) && $backup['service'] != 'email' && $backup['service'] != 'none')) ? '1' : '0';
3297
  $title = __('Delete this backup set', 'updraftplus');
3298
+ $non = $backup['nonce'];
3299
+ $rawbackup = "<h2>$esc_pretty_date ($key)</h2><pre><p>".esc_attr(print_r($backup, true));
3300
+ if (!empty($non)) {
3301
+ $jd = $updraftplus->jobdata_getarray($non);
3302
+ if (!empty($jd) && is_array($jd)) {
3303
+ $rawbackup .= '</p><p>'.esc_attr(print_r($jd, true));
3304
+ }
3305
+ }
3306
+ $rawbackup .= '</p></pre>';
3307
+
3308
+ $jobdata = $updraftplus->jobdata_getarray($non);
3309
+ $datespan = apply_filters('updraftplus_showbackup_date', $pretty_date, $backup, $jobdata);
3310
+
3311
  $ret .= <<<ENDHERE
3312
  <tr id="updraft_existing_backups_row_$key">
3313
+ <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>
3314
  ENDHERE;
3315
 
3316
+ # TODO: This probably isn't showing the right thing when an incremental backup finishes
3317
  if (is_array($jobdata) && !empty($jobdata['resume_interval']) && (empty($jobdata['jobstatus']) || 'finished' != $jobdata['jobstatus'])) {
3318
+ $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);
3319
  }
3320
 
3321
  $ret .= "</td>\n";
3325
  if (isset($backup['db'])) {
3326
  $entities .= '/db=0/';
3327
  $sdescrip = preg_replace('/ \(.*\)$/', '', __('Database','updraftplus'));
 
3328
 
3329
+ if (!empty($backup['meta_foreign']) && isset($accept[$backup['meta_foreign']])) {
3330
  $desc_source = $accept[$backup['meta_foreign']]['desc'];
3331
  } else {
3332
  $desc_source = __('unknown source', 'updraftplus');
3366
  $entities = '/db=0/meta_foreign=1/';
3367
  }
3368
 
3369
+ if (!empty($backup['meta_foreign']) && !empty($accept[$backup['meta_foreign']]) && !empty($accept[$backup['meta_foreign']]['separatedb'])) {
3370
  $entities .= '/meta_foreign=2/';
3371
  }
3372
 
3502
  // If $remotescan is set, then remote storage is also scanned
3503
  public function rebuild_backup_history($remotescan = false) {
3504
 
3505
+ # TODO: Make compatible with incremental naming scheme
3506
+
3507
  global $updraftplus;
3508
  $messages = array();
3509
  $gmt_offset = get_option('gmt_offset');
3510
 
3511
+ # Array of nonces keyed by filename
3512
  $known_files = array();
3513
+ # Array of backup times keyed by nonce
3514
  $known_nonces = array();
3515
  $changes = false;
3516
 
3523
 
3524
  $accept = apply_filters('updraftplus_accept_archivename', array());
3525
  if (!is_array($accept)) $accept = array();
3526
+ // Process what is known from the database backup history; this means populating $known_files and $known_nonces
3527
  foreach ($backup_history as $btime => $bdata) {
3528
  $found_file = false;
3529
  foreach ($bdata as $key => $values) {
3539
  } else {
3540
  $found_file = true;
3541
  $known_files[$val] = $nonce;
3542
+ $known_nonces[$nonce] = (empty($known_nonces[$nonce]) || $known_nonces[$nonce]<100) ? $btime : min($btime, $known_nonces[$nonce]);
3543
  }
3544
  } else {
3545
  $accepted = false;
3548
  }
3549
  if (!empty($accepted) && (false != ($btime = apply_filters('updraftplus_foreign_gettime', false, $fkey, $val))) && $btime > 0) {
3550
  $found_file = true;
3551
+ # Generate a nonce; this needs to be deterministic and based on the filename only
3552
  $nonce = substr(md5($val), 0, 12);
3553
  $known_files[$val] = $nonce;
3554
+ $known_nonces[$nonce] = (empty($known_nonces[$nonce]) || $known_nonces[$nonce]<100) ? $btime : min($btime, $known_nonces[$nonce]);
3555
  }
3556
  }
3557
  }
3566
  $remotefiles = array();
3567
  $remotesizes = array();
3568
  # Scan remote storage and get back lists of files and their sizes
3569
+ # TODO: Make compatible with incremental naming
3570
  if ($remotescan) {
3571
  foreach ($updraftplus->backup_methods as $method => $desc) {
3572
  require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
3608
  $accepted_foreign = false;
3609
  $potmessage = false;
3610
  if ('.' == $entry || '..' == $entry) continue;
3611
+ # TODO: Make compatible with Incremental naming
3612
  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)) {
3613
 
3614
  // Interpret the time as one from the blog's local timezone, rather than as UTC
3625
  $index = (empty($matches[4])) ? '0' : (max((int)$matches[4]-1,0));
3626
  }
3627
  $itext = ($index == 0) ? '' : $index;
3628
+ } elseif (false != ($accepted_foreign = apply_filters('updraftplus_accept_foreign', false, $entry)) && false !== ($btime = apply_filters('updraftplus_foreign_gettime', false, $accepted_foreign, $entry))) {
3629
  $nonce = substr(md5($entry), 0, 12);
3630
  $type = preg_match('/\.sql(\.(bz2|gz))?$/', $entry) ? 'db' : 'wpcore';
3631
  $index = '0';
3649
  continue;
3650
  }
3651
  // The time from the filename does not include seconds. Need to identify the seconds to get the right time
3652
+ if (isset($known_nonces[$nonce])) {
3653
+ $btime_exact = $known_nonces[$nonce];
3654
+ # 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)
3655
+ if ($btime > 100 && $btime_exact - $btime > 60 && !empty($backup_history[$btime_exact])) {
3656
+ # TODO: This needs testing
3657
+ # The code below assumes that $backup_history[$btime] is presently empty
3658
+ # Re-key array, indicating the newly-found time to be the start of the backup set
3659
+ $backup_history[$btime] = $backup_history[$btime_exact];
3660
+ unset($backup_history[$btime_exact]);
3661
+ $btime_exact = $btime;
3662
+ }
3663
+ $btime = $btime_exact;
3664
+ }
3665
  if ($btime <= 100) continue;
3666
  $fs = @filesize($updraft_dir.'/'.$entry);
3667
 
3670
  if (is_array($potmessage)) $messages[$potmessage['code']] = $potmessage;
3671
  }
3672
 
3673
+ # TODO: Code below here has not been reviewed or adjusted for compatibility with incremental backups
3674
  # Make sure we have the right list of services
3675
  $current_services = (!empty($backup_history[$btime]) && !empty($backup_history[$btime]['service'])) ? $backup_history[$btime]['service'] : array();
3676
  if (is_string($current_services)) $current_services = array($current_services);
3767
  }
3768
 
3769
  // Return values: false = 'not yet' (not necessarily terminal); WP_Error = terminal failure; true = success
3770
+ private function restore_backup($timestamp) {
3771
 
3772
  @set_time_limit(900);
3773
 
3795
  $credentials = request_filesystem_credentials(UpdraftPlus_Options::admin_page()."?page=updraftplus&action=updraft_restore&backup_timestamp=$timestamp", '', false, false, $extra_fields);
3796
  WP_Filesystem($credentials);
3797
  if ( $wp_filesystem->errors->get_error_code() ) {
3798
+ echo '<p><em><a href="http://updraftplus.com/faqs/asked-ftp-details-upon-restorationmigration-updates/">'.__('Why am I seeing this?', 'updraftplus').'</a></em></p>';
3799
  foreach ( $wp_filesystem->errors->get_error_messages() as $message ) show_message($message);
3800
+ exit;
3801
  }
3802
 
3803
  # Set up logging
3833
  if (empty($backup_set['meta_foreign'])) {
3834
  $entities_to_restore[$entity] = $entity;
3835
  } else {
3836
+ if ('db' == $entity && !empty($foreign_known[$backup_set['meta_foreign']]) && !empty($foreign_known[$backup_set['meta_foreign']]['separatedb'])) {
3837
  $entities_to_restore[$entity] = 'db';
3838
  } else {
3839
  $entities_to_restore[$entity] = 'wpcore';
4035
  if (!empty($data)) {
4036
  $pdata = (is_string($data)) ? $data : serialize($data);
4037
  echo '<strong>'.__('Error data:', 'updraftplus').'</strong> '.htmlspecialchars($pdata).'<br>';
4038
+ if (false !== strpos($pdata, 'PCLZIP_ERR_BAD_FORMAT (-10)')) {
4039
+ echo '<a href="http://updraftplus.com/faqs/error-message-pclzip_err_bad_format-10-invalid-archive-structure-mean/"><strong>'.__('Please consult this FAQ for help on what to do about it.', 'updraftplus').'</strong></a><br>';
4040
+ }
4041
  }
4042
  }
4043
  }
4044
  echo '</div>'; //close the updraft_restore_progress div even if we error
 
 
 
4045
  restore_error_handler();
4046
  return $val;
4047
  } elseif (false === $val) {
4057
  foreach (array('template', 'stylesheet', 'template_root', 'stylesheet_root') as $opt) {
4058
  add_filter('pre_option_'.$opt, array($this, 'option_filter_'.$opt));
4059
  }
4060
+ if (!function_exists('validate_current_theme')) require_once(ABSPATH.WPINC.'/themes');
4061
 
4062
  # Have seen a case where the current theme in the DB began with a capital, but not on disk - and this breaks migrating from Windows to a case-sensitive system
4063
  $template = get_option('template');
4119
  private function get_settings_keys() {
4120
  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',
4121
  'updraft_lastmessage', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder',
4122
+ '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');
4123
  }
4124
 
4125
  }
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
 
@@ -11,8 +11,9 @@ class UpdraftPlus_Backup {
11
 
12
  private $zipfiles_added;
13
  private $zipfiles_added_thisrun = 0;
14
- private $zipfiles_dirbatched;
15
- private $zipfiles_batched;
 
16
  private $zip_split_every = 838860800; # 800Mb
17
  private $zip_last_ratio = 1;
18
  private $whichone;
@@ -24,15 +25,22 @@ class UpdraftPlus_Backup {
24
  private $dbhandle;
25
  private $dbhandle_isgz;
26
 
 
 
 
 
 
27
  private $use_zip_object = 'UpdraftPlus_ZipArchive';
28
  public $debug = false;
29
 
30
- private $updraft_dir;
31
  private $blog_name;
32
  private $wpdb_obj;
33
  private $job_file_entities = array();
34
 
35
- public function __construct($backup_files) {
 
 
36
 
37
  global $updraftplus;
38
 
@@ -51,6 +59,8 @@ class UpdraftPlus_Backup {
51
  return;
52
  }
53
 
 
 
54
  // false means 'tried + failed'; whereas 0 means 'not yet tried'
55
  // Disallow binzip on OpenVZ when we're not sure there's plenty of memory
56
  if ($this->binzip === 0 && (!defined('UPDRAFTPLUS_PREFERPCLZIP') || UPDRAFTPLUS_PREFERPCLZIP != true) && (!defined('UPDRAFTPLUS_NO_BINZIP') || !UPDRAFTPLUS_NO_BINZIP) && $updraftplus->current_resumption <9) {
@@ -117,6 +127,7 @@ class UpdraftPlus_Backup {
117
  return false;
118
  }
119
 
 
120
  $itext = (empty($index)) ? '' : ($index+1);
121
  $base_path = $backup_file_basename.'-'.$whichone.$itext.'.zip';
122
  $full_path = $this->updraft_dir.'/'.$base_path;
@@ -133,7 +144,8 @@ class UpdraftPlus_Backup {
133
  $updraftplus->terminate_due_to_activity($base_path, $time_now, $time_mod);
134
  }
135
  $index++;
136
- $base_path = $backup_file_basename.'-'.$whichone.$index.'.zip';
 
137
  $full_path = $this->updraft_dir.'/'.$base_path;
138
  }
139
  }
@@ -159,6 +171,7 @@ class UpdraftPlus_Backup {
159
  $match = '_'.$updraftplus->nonce."-".$whichone;
160
  while (false !== ($e = $d->read())) {
161
  if ('.' == $e || '..' == $e || !is_file($this->updraft_dir.'/'.$e)) continue;
 
162
  $ziparchive_match = preg_match("/$match([0-9]+)?\.zip\.tmp\.([A-Za-z0-9]){6}?$/i", $e);
163
  $binzip_match = preg_match("/^zi([A-Za-z0-9]){6}$/", $e);
164
  if ($time_now-filemtime($this->updraft_dir.'/'.$e) < 30 && ($ziparchive_match || (0 != $updraftplus->current_resumption && $binzip_match))) {
@@ -186,6 +199,7 @@ class UpdraftPlus_Backup {
186
  return false;
187
  } else {
188
  $itext = (empty($this->index)) ? '' : ($this->index+1);
 
189
  $full_path = $this->updraft_dir.'/'.$backup_file_basename.'-'.$whichone.$itext.'.zip';
190
  if (file_exists($full_path.'.tmp')) {
191
  if (@filesize($full_path.'.tmp') === 0) {
@@ -211,6 +225,7 @@ class UpdraftPlus_Backup {
211
  $updraftplus->clean_temporary_files('_'.$updraftplus->nonce."-$whichone", 0);
212
  }
213
 
 
214
  # Create the results array to send back (just the new ones, not any prior ones)
215
  $files_existing = array();
216
  $res_index = 0;
@@ -284,7 +299,7 @@ class UpdraftPlus_Backup {
284
  $objname = "UpdraftPlus_BackupModule_${service}";
285
  if (class_exists($objname)) {
286
  $remote_obj = new $objname;
287
- $pass_to_prune = $remote_obj->backup($backup_array);
288
  $do_prune[$service] = array($remote_obj, $pass_to_prune);
289
  } else {
290
  $updraftplus->log("Unexpected error: no class '$objname' was found ($method_include)");
@@ -461,7 +476,8 @@ class UpdraftPlus_Backup {
461
  if (!is_null($method_object)) $method_object->delete($dofiles, $object_passback);
462
  }
463
 
464
- public function send_results_email($final_message) {
 
465
 
466
  global $updraftplus;
467
 
@@ -470,19 +486,23 @@ class UpdraftPlus_Backup {
470
  $sendmail_to = $updraftplus->just_one_email(UpdraftPlus_Options::get_updraft_option('updraft_email'));
471
  if (is_string($sendmail_to)) $sendmail_to = array($sendmail_to);
472
 
473
- $backup_files = $updraftplus->jobdata_get('backup_files');
474
- $backup_db = $updraftplus->jobdata_get('backup_database');
475
 
476
  if (is_array($backup_db)) $backup_db = $backup_db['wp'];
477
  if (is_array($backup_db)) $backup_db = $backup_db['status'];
478
 
 
 
479
  if ('finished' == $backup_files && ('finished' == $backup_db || 'encrypted' == $backup_db)) {
480
- $backup_contains = __("Files and database", 'updraftplus');
481
  } elseif ('finished' == $backup_files) {
482
  $backup_contains = ($backup_db == "begun") ? __("Files (database backup has not completed)", 'updraftplus') : __("Files only (database was not part of this particular schedule)", 'updraftplus');
 
483
  } elseif ($backup_db == 'finished' || $backup_db == 'encrypted') {
484
  $backup_contains = ($backup_files == "begun") ? __("Database (files backup has not completed)", 'updraftplus') : __("Database only (files were not part of this particular schedule)", 'updraftplus');
485
  } else {
 
486
  $backup_contains = __("Unknown/unexpected error - please raise a support request", 'updraftplus');
487
  }
488
 
@@ -508,7 +528,7 @@ class UpdraftPlus_Backup {
508
  }
509
  $append_log.="\r\n";
510
  }
511
- $warnings = $updraftplus->jobdata_get('warnings');
512
  if (is_array($warnings) && count($warnings) >0) {
513
  $append_log .= __('Warnings encountered:', 'updraftplus')."\r\n";
514
  $attachments[0] = $updraftplus->logfile_name;
@@ -529,7 +549,7 @@ class UpdraftPlus_Backup {
529
 
530
  # The class_exists() check here is a micro-optimization to prevent a possible HTTP call whose results may be disregarded by the filter
531
  $feed = '';
532
- if (!class_exists('UpdraftPlus_Addon_Reporting') && !defined('UPDRAFTPLUS_NOADS_A') && !defined('UPDRAFTPLUS_NONEWSFEED')) {
533
  $updraftplus->log('Fetching RSS news feed');
534
  $rss = $updraftplus->get_updraftplus_rssfeed();
535
  $updraftplus->log('Fetched RSS news feed; result is a: '.get_class($rss));
@@ -546,7 +566,25 @@ class UpdraftPlus_Backup {
546
  $feed .= "\r\n\r\n";
547
  }
548
 
549
- $body = apply_filters('updraft_report_body', __('Backup of:').' '.site_url()."\r\nUpdraftPlus ".__('WordPress backup is complete','updraftplus').".\r\n".__('Backup contains:','updraftplus').' '.$backup_contains."\r\n".__('Latest status:', 'updraftplus').' '.$final_message."\r\n\r\n".$feed.$updraftplus->wordshell_random_advert(0)."\r\n".$append_log, $final_message, $backup_contains, $updraftplus->errors, $warnings);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
550
 
551
  $this->attachments = apply_filters('updraft_report_attachments', $attachments);
552
 
@@ -585,7 +623,11 @@ class UpdraftPlus_Backup {
585
 
586
  foreach (explode(',', $mailto) as $sendmail_addr) {
587
  $updraftplus->log("Sending email ('$backup_contains') report (attachments: ".count($attachments).", size: ".round($attach_size/1024, 1)." Kb) to: ".substr($sendmail_addr, 0, 5)."...");
588
- wp_mail(trim($sendmail_addr), $subject, $body);
 
 
 
 
589
  }
590
  }
591
 
@@ -603,7 +645,7 @@ class UpdraftPlus_Backup {
603
 
604
  global $updraftplus;
605
  if ($a == $b) return 0;
606
- $our_table_prefix = $this->table_prefix;
607
  if ($a == $our_table_prefix.'options') return -1;
608
  if ($b == $our_table_prefix.'options') return 1;
609
  if ($a == $our_table_prefix.'users') return -1;
@@ -690,18 +732,20 @@ class UpdraftPlus_Backup {
690
  $index = (int)$this->job_file_entities[$youwhat]['index'];
691
  if (empty($index)) $index=0;
692
  $indextext = (0 == $index) ? '' : (1+$index);
 
693
  $zip_file = $this->updraft_dir.'/'.$backup_file_basename.'-'.$youwhat.$indextext.'.zip';
694
 
695
  # Split needed?
696
- $split_every=max((int)$updraftplus->jobdata_get('split_every'), 250);
697
  if (file_exists($zip_file) && filesize($zip_file) > $split_every*1048576) {
698
  $index++;
699
  $this->job_file_entities[$youwhat]['index'] = $index;
700
  $updraftplus->jobdata_set('job_file_entities', $this->job_file_entities);
701
  }
702
 
 
703
  // Populate prior parts of array, if we're on a subsequent zip file
704
- if ($index >0) {
705
  for ($i=0; $i<$index; $i++) {
706
  $itext = (0 == $i) ? '' : ($i+1);
707
  $backup_array[$youwhat][$i] = $backup_file_basename.'-'.$youwhat.$itext.'.zip';
@@ -714,6 +758,7 @@ class UpdraftPlus_Backup {
714
  if ('finished' == $job_status) {
715
  // Add the final part of the array
716
  if ($index >0) {
 
717
  $fbase = $backup_file_basename.'-'.$youwhat.($index+1).'.zip';
718
  $z = $this->updraft_dir.'/'.$fbase;
719
  if (file_exists($z)) {
@@ -801,7 +846,8 @@ class UpdraftPlus_Backup {
801
  foreach ($files as $file) $updraftplus->check_recent_modification($this->updraft_dir.'/'.$file);
802
  }
803
  } elseif ('begun' == $bfiles_status) {
804
- if ($resumption_no>0) {
 
805
  $updraftplus->log("Creation of backups of directories: had begun; will resume");
806
  } else {
807
  $updraftplus->log("Creation of backups of directories: beginning");
@@ -991,14 +1037,16 @@ class UpdraftPlus_Backup {
991
  }
992
 
993
  # 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??)
994
- $bindump = (isset($rows) && $rows>8000 && is_string($binsqldump)) ? $this->backup_table_bindump($binsqldump, $table, $where) : false;
 
 
 
 
995
  if (true !== $bindump) $this->backup_table($table, $where);
996
 
997
  if (!empty($manyrows_warning)) $updraftplus->log_removewarning('manyrows_'.$this->whichdb_suffix.$table);
998
 
999
- // Close file
1000
-
1001
- $this->close($this->dbhandle);
1002
 
1003
  $updraftplus->log("Table $table: finishing file (${table_file_prefix}.gz - ".round(filesize($this->updraft_dir.'/'.$table_file_prefix.'.tmp.gz')/1024,1)." Kb)");
1004
 
@@ -1047,7 +1095,7 @@ class UpdraftPlus_Backup {
1047
  $updraftplus->log("PHP function is disabled; abort expected: gzopen");
1048
  }
1049
 
1050
- if (false === ($opendb = $this->backup_db_open($backup_final_file_name, true))) return false;
1051
 
1052
  $this->backup_db_header();
1053
 
@@ -1074,7 +1122,7 @@ class UpdraftPlus_Backup {
1074
  }
1075
 
1076
  $updraftplus->log($file_base.'-db'.$this->whichdb_suffix.'.gz: finished writing out complete database file ('.round(filesize($backup_final_file_name)/1024,1).' Kb)');
1077
- if (!$this->close($this->dbhandle)) {
1078
  $updraftplus->log('An error occurred whilst closing the final database file');
1079
  $updraftplus->log(__('An error occurred whilst closing the final database file', 'updraftplus'), 'error');
1080
  $errors++;
@@ -1229,7 +1277,8 @@ class UpdraftPlus_Backup {
1229
 
1230
  $increment = 1000;
1231
  if (!$updraftplus->something_useful_happened && !empty($updraftplus->current_resumption) && ($updraftplus->current_resumption - $updraftplus->last_successful_resumption > 1)) {
1232
- $increment = 500;
 
1233
  }
1234
 
1235
  if($segment == 'none') {
@@ -1311,16 +1360,12 @@ class UpdraftPlus_Backup {
1311
  }
1312
  }
1313
 
1314
- private function close($handle) {
1315
- if ($this->dbhandle_isgz) {
1316
- return gzclose($handle);
1317
- } else {
1318
- return fclose($handle);
1319
- }
1320
  }
1321
 
1322
  // Open a file, store its filehandle
1323
- private function backup_db_open($file, $allow_gz = true) {
1324
  if (function_exists('gzopen') && $allow_gz == true) {
1325
  $this->dbhandle = @gzopen($file, 'w');
1326
  $this->dbhandle_isgz = true;
@@ -1336,21 +1381,22 @@ class UpdraftPlus_Backup {
1336
  return $this->dbhandle;
1337
  }
1338
 
1339
- private function stow($query_line) {
1340
  if ($this->dbhandle_isgz) {
1341
- if(! @gzwrite($this->dbhandle, $query_line)) {
1342
  //$updraftplus->log(__('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg, 'error');
1343
  }
1344
  } else {
1345
- if(false === @fwrite($this->dbhandle, $query_line)) {
1346
  //$updraftplus->log(__('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg, 'error');
1347
  }
1348
  }
 
1349
  }
1350
 
1351
  private function backup_db_header() {
1352
 
1353
- @include(ABSPATH.'wp-includes/version.php');
1354
  global $wp_version, $updraftplus;
1355
 
1356
  $mysql_version = $this->wpdb_obj->db_version();
@@ -1409,6 +1455,7 @@ class UpdraftPlus_Backup {
1409
  // $exclude is passed by reference so that we can remove elements as they are matched - saves time checking against already-dealt-with objects
1410
  private function makezip_recursive_add($fullpath, $use_path_when_storing, $original_fullpath, $startlevels = 1, &$exclude) {
1411
 
 
1412
  $zipfile = $this->zip_basename.(($this->index == 0) ? '' : ($this->index+1)).'.zip.tmp';
1413
 
1414
  global $updraftplus;
@@ -1419,7 +1466,7 @@ class UpdraftPlus_Backup {
1419
 
1420
  // Is the place we've ended up above the original base? That leads to infinite recursion
1421
  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)))) {
1422
- $updraftplus->log("Infinite recursion: symlink lead us to $fullpath, which is within $original_fullpath");
1423
  $updraftplus->log(__("Infinite recursion: consult your log for more information",'updraftplus'), 'error');
1424
  return false;
1425
  }
@@ -1432,25 +1479,37 @@ class UpdraftPlus_Backup {
1432
  return true;
1433
  }
1434
 
1435
- if(is_file($fullpath)) {
 
 
1436
  if (is_readable($fullpath)) {
1437
- $key = ($fullpath == $original_fullpath) ? ((2 == $startlevels) ? $use_path_when_storing : basename($fullpath)) : $use_path_when_storing.'/'.basename($fullpath);
1438
- $this->zipfiles_batched[$fullpath] = $key;
1439
- $this->makezip_recursive_batchedbytes += @filesize($fullpath);
1440
- #@touch($zipfile);
 
 
 
 
 
1441
  } else {
1442
  $updraftplus->log("$fullpath: unreadable file");
1443
  $updraftplus->log(sprintf(__("%s: unreadable file - could not be backed up (check the file permissions)", 'updraftplus'), $fullpath), 'warning');
1444
  }
1445
  } elseif (is_dir($fullpath)) {
 
 
 
 
1446
  if (!isset($this->existing_files[$use_path_when_storing])) $this->zipfiles_dirbatched[] = $use_path_when_storing;
1447
  if (!$dir_handle = @opendir($fullpath)) {
1448
  $updraftplus->log("Failed to open directory: $fullpath");
1449
  $updraftplus->log(sprintf(__("Failed to open directory (check the file permissions): %s",'updraftplus'), $fullpath), 'error');
1450
  return false;
1451
  }
 
1452
  while (false !== ($e = readdir($dir_handle))) {
1453
- if ($e != '.' && $e != '..') {
1454
  if (is_link($fullpath.'/'.$e)) {
1455
  $deref = realpath($fullpath.'/'.$e);
1456
  if (is_file($deref)) {
@@ -1460,9 +1519,14 @@ class UpdraftPlus_Backup {
1460
  $updraftplus->log("Entity excluded by configuration option: $use_stripped");
1461
  unset($exclude[$fkey]);
1462
  } else {
1463
- $this->zipfiles_batched[$deref] = $use_path_when_storing.'/'.$e;
1464
- $this->makezip_recursive_batchedbytes += @filesize($deref);
1465
- #@touch($zipfile);
 
 
 
 
 
1466
  }
1467
  } else {
1468
  $updraftplus->log("$deref: unreadable file");
@@ -1478,9 +1542,13 @@ class UpdraftPlus_Backup {
1478
  $updraftplus->log("Entity excluded by configuration option: $use_stripped");
1479
  unset($exclude[$fkey]);
1480
  } else {
1481
- $this->zipfiles_batched[$fullpath.'/'.$e] = $use_path_when_storing.'/'.$e;
1482
- $this->makezip_recursive_batchedbytes += @filesize($fullpath.'/'.$e);
1483
- #@touch($zipfile);
 
 
 
 
1484
  }
1485
  } else {
1486
  $updraftplus->log("$fullpath/$e: unreadable file");
@@ -1497,19 +1565,7 @@ class UpdraftPlus_Backup {
1497
  $updraftplus->log("Unexpected: path ($use_path_when_storing) fails both is_file() and is_dir()");
1498
  }
1499
 
1500
- // We don't want to tweak the zip file on every single file, so we batch them up
1501
- // We go every 25 files, because if you wait too much longer, the contents may have changed from under you. Note though that since this fires once-per-directory, the actual number by this stage may be much larger; the most we saw was over 3000; but in that case, makezip_addfiles() will split the write-out up into smaller chunks
1502
- // And for some redundancy (redundant because of the touches going on anyway), we try to touch the file after 20 seconds, to help with the "recently modified" check on resumption (we saw a case where the file went for 155 seconds without being touched and so the other runner was not detected)
1503
- if (count($this->zipfiles_batched) > 25 || (file_exists($zipfile) && ((time()-filemtime($zipfile)) > 20) )) {
1504
- $ret = true;
1505
- # In fact, this is entirely redundant, and slows things down - the logic in makezip_addfiles() now does this, much better
1506
- # If adding this back in, then be careful - we now assume that makezip_recursive_add() does *not* touch the zipfile
1507
- // $ret = $this->makezip_addfiles();
1508
- } else {
1509
- $ret = true;
1510
- }
1511
-
1512
- return $ret;
1513
 
1514
  }
1515
 
@@ -1521,6 +1577,7 @@ class UpdraftPlus_Backup {
1521
 
1522
  $original_index = $this->index;
1523
 
 
1524
  $itext = (empty($this->index)) ? '' : ($this->index+1);
1525
  $destination_base = $backup_file_basename.'-'.$whichone.$itext.'.zip.tmp';
1526
  $destination = $this->updraft_dir.'/'.$destination_base;
@@ -1547,6 +1604,7 @@ class UpdraftPlus_Backup {
1547
  // Enumerate existing files
1548
  for ($j=0; $j<=$this->index; $j++) {
1549
  $jtext = ($j == 0) ? '' : ($j+1);
 
1550
  $examine_zip = $this->updraft_dir.'/'.$backup_file_basename.'-'.$whichone.$jtext.'.zip'.(($j == $this->index) ? '.tmp' : '');
1551
 
1552
  // If the file exists, then we should grab its index of files inside, and sizes
@@ -1598,13 +1656,11 @@ class UpdraftPlus_Backup {
1598
  $this->zipfiles_added_thisrun = 0;
1599
  $this->zipfiles_dirbatched = array();
1600
  $this->zipfiles_batched = array();
 
1601
  $this->zipfiles_lastwritetime = time();
1602
-
1603
  $this->zip_basename = $this->updraft_dir.'/'.$backup_file_basename.'-'.$whichone;
1604
 
1605
- if (!empty($do_bump_index)) {
1606
- $this->bump_index();
1607
- }
1608
 
1609
  $error_occurred = false;
1610
 
@@ -1616,13 +1672,22 @@ class UpdraftPlus_Backup {
1616
  if (!is_array($source)) $source=array($source);
1617
 
1618
  $exclude = $updraftplus->get_exclude($whichone);
 
 
 
 
 
 
 
 
1619
  foreach ($source as $element) {
1620
  #makezip_recursive_add($fullpath, $use_path_when_storing, $original_fullpath, $startlevels = 1, $exclude_array)
1621
  if ('uploads' == $whichone) {
1622
  $dirname = dirname($element);
1623
- $add_them = $this->makezip_recursive_add($element, basename($dirname).'/'.basename($element), $element, 2, $exclude);
 
1624
  } else {
1625
- $add_them = $this->makezip_recursive_add($element, basename($element), $element, 1, $exclude);
1626
  }
1627
  if (is_wp_error($add_them) || false === $add_them) $error_occurred = true;
1628
  }
@@ -1634,7 +1699,7 @@ class UpdraftPlus_Backup {
1634
  if (empty($do_bump_index)) @touch($destination);
1635
 
1636
  if (count($this->zipfiles_dirbatched)>0 || count($this->zipfiles_batched)>0) {
1637
- $updraftplus->log(sprintf("Total entities for the zip file: %d directories, %d files, %s Mb", count($this->zipfiles_dirbatched), count($this->zipfiles_batched), round($this->makezip_recursive_batchedbytes/1048576,1)));
1638
  $add_them = $this->makezip_addfiles();
1639
  if (is_wp_error($add_them)) {
1640
  foreach ($add_them->get_error_messages() as $msg) {
@@ -1650,6 +1715,7 @@ class UpdraftPlus_Backup {
1650
  # Reset these variables because the index may have changed since we began
1651
 
1652
  $itext = (empty($this->index)) ? '' : ($this->index+1);
 
1653
  $destination_base = $backup_file_basename.'-'.$whichone.$itext.'.zip.tmp';
1654
  $destination = $this->updraft_dir.'/'.$destination_base;
1655
 
@@ -1674,6 +1740,23 @@ class UpdraftPlus_Backup {
1674
 
1675
  }
1676
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1677
  // Q. Why don't we only open and close the zip file just once?
1678
  // 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)
1679
 
@@ -1685,6 +1768,7 @@ class UpdraftPlus_Backup {
1685
  # Used to detect requests to bump the size
1686
  $bump_index = false;
1687
 
 
1688
  $zipfile = $this->zip_basename.(($this->index == 0) ? '' : ($this->index+1)).'.zip.tmp';
1689
 
1690
  $maxzipbatch = $updraftplus->jobdata_get('maxzipbatch', 26214400);
@@ -1696,33 +1780,43 @@ class UpdraftPlus_Backup {
1696
  # 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)
1697
  # This assumes that makezip_addfiles() is only called once so that we know about all needed files (the new style)
1698
  # This is rather conservative - because it assumes zero compression. But we can't know that in advance.
1699
- 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))) {
1700
- $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)");
1701
- if(!class_exists('PclZip')) require_once(ABSPATH.'/wp-admin/includes/class-pclzip.php');
1702
- $zip = new PclZip($zipfile);
1703
- $remove_path = ($this->whichone == 'wpcore') ? untrailingslashit(ABSPATH) : WP_CONTENT_DIR;
1704
- $add_path = false;
1705
- // Remove prefixes
1706
- $backupable_entities = $updraftplus->get_backupable_file_entities(true);
1707
- if (isset($backupable_entities[$this->whichone])) {
1708
- if ('plugins' == $this->whichone || 'themes' == $this->whichone || 'uploads' == $this->whichone) {
1709
- $remove_path = dirname($backupable_entities[$this->whichone]);
1710
- # 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.
1711
- #$add_path = $this->whichone;
1712
- } else {
1713
- $remove_path = $backupable_entities[$this->whichone];
1714
- }
1715
- }
1716
- if ($add_path) {
1717
- $zipcode = $zip->create($this->source, PCLZIP_OPT_REMOVE_PATH, $remove_path, PCLZIP_OPT_ADD_PATH, $add_path);
1718
- } else {
1719
- $zipcode = $zip->create($this->source, PCLZIP_OPT_REMOVE_PATH, $remove_path);
1720
- }
1721
- if ($zipcode == 0 ) {
1722
- $updraftplus->log("PclZip Error: ".$zip->errorInfo(true), 'warning');
1723
- return $zip->errorCode();
1724
- } else {
1725
- return true;
 
 
 
 
 
 
 
 
 
 
1726
  }
1727
  }
1728
 
@@ -1744,11 +1838,11 @@ class UpdraftPlus_Backup {
1744
  }
1745
 
1746
  if ($opencode !== true) return new WP_Error('no_open', sprintf(__('Failed to open the zip file (%s) - %s', 'updraftplus'),$zipfile, $zip->last_error));
1747
- // Make sure all directories are created before we start creating files
1748
- while ($dir = array_pop($this->zipfiles_dirbatched)) {
1749
- $zip->addEmptyDir($dir);
1750
- }
1751
 
 
 
1752
  $zipfiles_added_thisbatch = 0;
1753
 
1754
  // Go through all those batched files
@@ -1772,7 +1866,7 @@ class UpdraftPlus_Backup {
1772
  $data_added_since_reopen += $fsize;
1773
  /* Conditions for forcing a write-out and re-open:
1774
  - more than $maxzipbatch bytes have been batched
1775
- - more than 1.5 seconds have passed since the last time we wrote
1776
  - 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)
1777
  - more than 500 files batched (should perhaps intelligently lower this as the zip file gets bigger - not yet needed)
1778
  */
@@ -1781,7 +1875,7 @@ class UpdraftPlus_Backup {
1781
  # 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
1782
  $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;
1783
 
1784
- if ($zipfiles_added_thisbatch > UPDRAFTPLUS_MAXBATCHFILES || $reaching_split_limit || $data_added_since_reopen > $maxzipbatch || (time() - $this->zipfiles_lastwritetime) > 1.5) {
1785
 
1786
  @set_time_limit(900);
1787
  $something_useful_sizetest = false;
@@ -1792,7 +1886,7 @@ class UpdraftPlus_Backup {
1792
  } elseif ($zipfiles_added_thisbatch > UPDRAFTPLUS_MAXBATCHFILES) {
1793
  $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)');
1794
  } elseif (!$reaching_split_limit) {
1795
- $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)');
1796
  } else {
1797
  $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)');
1798
  }
@@ -1811,7 +1905,7 @@ class UpdraftPlus_Backup {
1811
  // Call here, in case we've got so many big files that we don't complete the whole routine
1812
  if (filesize($zipfile) > $original_size) {
1813
 
1814
- # 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
1815
  $this->zip_last_ratio = ($data_added_since_reopen > 0) ? min((filesize($zipfile) - $original_size)/$data_added_since_reopen, 1) : 1;
1816
 
1817
  # We need a rolling update of this
@@ -1857,7 +1951,7 @@ class UpdraftPlus_Backup {
1857
  if ($updraftplus->current_resumption >= 1) {
1858
  $time_passed = $updraftplus->jobdata_get('run_times');
1859
  if (!is_array($time_passed)) $time_passed = array();
1860
- list($max_time, $timings_string, $run_times_known) = $updraftplus->max_time_passed($time_passed, $updraftplus->current_resumption-1);
1861
  } else {
1862
  $run_times_known = 0;
1863
  $max_time = -1;
@@ -1953,7 +2047,7 @@ class UpdraftPlus_Backup {
1953
  $this->zipfiles_lastwritetime = time();
1954
  }
1955
  } elseif (0 == $this->zipfiles_added_thisrun) {
1956
- // 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.
1957
  // Testing shows that calling time() 1000 times takes negligible time
1958
  $this->zipfiles_lastwritetime=time();
1959
  }
@@ -1965,8 +2059,10 @@ class UpdraftPlus_Backup {
1965
  $updraftplus->log(sprintf("Zip size is at/near split limit (%s Mb / %s Mb) - bumping index (from: %d)", $bumped_at, round($this->zip_split_every/1048576, 1), $this->index));
1966
  $bump_index = false;
1967
  $this->bump_index();
 
1968
  $zipfile = $this->zip_basename.($this->index+1).'.zip.tmp';
1969
  }
 
1970
  if (empty($zip)) {
1971
  $zip = new $this->use_zip_object;
1972
 
@@ -1980,16 +2076,16 @@ class UpdraftPlus_Backup {
1980
  $original_size = 0;
1981
  }
1982
 
1983
- if ($opencode !== true) return new WP_Error('no_open', sprintf(__('Failed to open the zip file (%s) - %s', 'updraftplus'),$zipfile, $zip->last_error));
1984
  }
1985
 
1986
  }
1987
 
1988
  # Reset array
1989
  $this->zipfiles_batched = array();
 
1990
 
1991
- $ret = $zip->close();
1992
- if (!$ret) {
1993
  $updraftplus->log(__('A zip error occurred - check your log for more details.', 'updraftplus'), 'warning', 'zipcloseerror');
1994
  $updraftplus->log("Closing the zip file returned an error (".$zip->last_error."). List of files we were trying to add follows (check their permissions).");
1995
  foreach ($files_zipadded_since_open as $ffile) {
@@ -1997,6 +2093,8 @@ class UpdraftPlus_Backup {
1997
  }
1998
  }
1999
 
 
 
2000
  $this->zipfiles_lastwritetime = time();
2001
  # May not exist if the last thing we did was bump
2002
  if (file_exists($zipfile) && filesize($zipfile) > $original_size) $updraftplus->something_useful_happened();
@@ -2027,6 +2125,7 @@ class UpdraftPlus_Backup {
2027
  # We touch the next zip before renaming the temporary file; this indicates that the backup for the entity is not *necessarily* finished
2028
  touch($next_full_path.'.tmp');
2029
 
 
2030
  @rename($full_path.'.tmp', $full_path);
2031
  $kbsize = filesize($full_path)/1024;
2032
  $rate = round($kbsize/$timetaken, 1);
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
 
11
 
12
  private $zipfiles_added;
13
  private $zipfiles_added_thisrun = 0;
14
+ public $zipfiles_dirbatched;
15
+ public $zipfiles_batched;
16
+ public $zipfiles_skipped_notaltered;
17
  private $zip_split_every = 838860800; # 800Mb
18
  private $zip_last_ratio = 1;
19
  private $whichone;
25
  private $dbhandle;
26
  private $dbhandle_isgz;
27
 
28
+ # Array of entities => times
29
+ private $altered_since = -1;
30
+ # Time for the current entity
31
+ private $makezip_if_altered_since = -1;
32
+
33
  private $use_zip_object = 'UpdraftPlus_ZipArchive';
34
  public $debug = false;
35
 
36
+ public $updraft_dir;
37
  private $blog_name;
38
  private $wpdb_obj;
39
  private $job_file_entities = array();
40
 
41
+ private $first_run = 0;
42
+
43
+ public function __construct($backup_files, $altered_since = -1) {
44
 
45
  global $updraftplus;
46
 
59
  return;
60
  }
61
 
62
+ $this->altered_since = $altered_since;
63
+
64
  // false means 'tried + failed'; whereas 0 means 'not yet tried'
65
  // Disallow binzip on OpenVZ when we're not sure there's plenty of memory
66
  if ($this->binzip === 0 && (!defined('UPDRAFTPLUS_PREFERPCLZIP') || UPDRAFTPLUS_PREFERPCLZIP != true) && (!defined('UPDRAFTPLUS_NO_BINZIP') || !UPDRAFTPLUS_NO_BINZIP) && $updraftplus->current_resumption <9) {
127
  return false;
128
  }
129
 
130
+ # TODO: Make compatible with filenames which indicate increments
131
  $itext = (empty($index)) ? '' : ($index+1);
132
  $base_path = $backup_file_basename.'-'.$whichone.$itext.'.zip';
133
  $full_path = $this->updraft_dir.'/'.$base_path;
144
  $updraftplus->terminate_due_to_activity($base_path, $time_now, $time_mod);
145
  }
146
  $index++;
147
+ # TODO: Make compatible with filenames which indicate increments
148
+ $base_path = $backup_file_basename.'-'.$whichone.($index+1).'.zip';
149
  $full_path = $this->updraft_dir.'/'.$base_path;
150
  }
151
  }
171
  $match = '_'.$updraftplus->nonce."-".$whichone;
172
  while (false !== ($e = $d->read())) {
173
  if ('.' == $e || '..' == $e || !is_file($this->updraft_dir.'/'.$e)) continue;
174
+ # TODO: Make compatible with filenames which indicate increments
175
  $ziparchive_match = preg_match("/$match([0-9]+)?\.zip\.tmp\.([A-Za-z0-9]){6}?$/i", $e);
176
  $binzip_match = preg_match("/^zi([A-Za-z0-9]){6}$/", $e);
177
  if ($time_now-filemtime($this->updraft_dir.'/'.$e) < 30 && ($ziparchive_match || (0 != $updraftplus->current_resumption && $binzip_match))) {
199
  return false;
200
  } else {
201
  $itext = (empty($this->index)) ? '' : ($this->index+1);
202
+ # TODO: Make compatible with filenames which indicate increments
203
  $full_path = $this->updraft_dir.'/'.$backup_file_basename.'-'.$whichone.$itext.'.zip';
204
  if (file_exists($full_path.'.tmp')) {
205
  if (@filesize($full_path.'.tmp') === 0) {
225
  $updraftplus->clean_temporary_files('_'.$updraftplus->nonce."-$whichone", 0);
226
  }
227
 
228
+ # TODO: Make compatible with indication of increments in filename
229
  # Create the results array to send back (just the new ones, not any prior ones)
230
  $files_existing = array();
231
  $res_index = 0;
299
  $objname = "UpdraftPlus_BackupModule_${service}";
300
  if (class_exists($objname)) {
301
  $remote_obj = new $objname;
302
+ $pass_to_prune = $remote_obj->backup($sarray);
303
  $do_prune[$service] = array($remote_obj, $pass_to_prune);
304
  } else {
305
  $updraftplus->log("Unexpected error: no class '$objname' was found ($method_include)");
476
  if (!is_null($method_object)) $method_object->delete($dofiles, $object_passback);
477
  }
478
 
479
+ # The jobdata is passed in instead of fetched, because the live jobdata may now differ from that which should be reported on (e.g. an incremental run was subsequently scheduled)
480
+ public function send_results_email($final_message, $jobdata) {
481
 
482
  global $updraftplus;
483
 
486
  $sendmail_to = $updraftplus->just_one_email(UpdraftPlus_Options::get_updraft_option('updraft_email'));
487
  if (is_string($sendmail_to)) $sendmail_to = array($sendmail_to);
488
 
489
+ $backup_files =$jobdata['backup_files'];
490
+ $backup_db = $jobdata['backup_database'];
491
 
492
  if (is_array($backup_db)) $backup_db = $backup_db['wp'];
493
  if (is_array($backup_db)) $backup_db = $backup_db['status'];
494
 
495
+ $backup_type = ('backup' == $jobdata['job_type']) ? __('Full backup', 'updraftplus') : __('Incremental', 'updraftplus');
496
+
497
  if ('finished' == $backup_files && ('finished' == $backup_db || 'encrypted' == $backup_db)) {
498
+ $backup_contains = __("Files and database", 'updraftplus')." ($backup_type)";
499
  } elseif ('finished' == $backup_files) {
500
  $backup_contains = ($backup_db == "begun") ? __("Files (database backup has not completed)", 'updraftplus') : __("Files only (database was not part of this particular schedule)", 'updraftplus');
501
+ $backup_contains .= " ($backup_type)";
502
  } elseif ($backup_db == 'finished' || $backup_db == 'encrypted') {
503
  $backup_contains = ($backup_files == "begun") ? __("Database (files backup has not completed)", 'updraftplus') : __("Database only (files were not part of this particular schedule)", 'updraftplus');
504
  } else {
505
+ $updraftplus->log('Unknown/unexpected status: '.serialize($backup_files).'/'.serialize($backup_db));
506
  $backup_contains = __("Unknown/unexpected error - please raise a support request", 'updraftplus');
507
  }
508
 
528
  }
529
  $append_log.="\r\n";
530
  }
531
+ $warnings = (isset($jobdata['warnings'])) ? $jobdata['warnings'] : array();
532
  if (is_array($warnings) && count($warnings) >0) {
533
  $append_log .= __('Warnings encountered:', 'updraftplus')."\r\n";
534
  $attachments[0] = $updraftplus->logfile_name;
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));
566
  $feed .= "\r\n\r\n";
567
  }
568
 
569
+ $extra_messages = apply_filters('updraftplus_report_extramessages', array());
570
+ $extra_msg = '';
571
+ if (is_array($extra_messages)) {
572
+ foreach ($extra_messages as $msg) {
573
+ $extra_msg .= '<strong>'.$msg['key'].'</strong>: '.$msg['val']."\r\n";
574
+ }
575
+ }
576
+
577
+ $body = apply_filters('updraft_report_body',
578
+ __('Backup of:').' '.site_url()."\r\n".
579
+ "UpdraftPlus ".__('WordPress backup is complete','updraftplus').".\r\n".
580
+ __('Backup contains:','updraftplus')." $backup_contains\r\n".
581
+ __('Latest status:', 'updraftplus').' '.$final_message."\r\n".
582
+ $extra_msg.
583
+ "\r\n".
584
+ $feed.
585
+ $updraftplus->wordshell_random_advert(0)."\r\n".
586
+ $append_log,
587
+ $final_message, $backup_contains, $updraftplus->errors, $warnings, $jobdata);
588
 
589
  $this->attachments = apply_filters('updraft_report_attachments', $attachments);
590
 
623
 
624
  foreach (explode(',', $mailto) as $sendmail_addr) {
625
  $updraftplus->log("Sending email ('$backup_contains') report (attachments: ".count($attachments).", size: ".round($attach_size/1024, 1)." Kb) to: ".substr($sendmail_addr, 0, 5)."...");
626
+ try {
627
+ wp_mail(trim($sendmail_addr), $subject, $body);
628
+ } catch (Exception $e) {
629
+ $updraftplus->log("Exception occurred when sending mail (".get_class($e)."): ".$e->getMessage());
630
+ }
631
  }
632
  }
633
 
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;
732
  $index = (int)$this->job_file_entities[$youwhat]['index'];
733
  if (empty($index)) $index=0;
734
  $indextext = (0 == $index) ? '' : (1+$index);
735
+ # TODO: Make compatible with filenames which indicate increments
736
  $zip_file = $this->updraft_dir.'/'.$backup_file_basename.'-'.$youwhat.$indextext.'.zip';
737
 
738
  # Split needed?
739
+ $split_every = max((int)$updraftplus->jobdata_get('split_every'), 250);
740
  if (file_exists($zip_file) && filesize($zip_file) > $split_every*1048576) {
741
  $index++;
742
  $this->job_file_entities[$youwhat]['index'] = $index;
743
  $updraftplus->jobdata_set('job_file_entities', $this->job_file_entities);
744
  }
745
 
746
+ # TODO: Make compatible with filenames which indicate increments
747
  // Populate prior parts of array, if we're on a subsequent zip file
748
+ if ($index > 0) {
749
  for ($i=0; $i<$index; $i++) {
750
  $itext = (0 == $i) ? '' : ($i+1);
751
  $backup_array[$youwhat][$i] = $backup_file_basename.'-'.$youwhat.$itext.'.zip';
758
  if ('finished' == $job_status) {
759
  // Add the final part of the array
760
  if ($index >0) {
761
+ # TODO: Make compatible with filenames which indicate increments
762
  $fbase = $backup_file_basename.'-'.$youwhat.($index+1).'.zip';
763
  $z = $this->updraft_dir.'/'.$fbase;
764
  if (file_exists($z)) {
846
  foreach ($files as $file) $updraftplus->check_recent_modification($this->updraft_dir.'/'.$file);
847
  }
848
  } elseif ('begun' == $bfiles_status) {
849
+ $this->first_run = apply_filters('updraftplus_filerun_firstrun', 0);
850
+ if ($resumption_no > $this->first_run) {
851
  $updraftplus->log("Creation of backups of directories: had begun; will resume");
852
  } else {
853
  $updraftplus->log("Creation of backups of directories: beginning");
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)");
1052
 
1095
  $updraftplus->log("PHP function is disabled; abort expected: gzopen");
1096
  }
1097
 
1098
+ if (false === $this->backup_db_open($backup_final_file_name, true)) return false;
1099
 
1100
  $this->backup_db_header();
1101
 
1122
  }
1123
 
1124
  $updraftplus->log($file_base.'-db'.$this->whichdb_suffix.'.gz: finished writing out complete database file ('.round(filesize($backup_final_file_name)/1024,1).' Kb)');
1125
+ if (!$this->close()) {
1126
  $updraftplus->log('An error occurred whilst closing the final database file');
1127
  $updraftplus->log(__('An error occurred whilst closing the final database file', 'updraftplus'), 'error');
1128
  $errors++;
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') {
1360
  }
1361
  }
1362
 
1363
+ public function close() {
1364
+ return ($this->dbhandle_isgz) ? gzclose($this->dbhandle) : fclose($this->dbhandle);
 
 
 
 
1365
  }
1366
 
1367
  // Open a file, store its filehandle
1368
+ public function backup_db_open($file, $allow_gz = true) {
1369
  if (function_exists('gzopen') && $allow_gz == true) {
1370
  $this->dbhandle = @gzopen($file, 'w');
1371
  $this->dbhandle_isgz = true;
1381
  return $this->dbhandle;
1382
  }
1383
 
1384
+ public function stow($query_line) {
1385
  if ($this->dbhandle_isgz) {
1386
+ if(false == ($ret = @gzwrite($this->dbhandle, $query_line))) {
1387
  //$updraftplus->log(__('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg, 'error');
1388
  }
1389
  } else {
1390
+ if(false == ($ret = @fwrite($this->dbhandle, $query_line))) {
1391
  //$updraftplus->log(__('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg, 'error');
1392
  }
1393
  }
1394
+ return $ret;
1395
  }
1396
 
1397
  private function backup_db_header() {
1398
 
1399
+ @include(ABSPATH.WPINC.'/version.php');
1400
  global $wp_version, $updraftplus;
1401
 
1402
  $mysql_version = $this->wpdb_obj->db_version();
1455
  // $exclude is passed by reference so that we can remove elements as they are matched - saves time checking against already-dealt-with objects
1456
  private function makezip_recursive_add($fullpath, $use_path_when_storing, $original_fullpath, $startlevels = 1, &$exclude) {
1457
 
1458
+ # TODO: Make compatible with filenames which indicate increments
1459
  $zipfile = $this->zip_basename.(($this->index == 0) ? '' : ($this->index+1)).'.zip.tmp';
1460
 
1461
  global $updraftplus;
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
  }
1479
  return true;
1480
  }
1481
 
1482
+ $if_altered_since = $this->makezip_if_altered_since;
1483
+
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);
1491
+ #@touch($zipfile);
1492
+ } else {
1493
+ $this->zipfiles_skipped_notaltered[$fullpath] = $key;
1494
+ }
1495
  } else {
1496
  $updraftplus->log("$fullpath: unreadable file");
1497
  $updraftplus->log(sprintf(__("%s: unreadable file - could not be backed up (check the file permissions)", 'updraftplus'), $fullpath), 'warning');
1498
  }
1499
  } elseif (is_dir($fullpath)) {
1500
+ if (file_exists($fullpath.'/.donotbackup')) {
1501
+ $updraftplus->log("Skip directory (.donotbackup file found): $use_path_when_storing");
1502
+ return true;
1503
+ }
1504
  if (!isset($this->existing_files[$use_path_when_storing])) $this->zipfiles_dirbatched[] = $use_path_when_storing;
1505
  if (!$dir_handle = @opendir($fullpath)) {
1506
  $updraftplus->log("Failed to open directory: $fullpath");
1507
  $updraftplus->log(sprintf(__("Failed to open directory (check the file permissions): %s",'updraftplus'), $fullpath), 'error');
1508
  return false;
1509
  }
1510
+
1511
  while (false !== ($e = readdir($dir_handle))) {
1512
+ if ('.' != $e && '..' != $e ) {
1513
  if (is_link($fullpath.'/'.$e)) {
1514
  $deref = realpath($fullpath.'/'.$e);
1515
  if (is_file($deref)) {
1519
  $updraftplus->log("Entity excluded by configuration option: $use_stripped");
1520
  unset($exclude[$fkey]);
1521
  } else {
1522
+ $mtime = filemtime($deref);
1523
+ if ($mtime > 0 && $mtime > $if_altered_since) {
1524
+ $this->zipfiles_batched[$deref] = $use_path_when_storing.'/'.$e;
1525
+ $this->makezip_recursive_batchedbytes += @filesize($deref);
1526
+ #@touch($zipfile);
1527
+ } else {
1528
+ $this->zipfiles_skipped_notaltered[$deref] = $use_path_when_storing.'/'.$e;
1529
+ }
1530
  }
1531
  } else {
1532
  $updraftplus->log("$deref: unreadable file");
1542
  $updraftplus->log("Entity excluded by configuration option: $use_stripped");
1543
  unset($exclude[$fkey]);
1544
  } else {
1545
+ $mtime = filemtime($fullpath.'/'.$e);
1546
+ if ($mtime > 0 && $mtime > $if_altered_since) {
1547
+ $this->zipfiles_batched[$fullpath.'/'.$e] = $use_path_when_storing.'/'.$e;
1548
+ $this->makezip_recursive_batchedbytes += @filesize($fullpath.'/'.$e);
1549
+ } else {
1550
+ $this->zipfiles_skipped_notaltered[$fullpath.'/'.$e] = $use_path_when_storing.'/'.$e;
1551
+ }
1552
  }
1553
  } else {
1554
  $updraftplus->log("$fullpath/$e: unreadable file");
1565
  $updraftplus->log("Unexpected: path ($use_path_when_storing) fails both is_file() and is_dir()");
1566
  }
1567
 
1568
+ return true;
 
 
 
 
 
 
 
 
 
 
 
 
1569
 
1570
  }
1571
 
1577
 
1578
  $original_index = $this->index;
1579
 
1580
+ # TODO: Make compatible with filenames which indicate increments
1581
  $itext = (empty($this->index)) ? '' : ($this->index+1);
1582
  $destination_base = $backup_file_basename.'-'.$whichone.$itext.'.zip.tmp';
1583
  $destination = $this->updraft_dir.'/'.$destination_base;
1604
  // Enumerate existing files
1605
  for ($j=0; $j<=$this->index; $j++) {
1606
  $jtext = ($j == 0) ? '' : ($j+1);
1607
+ # TODO: Make compatible with filenames which indicate increments
1608
  $examine_zip = $this->updraft_dir.'/'.$backup_file_basename.'-'.$whichone.$jtext.'.zip'.(($j == $this->index) ? '.tmp' : '');
1609
 
1610
  // If the file exists, then we should grab its index of files inside, and sizes
1656
  $this->zipfiles_added_thisrun = 0;
1657
  $this->zipfiles_dirbatched = array();
1658
  $this->zipfiles_batched = array();
1659
+ $this->zipfiles_skipped_notaltered = array();
1660
  $this->zipfiles_lastwritetime = time();
 
1661
  $this->zip_basename = $this->updraft_dir.'/'.$backup_file_basename.'-'.$whichone;
1662
 
1663
+ if (!empty($do_bump_index)) $this->bump_index();
 
 
1664
 
1665
  $error_occurred = false;
1666
 
1672
  if (!is_array($source)) $source=array($source);
1673
 
1674
  $exclude = $updraftplus->get_exclude($whichone);
1675
+
1676
+ $files_enumerated_at = $updraftplus->jobdata_get('files_enumerated_at');
1677
+ if (!is_array($files_enumerated_at)) $files_enumerated_at = array();
1678
+ $files_enumerated_at[$whichone] = time();
1679
+ $updraftplus->jobdata_set('files_enumerated_at', $files_enumerated_at);
1680
+
1681
+ $this->makezip_if_altered_since = (is_array($this->altered_since)) ? (isset($this->altered_since[$whichone]) ? $this->altered_since[$whichone] : -1) : -1;
1682
+
1683
  foreach ($source as $element) {
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
  }
1699
  if (empty($do_bump_index)) @touch($destination);
1700
 
1701
  if (count($this->zipfiles_dirbatched)>0 || count($this->zipfiles_batched)>0) {
1702
+ $updraftplus->log(sprintf("Total entities for the zip file: %d directories, %d files (%d skipped as non-modified), %s Mb", count($this->zipfiles_dirbatched), count($this->zipfiles_batched), count($this->zipfiles_skipped_notaltered), round($this->makezip_recursive_batchedbytes/1048576,1)));
1703
  $add_them = $this->makezip_addfiles();
1704
  if (is_wp_error($add_them)) {
1705
  foreach ($add_them->get_error_messages() as $msg) {
1715
  # Reset these variables because the index may have changed since we began
1716
 
1717
  $itext = (empty($this->index)) ? '' : ($this->index+1);
1718
+ # TODO: Make compatible with filenames which indicate increments
1719
  $destination_base = $backup_file_basename.'-'.$whichone.$itext.'.zip.tmp';
1720
  $destination = $this->updraft_dir.'/'.$destination_base;
1721
 
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
 
1768
  # Used to detect requests to bump the size
1769
  $bump_index = false;
1770
 
1771
+ # TODO: Make compatible with filenames which indicate increments
1772
  $zipfile = $this->zip_basename.(($this->index == 0) ? '' : ($this->index+1)).'.zip.tmp';
1773
 
1774
  $maxzipbatch = $updraftplus->jobdata_get('maxzipbatch', 26214400);
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
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